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,
19 use rustc::middle::const_eval::ConstVal;
20 use rustc::middle::def_id::DefId;
21 use rustc::middle::region::CodeExtent;
22 use rustc::middle::subst::Substs;
23 use rustc::middle::ty::{self, AdtDef, ClosureSubsts, Region, Ty};
26 use syntax::codemap::Span;
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>,
146 source: ExprRef<'tcx>,
149 source: ExprRef<'tcx>,
152 condition: ExprRef<'tcx>,
154 otherwise: Option<ExprRef<'tcx>>,
157 condition: Option<ExprRef<'tcx>>,
161 discriminant: ExprRef<'tcx>,
162 arms: Vec<Arm<'tcx>>,
165 body: &'tcx hir::Block,
182 index: ExprRef<'tcx>,
187 /// first argument, used for self in a closure
194 borrow_kind: BorrowKind,
198 label: Option<CodeExtent>,
201 label: Option<CodeExtent>,
204 value: Option<ExprRef<'tcx>>,
207 value: ExprRef<'tcx>,
208 count: TypedConstVal<'tcx>,
211 fields: Vec<ExprRef<'tcx>>,
214 fields: Vec<ExprRef<'tcx>>,
217 adt_def: AdtDef<'tcx>,
218 variant_index: usize,
219 substs: &'tcx Substs<'tcx>,
220 fields: Vec<FieldExprRef<'tcx>>,
221 base: Option<FruInfo<'tcx>>
225 substs: &'tcx ClosureSubsts<'tcx>,
226 upvars: Vec<ExprRef<'tcx>>,
229 literal: Literal<'tcx>,
232 asm: &'tcx hir::InlineAsm,
233 outputs: Vec<ExprRef<'tcx>>,
234 inputs: Vec<ExprRef<'tcx>>
238 #[derive(Clone, Debug)]
239 pub enum ExprRef<'tcx> {
240 Hair(&'tcx hir::Expr),
241 Mirror(Box<Expr<'tcx>>),
244 #[derive(Clone, Debug)]
245 pub struct FieldExprRef<'tcx> {
247 pub expr: ExprRef<'tcx>,
250 #[derive(Clone, Debug)]
251 pub struct FruInfo<'tcx> {
252 pub base: ExprRef<'tcx>,
253 pub field_types: Vec<Ty<'tcx>>
256 #[derive(Clone, Debug)]
257 pub struct Arm<'tcx> {
258 pub patterns: Vec<Pattern<'tcx>>,
259 pub guard: Option<ExprRef<'tcx>>,
260 pub body: ExprRef<'tcx>,
263 #[derive(Clone, Debug)]
264 pub struct Pattern<'tcx> {
267 pub kind: Box<PatternKind<'tcx>>,
270 #[derive(Copy, Clone, Debug)]
276 #[derive(Clone, Debug)]
277 pub enum PatternKind<'tcx> {
280 /// x, ref x, x @ P, etc
282 mutability: Mutability,
287 subpattern: Option<Pattern<'tcx>>,
290 /// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
292 adt_def: AdtDef<'tcx>,
293 variant_index: usize,
294 subpatterns: Vec<FieldPattern<'tcx>>,
297 /// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
299 subpatterns: Vec<FieldPattern<'tcx>>,
302 /// box P, &P, &mut P, etc
304 subpattern: Pattern<'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> {