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