]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/mod.rs
Rollup merge of #55377 - goffrie:patch-2, r=joshtriplett
[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 built 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::mir::{BinOp, BorrowKind, UserTypeAnnotation, Field, UnOp};
18 use rustc::hir::def_id::DefId;
19 use rustc::middle::region;
20 use rustc::ty::subst::Substs;
21 use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const};
22 use rustc::hir;
23 use syntax::ast;
24 use syntax_pos::Span;
25 use self::cx::Cx;
26
27 pub mod cx;
28
29 pub mod pattern;
30 pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
31 pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
32
33 mod util;
34
35 #[derive(Copy, Clone, Debug)]
36 pub enum LintLevel {
37     Inherited,
38     Explicit(ast::NodeId)
39 }
40
41 impl LintLevel {
42     pub fn is_explicit(self) -> bool {
43         match self {
44             LintLevel::Inherited => false,
45             LintLevel::Explicit(_) => true
46         }
47     }
48 }
49
50 #[derive(Clone, Debug)]
51 pub struct Block<'tcx> {
52     pub targeted_by_break: bool,
53     pub region_scope: region::Scope,
54     pub opt_destruction_scope: Option<region::Scope>,
55     pub span: Span,
56     pub stmts: Vec<StmtRef<'tcx>>,
57     pub expr: Option<ExprRef<'tcx>>,
58     pub safety_mode: BlockSafety,
59 }
60
61 #[derive(Copy, Clone, Debug)]
62 pub enum BlockSafety {
63     Safe,
64     ExplicitUnsafe(ast::NodeId),
65     PushUnsafe,
66     PopUnsafe
67 }
68
69 #[derive(Clone, Debug)]
70 pub enum StmtRef<'tcx> {
71     Mirror(Box<Stmt<'tcx>>),
72 }
73
74 #[derive(Clone, Debug)]
75 pub struct Stmt<'tcx> {
76     pub kind: StmtKind<'tcx>,
77     pub opt_destruction_scope: Option<region::Scope>,
78 }
79
80 #[derive(Clone, Debug)]
81 pub enum StmtKind<'tcx> {
82     Expr {
83         /// scope for this statement; may be used as lifetime of temporaries
84         scope: region::Scope,
85
86         /// expression being evaluated in this statement
87         expr: ExprRef<'tcx>,
88     },
89
90     Let {
91         /// scope for variables bound in this let; covers this and
92         /// remaining statements in block
93         remainder_scope: region::Scope,
94
95         /// scope for the initialization itself; might be used as
96         /// lifetime of temporaries
97         init_scope: region::Scope,
98
99         /// `let <PAT> = ...`
100         ///
101         /// if a type is included, it is added as an ascription pattern
102         pattern: Pattern<'tcx>,
103
104         /// let pat: ty = <INIT> ...
105         initializer: Option<ExprRef<'tcx>>,
106
107         /// the lint level for this let-statement
108         lint_level: LintLevel,
109     },
110 }
111
112 /// The Hair trait implementor lowers their expressions (`&'tcx H::Expr`)
113 /// into instances of this `Expr` enum. This lowering can be done
114 /// basically as lazily or as eagerly as desired: every recursive
115 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
116 /// may in turn be another instance of this enum (boxed), or else an
117 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
118 /// shortlived. They are created by `Hair::to_expr`, analyzed and
119 /// converted into MIR, and then discarded.
120 ///
121 /// If you compare `Expr` to the full compiler AST, you will see it is
122 /// a good bit simpler. In fact, a number of the more straight-forward
123 /// MIR simplifications are already done in the impl of `Hair`. For
124 /// example, method calls and overloaded operators are absent: they are
125 /// expected to be converted into `Expr::Call` instances.
126 #[derive(Clone, Debug)]
127 pub struct Expr<'tcx> {
128     /// type of this expression
129     pub ty: Ty<'tcx>,
130
131     /// lifetime of this expression if it should be spilled into a
132     /// temporary; should be None only if in a constant context
133     pub temp_lifetime: Option<region::Scope>,
134
135     /// span of the expression in the source
136     pub span: Span,
137
138     /// kind of expression
139     pub kind: ExprKind<'tcx>,
140 }
141
142 #[derive(Clone, Debug)]
143 pub enum ExprKind<'tcx> {
144     Scope {
145         region_scope: region::Scope,
146         lint_level: LintLevel,
147         value: ExprRef<'tcx>,
148     },
149     Box {
150         value: ExprRef<'tcx>,
151     },
152     Call {
153         ty: Ty<'tcx>,
154         fun: ExprRef<'tcx>,
155         args: Vec<ExprRef<'tcx>>,
156         // Whether this is from a call in HIR, rather than from an overloaded
157         // operator. True for overloaded function call.
158         from_hir_call: bool,
159     },
160     Deref {
161         arg: ExprRef<'tcx>,
162     }, // NOT overloaded!
163     Binary {
164         op: BinOp,
165         lhs: ExprRef<'tcx>,
166         rhs: ExprRef<'tcx>,
167     }, // NOT overloaded!
168     LogicalOp {
169         op: LogicalOp,
170         lhs: ExprRef<'tcx>,
171         rhs: ExprRef<'tcx>,
172     }, // NOT overloaded!
173        // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
174     Unary {
175         op: UnOp,
176         arg: ExprRef<'tcx>,
177     }, // NOT overloaded!
178     Cast {
179         source: ExprRef<'tcx>,
180     },
181     Use {
182         source: ExprRef<'tcx>,
183     }, // Use a lexpr to get a vexpr.
184     NeverToAny {
185         source: ExprRef<'tcx>,
186     },
187     ReifyFnPointer {
188         source: ExprRef<'tcx>,
189     },
190     ClosureFnPointer {
191         source: ExprRef<'tcx>,
192     },
193     UnsafeFnPointer {
194         source: ExprRef<'tcx>,
195     },
196     Unsize {
197         source: ExprRef<'tcx>,
198     },
199     If {
200         condition: ExprRef<'tcx>,
201         then: ExprRef<'tcx>,
202         otherwise: Option<ExprRef<'tcx>>,
203     },
204     Loop {
205         condition: Option<ExprRef<'tcx>>,
206         body: ExprRef<'tcx>,
207     },
208     Match {
209         discriminant: ExprRef<'tcx>,
210         arms: Vec<Arm<'tcx>>,
211     },
212     Block {
213         body: &'tcx hir::Block,
214     },
215     Assign {
216         lhs: ExprRef<'tcx>,
217         rhs: ExprRef<'tcx>,
218     },
219     AssignOp {
220         op: BinOp,
221         lhs: ExprRef<'tcx>,
222         rhs: ExprRef<'tcx>,
223     },
224     Field {
225         lhs: ExprRef<'tcx>,
226         name: Field,
227     },
228     Index {
229         lhs: ExprRef<'tcx>,
230         index: ExprRef<'tcx>,
231     },
232     VarRef {
233         id: ast::NodeId,
234     },
235     /// first argument, used for self in a closure
236     SelfRef,
237     StaticRef {
238         id: DefId,
239     },
240     Borrow {
241         region: Region<'tcx>,
242         borrow_kind: BorrowKind,
243         arg: ExprRef<'tcx>,
244     },
245     Break {
246         label: region::Scope,
247         value: Option<ExprRef<'tcx>>,
248     },
249     Continue {
250         label: region::Scope,
251     },
252     Return {
253         value: Option<ExprRef<'tcx>>,
254     },
255     Repeat {
256         value: ExprRef<'tcx>,
257         count: u64,
258     },
259     Array {
260         fields: Vec<ExprRef<'tcx>>,
261     },
262     Tuple {
263         fields: Vec<ExprRef<'tcx>>,
264     },
265     Adt {
266         adt_def: &'tcx AdtDef,
267         variant_index: usize,
268         substs: &'tcx Substs<'tcx>,
269
270         /// Optional user-given substs: for something like `let x =
271         /// Bar::<T> { ... }`.
272         user_ty: Option<UserTypeAnnotation<'tcx>>,
273
274         fields: Vec<FieldExprRef<'tcx>>,
275         base: Option<FruInfo<'tcx>>
276     },
277     PlaceTypeAscription {
278         source: ExprRef<'tcx>,
279         /// Type that the user gave to this expression
280         user_ty: Option<UserTypeAnnotation<'tcx>>,
281     },
282     ValueTypeAscription {
283         source: ExprRef<'tcx>,
284         /// Type that the user gave to this expression
285         user_ty: Option<UserTypeAnnotation<'tcx>>,
286     },
287     Closure {
288         closure_id: DefId,
289         substs: UpvarSubsts<'tcx>,
290         upvars: Vec<ExprRef<'tcx>>,
291         movability: Option<hir::GeneratorMovability>,
292     },
293     Literal {
294         literal: &'tcx Const<'tcx>,
295         user_ty: Option<UserTypeAnnotation<'tcx>>,
296     },
297     InlineAsm {
298         asm: &'tcx hir::InlineAsm,
299         outputs: Vec<ExprRef<'tcx>>,
300         inputs: Vec<ExprRef<'tcx>>
301     },
302     Yield {
303         value: ExprRef<'tcx>,
304     },
305 }
306
307 #[derive(Clone, Debug)]
308 pub enum ExprRef<'tcx> {
309     Hair(&'tcx hir::Expr),
310     Mirror(Box<Expr<'tcx>>),
311 }
312
313 #[derive(Clone, Debug)]
314 pub struct FieldExprRef<'tcx> {
315     pub name: Field,
316     pub expr: ExprRef<'tcx>,
317 }
318
319 #[derive(Clone, Debug)]
320 pub struct FruInfo<'tcx> {
321     pub base: ExprRef<'tcx>,
322     pub field_types: Vec<Ty<'tcx>>
323 }
324
325 #[derive(Clone, Debug)]
326 pub struct Arm<'tcx> {
327     pub patterns: Vec<Pattern<'tcx>>,
328     pub guard: Option<Guard<'tcx>>,
329     pub body: ExprRef<'tcx>,
330     pub lint_level: LintLevel,
331 }
332
333 #[derive(Clone, Debug)]
334 pub enum Guard<'tcx> {
335     If(ExprRef<'tcx>),
336 }
337
338 #[derive(Copy, Clone, Debug)]
339 pub enum LogicalOp {
340     And,
341     Or,
342 }
343
344 impl<'tcx> ExprRef<'tcx> {
345     pub fn span(&self) -> Span {
346         match self {
347             ExprRef::Hair(expr) => expr.span,
348             ExprRef::Mirror(expr) => expr.span,
349         }
350     }
351 }
352
353 ///////////////////////////////////////////////////////////////////////////
354 // The Mirror trait
355
356 /// "Mirroring" is the process of converting from a HIR type into one
357 /// of the HAIR types defined in this file. This is basically a "on
358 /// the fly" desugaring step that hides a lot of the messiness in the
359 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
360 /// `Expr<'tcx>`.
361 ///
362 /// Mirroring is gradual: when you mirror an outer expression like `e1
363 /// + e2`, the references to the inner expressions `e1` and `e2` are
364 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
365 /// mirrored.  This allows a single AST node from the compiler to
366 /// expand into one or more Hair nodes, which lets the Hair nodes be
367 /// simpler.
368 pub trait Mirror<'tcx> {
369     type Output;
370
371     fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output;
372 }
373
374 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
375     type Output = Expr<'tcx>;
376
377     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
378         self
379     }
380 }
381
382 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
383     type Output = Expr<'tcx>;
384
385     fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
386         match self {
387             ExprRef::Hair(h) => h.make_mirror(hir),
388             ExprRef::Mirror(m) => *m,
389         }
390     }
391 }
392
393 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
394     type Output = Stmt<'tcx>;
395
396     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
397         self
398     }
399 }
400
401 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
402     type Output = Stmt<'tcx>;
403
404     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
405         match self {
406             StmtRef::Mirror(m) => *m,
407         }
408     }
409 }
410
411 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
412     type Output = Block<'tcx>;
413
414     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {
415         self
416     }
417 }