]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/mod.rs
intern CodeExtents
[rust.git] / src / librustc_mir / hair / mod.rs
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.
4 //
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.
10
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
15 //! structures.
16
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};
23 use rustc::hir;
24 use syntax::ast;
25 use syntax_pos::Span;
26 use self::cx::Cx;
27
28 pub mod cx;
29
30 pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
31
32 #[derive(Clone, Debug)]
33 pub struct Block<'tcx> {
34     pub targeted_by_break: bool,
35     pub extent: CodeExtent<'tcx>,
36     pub span: Span,
37     pub stmts: Vec<StmtRef<'tcx>>,
38     pub expr: Option<ExprRef<'tcx>>,
39 }
40
41 #[derive(Clone, Debug)]
42 pub enum StmtRef<'tcx> {
43     Mirror(Box<Stmt<'tcx>>),
44 }
45
46 #[derive(Clone, Debug)]
47 pub struct Stmt<'tcx> {
48     pub span: Span,
49     pub kind: StmtKind<'tcx>,
50 }
51
52 #[derive(Clone, Debug)]
53 pub enum StmtKind<'tcx> {
54     Expr {
55         /// scope for this statement; may be used as lifetime of temporaries
56         scope: CodeExtent<'tcx>,
57
58         /// expression being evaluated in this statement
59         expr: ExprRef<'tcx>,
60     },
61
62     Let {
63         /// scope for variables bound in this let; covers this and
64         /// remaining statements in block
65         remainder_scope: CodeExtent<'tcx>,
66
67         /// scope for the initialization itself; might be used as
68         /// lifetime of temporaries
69         init_scope: CodeExtent<'tcx>,
70
71         /// let <PAT> = ...
72         pattern: Pattern<'tcx>,
73
74         /// let pat = <INIT> ...
75         initializer: Option<ExprRef<'tcx>>
76     },
77 }
78
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.
87 ///
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
96     pub ty: Ty<'tcx>,
97
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>>,
101
102     /// whether this temp lifetime was shrunk by #36082.
103     pub temp_lifetime_was_shrunk: bool,
104
105     /// span of the expression in the source
106     pub span: Span,
107
108     /// kind of expression
109     pub kind: ExprKind<'tcx>,
110 }
111
112 #[derive(Clone, Debug)]
113 pub enum ExprKind<'tcx> {
114     Scope {
115         extent: CodeExtent<'tcx>,
116         value: ExprRef<'tcx>,
117     },
118     Box {
119         value: ExprRef<'tcx>,
120         value_extents: CodeExtent<'tcx>,
121     },
122     Call {
123         ty: ty::Ty<'tcx>,
124         fun: ExprRef<'tcx>,
125         args: Vec<ExprRef<'tcx>>,
126     },
127     Deref {
128         arg: ExprRef<'tcx>,
129     }, // NOT overloaded!
130     Binary {
131         op: BinOp,
132         lhs: ExprRef<'tcx>,
133         rhs: ExprRef<'tcx>,
134     }, // NOT overloaded!
135     LogicalOp {
136         op: LogicalOp,
137         lhs: ExprRef<'tcx>,
138         rhs: ExprRef<'tcx>,
139     }, // NOT overloaded!
140        // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
141     Unary {
142         op: UnOp,
143         arg: ExprRef<'tcx>,
144     }, // NOT overloaded!
145     Cast {
146         source: ExprRef<'tcx>,
147     },
148     Use {
149         source: ExprRef<'tcx>,
150     }, // Use a lexpr to get a vexpr.
151     NeverToAny {
152         source: ExprRef<'tcx>,
153     },
154     ReifyFnPointer {
155         source: ExprRef<'tcx>,
156     },
157     ClosureFnPointer {
158         source: ExprRef<'tcx>,
159     },
160     UnsafeFnPointer {
161         source: ExprRef<'tcx>,
162     },
163     Unsize {
164         source: ExprRef<'tcx>,
165     },
166     If {
167         condition: ExprRef<'tcx>,
168         then: ExprRef<'tcx>,
169         otherwise: Option<ExprRef<'tcx>>,
170     },
171     Loop {
172         condition: Option<ExprRef<'tcx>>,
173         body: ExprRef<'tcx>,
174     },
175     Match {
176         discriminant: ExprRef<'tcx>,
177         arms: Vec<Arm<'tcx>>,
178     },
179     Block {
180         body: &'tcx hir::Block,
181     },
182     Assign {
183         lhs: ExprRef<'tcx>,
184         rhs: ExprRef<'tcx>,
185     },
186     AssignOp {
187         op: BinOp,
188         lhs: ExprRef<'tcx>,
189         rhs: ExprRef<'tcx>,
190     },
191     Field {
192         lhs: ExprRef<'tcx>,
193         name: Field,
194     },
195     Index {
196         lhs: ExprRef<'tcx>,
197         index: ExprRef<'tcx>,
198     },
199     VarRef {
200         id: ast::NodeId,
201     },
202     /// first argument, used for self in a closure
203     SelfRef,
204     StaticRef {
205         id: DefId,
206     },
207     Borrow {
208         region: Region<'tcx>,
209         borrow_kind: BorrowKind,
210         arg: ExprRef<'tcx>,
211     },
212     Break {
213         label: CodeExtent<'tcx>,
214         value: Option<ExprRef<'tcx>>,
215     },
216     Continue {
217         label: CodeExtent<'tcx>,
218     },
219     Return {
220         value: Option<ExprRef<'tcx>>,
221     },
222     Repeat {
223         value: ExprRef<'tcx>,
224         count: ConstUsize,
225     },
226     Array {
227         fields: Vec<ExprRef<'tcx>>,
228     },
229     Tuple {
230         fields: Vec<ExprRef<'tcx>>,
231     },
232     Adt {
233         adt_def: &'tcx AdtDef,
234         variant_index: usize,
235         substs: &'tcx Substs<'tcx>,
236         fields: Vec<FieldExprRef<'tcx>>,
237         base: Option<FruInfo<'tcx>>
238     },
239     Closure {
240         closure_id: DefId,
241         substs: ClosureSubsts<'tcx>,
242         upvars: Vec<ExprRef<'tcx>>,
243     },
244     Literal {
245         literal: Literal<'tcx>,
246     },
247     InlineAsm {
248         asm: &'tcx hir::InlineAsm,
249         outputs: Vec<ExprRef<'tcx>>,
250         inputs: Vec<ExprRef<'tcx>>
251     },
252 }
253
254 #[derive(Clone, Debug)]
255 pub enum ExprRef<'tcx> {
256     Hair(&'tcx hir::Expr),
257     Mirror(Box<Expr<'tcx>>),
258 }
259
260 #[derive(Clone, Debug)]
261 pub struct FieldExprRef<'tcx> {
262     pub name: Field,
263     pub expr: ExprRef<'tcx>,
264 }
265
266 #[derive(Clone, Debug)]
267 pub struct FruInfo<'tcx> {
268     pub base: ExprRef<'tcx>,
269     pub field_types: Vec<Ty<'tcx>>
270 }
271
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>,
277 }
278
279 #[derive(Copy, Clone, Debug)]
280 pub enum LogicalOp {
281     And,
282     Or,
283 }
284
285 ///////////////////////////////////////////////////////////////////////////
286 // The Mirror trait
287
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
292 /// `Expr<'tcx>`.
293 ///
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
299 /// simpler.
300 pub trait Mirror<'tcx> {
301     type Output;
302
303     fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output;
304 }
305
306 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
307     type Output = Expr<'tcx>;
308
309     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
310         self
311     }
312 }
313
314 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
315     type Output = Expr<'tcx>;
316
317     fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
318         match self {
319             ExprRef::Hair(h) => h.make_mirror(hir),
320             ExprRef::Mirror(m) => *m,
321         }
322     }
323 }
324
325 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
326     type Output = Stmt<'tcx>;
327
328     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
329         self
330     }
331 }
332
333 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
334     type Output = Stmt<'tcx>;
335
336     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
337         match self {
338             StmtRef::Mirror(m) => *m,
339         }
340     }
341 }
342
343 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
344     type Output = Block<'tcx>;
345
346     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {
347         self
348     }
349 }