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::def_id::DefId;
19 use rustc::middle::region::CodeExtent;
20 use rustc::middle::subst::Substs;
21 use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty};
24 use syntax::codemap::Span;
29 #[derive(Clone, Debug)]
30 pub struct ItemRef<'tcx> {
34 pub substs: &'tcx Substs<'tcx>,
37 #[derive(Clone, Debug)]
38 pub struct Block<'tcx> {
39 pub extent: CodeExtent,
41 pub stmts: Vec<StmtRef<'tcx>>,
42 pub expr: Option<ExprRef<'tcx>>,
45 #[derive(Clone, Debug)]
46 pub enum StmtRef<'tcx> {
47 Mirror(Box<Stmt<'tcx>>),
50 #[derive(Clone, Debug)]
51 pub struct Stmt<'tcx> {
53 pub kind: StmtKind<'tcx>,
56 #[derive(Clone, Debug)]
57 pub enum StmtKind<'tcx> {
59 /// scope for this statement; may be used as lifetime of temporaries
62 /// expression being evaluated in this statement
67 /// scope for variables bound in this let; covers this and
68 /// remaining statements in block
69 remainder_scope: CodeExtent,
71 /// scope for the initialization itself; might be used as
72 /// lifetime of temporaries
73 init_scope: CodeExtent,
76 pattern: Pattern<'tcx>,
78 /// let pat = <INIT> ...
79 initializer: Option<ExprRef<'tcx>>,
81 /// let pat = init; <STMTS>
82 stmts: Vec<StmtRef<'tcx>>,
86 // The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
87 // into instances of this `Expr` enum. This translation can be done
88 // basically as lazilly or as eagerly as desired: every recursive
89 // reference to an expression in this enum is an `ExprRef<'tcx>`, which
90 // may in turn be another instance of this enum (boxed), or else an
91 // untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
92 // shortlived. They are created by `Hair::to_expr`, analyzed and
93 // converted into MIR, and then discarded.
95 // If you compare `Expr` to the full compiler AST, you will see it is
96 // a good bit simpler. In fact, a number of the more straight-forward
97 // MIR simplifications are already done in the impl of `Hair`. For
98 // example, method calls and overloaded operators are absent: they are
99 // expected to be converted into `Expr::Call` instances.
100 #[derive(Clone, Debug)]
101 pub struct Expr<'tcx> {
102 // type of this expression
105 // lifetime of this expression if it should be spilled into a
106 // temporary; should be None only if in a constant context
107 pub temp_lifetime: Option<CodeExtent>,
109 // span of the expression in the source
112 // kind of expression
113 pub kind: ExprKind<'tcx>,
116 #[derive(Clone, Debug)]
117 pub enum ExprKind<'tcx> {
120 value: ExprRef<'tcx>,
123 value: ExprRef<'tcx>,
127 args: Vec<ExprRef<'tcx>>,
131 }, // NOT overloaded!
136 }, // NOT overloaded!
145 }, // NOT overloaded!
147 source: ExprRef<'tcx>,
150 source: ExprRef<'tcx>,
153 source: ExprRef<'tcx>,
156 source: ExprRef<'tcx>,
159 condition: ExprRef<'tcx>,
161 otherwise: Option<ExprRef<'tcx>>,
164 condition: Option<ExprRef<'tcx>>,
168 discriminant: ExprRef<'tcx>,
169 arms: Vec<Arm<'tcx>>,
172 body: &'tcx hir::Block,
189 index: ExprRef<'tcx>,
194 SelfRef, // first argument, used for self in a closure
200 borrow_kind: BorrowKind,
204 label: Option<CodeExtent>,
207 label: Option<CodeExtent>,
210 value: Option<ExprRef<'tcx>>,
213 value: ExprRef<'tcx>,
214 // FIXME(#29789): Add a separate hair::Constant<'tcx> so this could be more explicit about
215 // its contained data. Currently this should only contain expression of ExprKind::Literal
217 count: ExprRef<'tcx>,
220 fields: Vec<ExprRef<'tcx>>,
223 fields: Vec<ExprRef<'tcx>>,
226 adt_def: AdtDef<'tcx>,
227 variant_index: usize,
228 substs: &'tcx Substs<'tcx>,
229 fields: Vec<FieldExprRef<'tcx>>,
230 base: Option<ExprRef<'tcx>>,
234 substs: &'tcx ClosureSubsts<'tcx>,
235 upvars: Vec<ExprRef<'tcx>>,
238 literal: Literal<'tcx>,
241 asm: &'tcx hir::InlineAsm,
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 Arm<'tcx> {
259 pub patterns: Vec<Pattern<'tcx>>,
260 pub guard: Option<ExprRef<'tcx>>,
261 pub body: ExprRef<'tcx>,
264 #[derive(Clone, Debug)]
265 pub struct Pattern<'tcx> {
268 pub kind: Box<PatternKind<'tcx>>,
271 #[derive(Copy, Clone, Debug)]
277 #[derive(Clone, Debug)]
278 pub enum PatternKind<'tcx> {
281 // x, ref x, x @ P, etc
283 mutability: Mutability,
288 subpattern: Option<Pattern<'tcx>>,
291 // Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
293 adt_def: AdtDef<'tcx>,
294 variant_index: usize,
295 subpatterns: Vec<FieldPattern<'tcx>>,
298 // (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
300 subpatterns: Vec<FieldPattern<'tcx>>,
304 subpattern: Pattern<'tcx>,
305 }, // box P, &P, &mut P, etc
308 value: Literal<'tcx>,
316 // matches against a slice, checking the length and extracting elements
318 prefix: Vec<Pattern<'tcx>>,
319 slice: Option<Pattern<'tcx>>,
320 suffix: Vec<Pattern<'tcx>>,
323 // fixed match against an array, irrefutable
325 prefix: Vec<Pattern<'tcx>>,
326 slice: Option<Pattern<'tcx>>,
327 suffix: Vec<Pattern<'tcx>>,
331 #[derive(Copy, Clone, Debug)]
332 pub enum BindingMode {
334 ByRef(Region, BorrowKind),
337 #[derive(Clone, Debug)]
338 pub struct FieldPattern<'tcx> {
340 pub pattern: Pattern<'tcx>,
343 ///////////////////////////////////////////////////////////////////////////
346 /// "Mirroring" is the process of converting from a HIR type into one
347 /// of the HAIR types defined in this file. This is basically a "on
348 /// the fly" desugaring step that hides a lot of the messiness in the
349 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
352 /// Mirroring is gradual: when you mirror an outer expression like `e1
353 /// + e2`, the references to the inner expressions `e1` and `e2` are
354 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
355 /// mirrored. This allows a single AST node from the compiler to
356 /// expand into one or more Hair nodes, which lets the Hair nodes be
358 pub trait Mirror<'tcx> {
361 fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Self::Output;
364 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
365 type Output = Expr<'tcx>;
367 fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
372 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
373 type Output = Expr<'tcx>;
375 fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
377 ExprRef::Hair(h) => h.make_mirror(hir),
378 ExprRef::Mirror(m) => *m,
383 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
384 type Output = Stmt<'tcx>;
386 fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> {
391 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
392 type Output = Stmt<'tcx>;
394 fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Stmt<'tcx> {
396 StmtRef::Mirror(m) => *m,
401 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
402 type Output = Block<'tcx>;
404 fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Block<'tcx> {