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