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::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp, ItemKind};
18 use rustc::middle::const_eval::ConstVal;
19 use rustc::middle::def_id::DefId;
20 use rustc::middle::region::CodeExtent;
21 use rustc::middle::subst::Substs;
22 use rustc::middle::ty::{self, AdtDef, ClosureSubsts, Region, Ty};
25 use syntax::codemap::Span;
30 #[derive(Clone, Debug)]
31 pub struct ItemRef<'tcx> {
35 pub substs: &'tcx Substs<'tcx>,
38 #[derive(Clone, Debug)]
39 pub struct Block<'tcx> {
40 pub extent: CodeExtent,
42 pub stmts: Vec<StmtRef<'tcx>>,
43 pub expr: Option<ExprRef<'tcx>>,
46 #[derive(Clone, Debug)]
47 pub enum StmtRef<'tcx> {
48 Mirror(Box<Stmt<'tcx>>),
51 #[derive(Clone, Debug)]
52 pub struct Stmt<'tcx> {
54 pub kind: StmtKind<'tcx>,
57 #[derive(Clone, Debug)]
58 pub enum StmtKind<'tcx> {
60 /// scope for this statement; may be used as lifetime of temporaries
63 /// expression being evaluated in this statement
68 /// scope for variables bound in this let; covers this and
69 /// remaining statements in block
70 remainder_scope: CodeExtent,
72 /// scope for the initialization itself; might be used as
73 /// lifetime of temporaries
74 init_scope: CodeExtent,
77 pattern: Pattern<'tcx>,
79 /// let pat = <INIT> ...
80 initializer: Option<ExprRef<'tcx>>,
82 /// let pat = init; <STMTS>
83 stmts: Vec<StmtRef<'tcx>>,
87 // The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
88 // into instances of this `Expr` enum. This translation can be done
89 // basically as lazilly or as eagerly as desired: every recursive
90 // reference to an expression in this enum is an `ExprRef<'tcx>`, which
91 // may in turn be another instance of this enum (boxed), or else an
92 // untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
93 // shortlived. They are created by `Hair::to_expr`, analyzed and
94 // converted into MIR, and then discarded.
96 // If you compare `Expr` to the full compiler AST, you will see it is
97 // a good bit simpler. In fact, a number of the more straight-forward
98 // MIR simplifications are already done in the impl of `Hair`. For
99 // example, method calls and overloaded operators are absent: they are
100 // expected to be converted into `Expr::Call` instances.
101 #[derive(Clone, Debug)]
102 pub struct Expr<'tcx> {
103 // type of this expression
106 // lifetime of this expression if it should be spilled into a
107 // temporary; should be None only if in a constant context
108 pub temp_lifetime: Option<CodeExtent>,
110 // span of the expression in the source
113 // kind of expression
114 pub kind: ExprKind<'tcx>,
117 #[derive(Clone, Debug)]
118 pub enum ExprKind<'tcx> {
121 value: ExprRef<'tcx>,
124 value: ExprRef<'tcx>,
129 args: Vec<ExprRef<'tcx>>,
133 }, // NOT overloaded!
138 }, // NOT overloaded!
147 }, // NOT overloaded!
149 source: ExprRef<'tcx>,
152 source: ExprRef<'tcx>,
155 source: ExprRef<'tcx>,
158 source: ExprRef<'tcx>,
161 condition: ExprRef<'tcx>,
163 otherwise: Option<ExprRef<'tcx>>,
166 condition: Option<ExprRef<'tcx>>,
170 discriminant: ExprRef<'tcx>,
171 arms: Vec<Arm<'tcx>>,
174 body: &'tcx hir::Block,
191 index: ExprRef<'tcx>,
196 SelfRef, // first argument, used for self in a closure
202 borrow_kind: BorrowKind,
206 label: Option<CodeExtent>,
209 label: Option<CodeExtent>,
212 value: Option<ExprRef<'tcx>>,
215 value: ExprRef<'tcx>,
216 // FIXME(#29789): Add a separate hair::Constant<'tcx> so this could be more explicit about
217 // its contained data. Currently this should only contain expression of ExprKind::Literal
219 count: ExprRef<'tcx>,
222 fields: Vec<ExprRef<'tcx>>,
225 fields: Vec<ExprRef<'tcx>>,
228 adt_def: AdtDef<'tcx>,
229 variant_index: usize,
230 substs: &'tcx Substs<'tcx>,
231 fields: Vec<FieldExprRef<'tcx>>,
232 base: Option<ExprRef<'tcx>>,
236 substs: &'tcx ClosureSubsts<'tcx>,
237 upvars: Vec<ExprRef<'tcx>>,
240 literal: Literal<'tcx>,
243 asm: &'tcx hir::InlineAsm,
247 #[derive(Clone, Debug)]
248 pub enum ExprRef<'tcx> {
249 Hair(&'tcx hir::Expr),
250 Mirror(Box<Expr<'tcx>>),
253 #[derive(Clone, Debug)]
254 pub struct FieldExprRef<'tcx> {
256 pub expr: ExprRef<'tcx>,
259 #[derive(Clone, Debug)]
260 pub struct Arm<'tcx> {
261 pub patterns: Vec<Pattern<'tcx>>,
262 pub guard: Option<ExprRef<'tcx>>,
263 pub body: ExprRef<'tcx>,
266 #[derive(Clone, Debug)]
267 pub struct Pattern<'tcx> {
270 pub kind: Box<PatternKind<'tcx>>,
273 #[derive(Copy, Clone, Debug)]
279 #[derive(Clone, Debug)]
280 pub enum PatternKind<'tcx> {
283 // x, ref x, x @ P, etc
285 mutability: Mutability,
290 subpattern: Option<Pattern<'tcx>>,
293 // Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
295 adt_def: AdtDef<'tcx>,
296 variant_index: usize,
297 subpatterns: Vec<FieldPattern<'tcx>>,
300 // (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
302 subpatterns: Vec<FieldPattern<'tcx>>,
306 subpattern: Pattern<'tcx>,
307 }, // box P, &P, &mut P, etc
318 // matches against a slice, checking the length and extracting elements
320 prefix: Vec<Pattern<'tcx>>,
321 slice: Option<Pattern<'tcx>>,
322 suffix: Vec<Pattern<'tcx>>,
325 // fixed match against an array, irrefutable
327 prefix: Vec<Pattern<'tcx>>,
328 slice: Option<Pattern<'tcx>>,
329 suffix: Vec<Pattern<'tcx>>,
333 #[derive(Copy, Clone, Debug)]
334 pub enum BindingMode {
336 ByRef(Region, BorrowKind),
339 #[derive(Clone, Debug)]
340 pub struct FieldPattern<'tcx> {
342 pub pattern: Pattern<'tcx>,
345 ///////////////////////////////////////////////////////////////////////////
348 /// "Mirroring" is the process of converting from a HIR type into one
349 /// of the HAIR types defined in this file. This is basically a "on
350 /// the fly" desugaring step that hides a lot of the messiness in the
351 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
354 /// Mirroring is gradual: when you mirror an outer expression like `e1
355 /// + e2`, the references to the inner expressions `e1` and `e2` are
356 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
357 /// mirrored. This allows a single AST node from the compiler to
358 /// expand into one or more Hair nodes, which lets the Hair nodes be
360 pub trait Mirror<'tcx> {
363 fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Self::Output;
366 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
367 type Output = Expr<'tcx>;
369 fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
374 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
375 type Output = Expr<'tcx>;
377 fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
379 ExprRef::Hair(h) => h.make_mirror(hir),
380 ExprRef::Mirror(m) => *m,
385 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
386 type Output = Stmt<'tcx>;
388 fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> {
393 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
394 type Output = Stmt<'tcx>;
396 fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Stmt<'tcx> {
398 StmtRef::Mirror(m) => *m,
403 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
404 type Output = Block<'tcx>;
406 fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Block<'tcx> {