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_const_math::ConstUsize;
18 use rustc::mir::{BinOp, BorrowKind, Field, Literal, UnOp};
19 use rustc::hir::def_id::DefId;
20 use rustc::middle::region::CodeExtent;
21 use rustc::ty::subst::Substs;
22 use rustc::ty::{self, AdtDef, ClosureSubsts, Region, Ty};
30 pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
32 #[derive(Clone, Debug)]
33 pub struct Block<'tcx> {
34 pub targeted_by_break: bool,
35 pub extent: CodeExtent<'tcx>,
37 pub stmts: Vec<StmtRef<'tcx>>,
38 pub expr: Option<ExprRef<'tcx>>,
41 #[derive(Clone, Debug)]
42 pub enum StmtRef<'tcx> {
43 Mirror(Box<Stmt<'tcx>>),
46 #[derive(Clone, Debug)]
47 pub struct Stmt<'tcx> {
49 pub kind: StmtKind<'tcx>,
52 #[derive(Clone, Debug)]
53 pub enum StmtKind<'tcx> {
55 /// scope for this statement; may be used as lifetime of temporaries
56 scope: CodeExtent<'tcx>,
58 /// expression being evaluated in this statement
63 /// scope for variables bound in this let; covers this and
64 /// remaining statements in block
65 remainder_scope: CodeExtent<'tcx>,
67 /// scope for the initialization itself; might be used as
68 /// lifetime of temporaries
69 init_scope: CodeExtent<'tcx>,
72 pattern: Pattern<'tcx>,
74 /// let pat = <INIT> ...
75 initializer: Option<ExprRef<'tcx>>
79 /// The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
80 /// into instances of this `Expr` enum. This translation can be done
81 /// basically as lazilly or as eagerly as desired: every recursive
82 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
83 /// may in turn be another instance of this enum (boxed), or else an
84 /// untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
85 /// shortlived. They are created by `Hair::to_expr`, analyzed and
86 /// converted into MIR, and then discarded.
88 /// If you compare `Expr` to the full compiler AST, you will see it is
89 /// a good bit simpler. In fact, a number of the more straight-forward
90 /// MIR simplifications are already done in the impl of `Hair`. For
91 /// example, method calls and overloaded operators are absent: they are
92 /// expected to be converted into `Expr::Call` instances.
93 #[derive(Clone, Debug)]
94 pub struct Expr<'tcx> {
95 /// type of this expression
98 /// lifetime of this expression if it should be spilled into a
99 /// temporary; should be None only if in a constant context
100 pub temp_lifetime: Option<CodeExtent<'tcx>>,
102 /// whether this temp lifetime was shrunk by #36082.
103 pub temp_lifetime_was_shrunk: bool,
105 /// span of the expression in the source
108 /// kind of expression
109 pub kind: ExprKind<'tcx>,
112 #[derive(Clone, Debug)]
113 pub enum ExprKind<'tcx> {
115 extent: CodeExtent<'tcx>,
116 value: ExprRef<'tcx>,
119 value: ExprRef<'tcx>,
120 value_extents: CodeExtent<'tcx>,
125 args: Vec<ExprRef<'tcx>>,
129 }, // NOT overloaded!
134 }, // NOT overloaded!
139 }, // NOT overloaded!
140 // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
144 }, // NOT overloaded!
146 source: ExprRef<'tcx>,
149 source: ExprRef<'tcx>,
150 }, // Use a lexpr to get a vexpr.
152 source: ExprRef<'tcx>,
155 source: ExprRef<'tcx>,
158 source: ExprRef<'tcx>,
161 source: ExprRef<'tcx>,
164 source: ExprRef<'tcx>,
167 condition: ExprRef<'tcx>,
169 otherwise: Option<ExprRef<'tcx>>,
172 condition: Option<ExprRef<'tcx>>,
176 discriminant: ExprRef<'tcx>,
177 arms: Vec<Arm<'tcx>>,
180 body: &'tcx hir::Block,
197 index: ExprRef<'tcx>,
202 /// first argument, used for self in a closure
208 region: Region<'tcx>,
209 borrow_kind: BorrowKind,
213 label: CodeExtent<'tcx>,
214 value: Option<ExprRef<'tcx>>,
217 label: CodeExtent<'tcx>,
220 value: Option<ExprRef<'tcx>>,
223 value: ExprRef<'tcx>,
227 fields: Vec<ExprRef<'tcx>>,
230 fields: Vec<ExprRef<'tcx>>,
233 adt_def: &'tcx AdtDef,
234 variant_index: usize,
235 substs: &'tcx Substs<'tcx>,
236 fields: Vec<FieldExprRef<'tcx>>,
237 base: Option<FruInfo<'tcx>>
241 substs: ClosureSubsts<'tcx>,
242 upvars: Vec<ExprRef<'tcx>>,
245 literal: Literal<'tcx>,
248 asm: &'tcx hir::InlineAsm,
249 outputs: Vec<ExprRef<'tcx>>,
250 inputs: Vec<ExprRef<'tcx>>
254 #[derive(Clone, Debug)]
255 pub enum ExprRef<'tcx> {
256 Hair(&'tcx hir::Expr),
257 Mirror(Box<Expr<'tcx>>),
260 #[derive(Clone, Debug)]
261 pub struct FieldExprRef<'tcx> {
263 pub expr: ExprRef<'tcx>,
266 #[derive(Clone, Debug)]
267 pub struct FruInfo<'tcx> {
268 pub base: ExprRef<'tcx>,
269 pub field_types: Vec<Ty<'tcx>>
272 #[derive(Clone, Debug)]
273 pub struct Arm<'tcx> {
274 pub patterns: Vec<Pattern<'tcx>>,
275 pub guard: Option<ExprRef<'tcx>>,
276 pub body: ExprRef<'tcx>,
279 #[derive(Copy, Clone, Debug)]
285 ///////////////////////////////////////////////////////////////////////////
288 /// "Mirroring" is the process of converting from a HIR type into one
289 /// of the HAIR types defined in this file. This is basically a "on
290 /// the fly" desugaring step that hides a lot of the messiness in the
291 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
294 /// Mirroring is gradual: when you mirror an outer expression like `e1
295 /// + e2`, the references to the inner expressions `e1` and `e2` are
296 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
297 /// mirrored. This allows a single AST node from the compiler to
298 /// expand into one or more Hair nodes, which lets the Hair nodes be
300 pub trait Mirror<'tcx> {
303 fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output;
306 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
307 type Output = Expr<'tcx>;
309 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
314 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
315 type Output = Expr<'tcx>;
317 fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
319 ExprRef::Hair(h) => h.make_mirror(hir),
320 ExprRef::Mirror(m) => *m,
325 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
326 type Output = Stmt<'tcx>;
328 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
333 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
334 type Output = Stmt<'tcx>;
336 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
338 StmtRef::Mirror(m) => *m,
343 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
344 type Output = Block<'tcx>;
346 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {