1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! The MIR is translated from some high-level abstract IR
12 //! (HAIR). This section defines the HAIR along with a trait for
13 //! accessing it. The intention is to allow MIR construction to be
14 //! unit-tested and separated from the Rust source and compiler data
17 use rustc::mir::{BinOp, BorrowKind, Field, Literal, UnOp, TypedConstVal};
18 use rustc::hir::def_id::DefId;
19 use rustc::middle::region::CodeExtent;
20 use rustc::ty::subst::Substs;
21 use rustc::ty::{self, AdtDef, ClosureSubsts, Region, Ty};
29 pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
31 #[derive(Clone, Debug)]
32 pub struct Block<'tcx> {
33 pub extent: CodeExtent,
35 pub stmts: Vec<StmtRef<'tcx>>,
36 pub expr: Option<ExprRef<'tcx>>,
39 #[derive(Clone, Debug)]
40 pub enum StmtRef<'tcx> {
41 Mirror(Box<Stmt<'tcx>>),
44 #[derive(Clone, Debug)]
45 pub struct Stmt<'tcx> {
47 pub kind: StmtKind<'tcx>,
50 #[derive(Clone, Debug)]
51 pub enum StmtKind<'tcx> {
53 /// scope for this statement; may be used as lifetime of temporaries
56 /// expression being evaluated in this statement
61 /// scope for variables bound in this let; covers this and
62 /// remaining statements in block
63 remainder_scope: CodeExtent,
65 /// scope for the initialization itself; might be used as
66 /// lifetime of temporaries
67 init_scope: CodeExtent,
70 pattern: Pattern<'tcx>,
72 /// let pat = <INIT> ...
73 initializer: Option<ExprRef<'tcx>>
77 /// The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
78 /// into instances of this `Expr` enum. This translation can be done
79 /// basically as lazilly or as eagerly as desired: every recursive
80 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
81 /// may in turn be another instance of this enum (boxed), or else an
82 /// untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
83 /// shortlived. They are created by `Hair::to_expr`, analyzed and
84 /// converted into MIR, and then discarded.
86 /// If you compare `Expr` to the full compiler AST, you will see it is
87 /// a good bit simpler. In fact, a number of the more straight-forward
88 /// MIR simplifications are already done in the impl of `Hair`. For
89 /// example, method calls and overloaded operators are absent: they are
90 /// expected to be converted into `Expr::Call` instances.
91 #[derive(Clone, Debug)]
92 pub struct Expr<'tcx> {
93 /// type of this expression
96 /// lifetime of this expression if it should be spilled into a
97 /// temporary; should be None only if in a constant context
98 pub temp_lifetime: Option<CodeExtent>,
100 /// span of the expression in the source
103 /// kind of expression
104 pub kind: ExprKind<'tcx>,
107 #[derive(Clone, Debug)]
108 pub enum ExprKind<'tcx> {
111 value: ExprRef<'tcx>,
114 value: ExprRef<'tcx>,
115 value_extents: CodeExtent,
120 args: Vec<ExprRef<'tcx>>,
124 }, // NOT overloaded!
129 }, // NOT overloaded!
138 }, // NOT overloaded!
140 source: ExprRef<'tcx>,
143 source: ExprRef<'tcx>,
144 }, // Use a lexpr to get a vexpr.
146 source: ExprRef<'tcx>,
149 source: ExprRef<'tcx>,
152 source: ExprRef<'tcx>,
155 source: ExprRef<'tcx>,
158 condition: ExprRef<'tcx>,
160 otherwise: Option<ExprRef<'tcx>>,
163 condition: Option<ExprRef<'tcx>>,
167 discriminant: ExprRef<'tcx>,
168 arms: Vec<Arm<'tcx>>,
171 body: &'tcx hir::Block,
188 index: ExprRef<'tcx>,
193 /// first argument, used for self in a closure
199 region: &'tcx Region,
200 borrow_kind: BorrowKind,
204 label: Option<CodeExtent>,
205 value: Option<ExprRef<'tcx>>,
208 label: Option<CodeExtent>,
211 value: Option<ExprRef<'tcx>>,
214 value: ExprRef<'tcx>,
215 count: TypedConstVal<'tcx>,
218 fields: Vec<ExprRef<'tcx>>,
221 fields: Vec<ExprRef<'tcx>>,
224 adt_def: &'tcx AdtDef,
225 variant_index: usize,
226 substs: &'tcx Substs<'tcx>,
227 fields: Vec<FieldExprRef<'tcx>>,
228 base: Option<FruInfo<'tcx>>
232 substs: ClosureSubsts<'tcx>,
233 upvars: Vec<ExprRef<'tcx>>,
236 literal: Literal<'tcx>,
239 asm: &'tcx hir::InlineAsm,
240 outputs: Vec<ExprRef<'tcx>>,
241 inputs: Vec<ExprRef<'tcx>>
245 #[derive(Clone, Debug)]
246 pub enum ExprRef<'tcx> {
247 Hair(&'tcx hir::Expr),
248 Mirror(Box<Expr<'tcx>>),
251 #[derive(Clone, Debug)]
252 pub struct FieldExprRef<'tcx> {
254 pub expr: ExprRef<'tcx>,
257 #[derive(Clone, Debug)]
258 pub struct FruInfo<'tcx> {
259 pub base: ExprRef<'tcx>,
260 pub field_types: Vec<Ty<'tcx>>
263 #[derive(Clone, Debug)]
264 pub struct Arm<'tcx> {
265 pub patterns: Vec<Pattern<'tcx>>,
266 pub guard: Option<ExprRef<'tcx>>,
267 pub body: ExprRef<'tcx>,
270 #[derive(Copy, Clone, Debug)]
276 ///////////////////////////////////////////////////////////////////////////
279 /// "Mirroring" is the process of converting from a HIR type into one
280 /// of the HAIR types defined in this file. This is basically a "on
281 /// the fly" desugaring step that hides a lot of the messiness in the
282 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
285 /// Mirroring is gradual: when you mirror an outer expression like `e1
286 /// + e2`, the references to the inner expressions `e1` and `e2` are
287 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
288 /// mirrored. This allows a single AST node from the compiler to
289 /// expand into one or more Hair nodes, which lets the Hair nodes be
291 pub trait Mirror<'tcx> {
294 fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output;
297 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
298 type Output = Expr<'tcx>;
300 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
305 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
306 type Output = Expr<'tcx>;
308 fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
310 ExprRef::Hair(h) => h.make_mirror(hir),
311 ExprRef::Mirror(m) => *m,
316 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
317 type Output = Stmt<'tcx>;
319 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
324 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
325 type Output = Stmt<'tcx>;
327 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
329 StmtRef::Mirror(m) => *m,
334 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
335 type Output = Block<'tcx>;
337 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {