]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/mod.rs
3078f10598c0dfff100330ec7ef5c20e4fc5b8e5
[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::ty::layout::VariantIdx;
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 mod pattern;
31 pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
32 pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
33
34 mod util;
35
36 #[derive(Copy, Clone, Debug)]
37 pub enum LintLevel {
38     Inherited,
39     Explicit(ast::NodeId)
40 }
41
42 impl LintLevel {
43     pub fn is_explicit(self) -> bool {
44         match self {
45             LintLevel::Inherited => false,
46             LintLevel::Explicit(_) => true
47         }
48     }
49 }
50
51 #[derive(Clone, Debug)]
52 pub struct Block<'tcx> {
53     pub targeted_by_break: bool,
54     pub region_scope: region::Scope,
55     pub opt_destruction_scope: Option<region::Scope>,
56     pub span: Span,
57     pub stmts: Vec<StmtRef<'tcx>>,
58     pub expr: Option<ExprRef<'tcx>>,
59     pub safety_mode: BlockSafety,
60 }
61
62 #[derive(Copy, Clone, Debug)]
63 pub enum BlockSafety {
64     Safe,
65     ExplicitUnsafe(ast::NodeId),
66     PushUnsafe,
67     PopUnsafe
68 }
69
70 #[derive(Clone, Debug)]
71 pub enum StmtRef<'tcx> {
72     Mirror(Box<Stmt<'tcx>>),
73 }
74
75 #[derive(Clone, Debug)]
76 pub struct StatementSpan(pub Span);
77
78 #[derive(Clone, Debug)]
79 pub struct Stmt<'tcx> {
80     pub kind: StmtKind<'tcx>,
81     pub opt_destruction_scope: Option<region::Scope>,
82     pub span: StatementSpan,
83 }
84
85 #[derive(Clone, Debug)]
86 pub enum StmtKind<'tcx> {
87     Expr {
88         /// scope for this statement; may be used as lifetime of temporaries
89         scope: region::Scope,
90
91         /// expression being evaluated in this statement
92         expr: ExprRef<'tcx>,
93     },
94
95     Let {
96         /// scope for variables bound in this let; covers this and
97         /// remaining statements in block
98         remainder_scope: region::Scope,
99
100         /// scope for the initialization itself; might be used as
101         /// lifetime of temporaries
102         init_scope: region::Scope,
103
104         /// `let <PAT> = ...`
105         ///
106         /// if a type is included, it is added as an ascription pattern
107         pattern: Pattern<'tcx>,
108
109         /// let pat: ty = <INIT> ...
110         initializer: Option<ExprRef<'tcx>>,
111
112         /// the lint level for this let-statement
113         lint_level: LintLevel,
114     },
115 }
116
117 /// The Hair trait implementor lowers their expressions (`&'tcx H::Expr`)
118 /// into instances of this `Expr` enum. This lowering can be done
119 /// basically as lazily or as eagerly as desired: every recursive
120 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
121 /// may in turn be another instance of this enum (boxed), or else an
122 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
123 /// short-lived. They are created by `Hair::to_expr`, analyzed and
124 /// converted into MIR, and then discarded.
125 ///
126 /// If you compare `Expr` to the full compiler AST, you will see it is
127 /// a good bit simpler. In fact, a number of the more straight-forward
128 /// MIR simplifications are already done in the impl of `Hair`. For
129 /// example, method calls and overloaded operators are absent: they are
130 /// expected to be converted into `Expr::Call` instances.
131 #[derive(Clone, Debug)]
132 pub struct Expr<'tcx> {
133     /// type of this expression
134     pub ty: Ty<'tcx>,
135
136     /// lifetime of this expression if it should be spilled into a
137     /// temporary; should be None only if in a constant context
138     pub temp_lifetime: Option<region::Scope>,
139
140     /// span of the expression in the source
141     pub span: Span,
142
143     /// kind of expression
144     pub kind: ExprKind<'tcx>,
145 }
146
147 #[derive(Clone, Debug)]
148 pub enum ExprKind<'tcx> {
149     Scope {
150         region_scope: region::Scope,
151         lint_level: LintLevel,
152         value: ExprRef<'tcx>,
153     },
154     Box {
155         value: ExprRef<'tcx>,
156     },
157     Call {
158         ty: Ty<'tcx>,
159         fun: ExprRef<'tcx>,
160         args: Vec<ExprRef<'tcx>>,
161         // Whether this is from a call in HIR, rather than from an overloaded
162         // operator. True for overloaded function call.
163         from_hir_call: bool,
164     },
165     Deref {
166         arg: ExprRef<'tcx>,
167     }, // NOT overloaded!
168     Binary {
169         op: BinOp,
170         lhs: ExprRef<'tcx>,
171         rhs: ExprRef<'tcx>,
172     }, // NOT overloaded!
173     LogicalOp {
174         op: LogicalOp,
175         lhs: ExprRef<'tcx>,
176         rhs: ExprRef<'tcx>,
177     }, // NOT overloaded!
178        // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
179     Unary {
180         op: UnOp,
181         arg: ExprRef<'tcx>,
182     }, // NOT overloaded!
183     Cast {
184         source: ExprRef<'tcx>,
185     },
186     Use {
187         source: ExprRef<'tcx>,
188     }, // Use a lexpr to get a vexpr.
189     NeverToAny {
190         source: ExprRef<'tcx>,
191     },
192     ReifyFnPointer {
193         source: ExprRef<'tcx>,
194     },
195     ClosureFnPointer {
196         source: ExprRef<'tcx>,
197     },
198     UnsafeFnPointer {
199         source: ExprRef<'tcx>,
200     },
201     Unsize {
202         source: ExprRef<'tcx>,
203     },
204     If {
205         condition: ExprRef<'tcx>,
206         then: ExprRef<'tcx>,
207         otherwise: Option<ExprRef<'tcx>>,
208     },
209     Loop {
210         condition: Option<ExprRef<'tcx>>,
211         body: ExprRef<'tcx>,
212     },
213     Match {
214         discriminant: ExprRef<'tcx>,
215         arms: Vec<Arm<'tcx>>,
216     },
217     Block {
218         body: &'tcx hir::Block,
219     },
220     Assign {
221         lhs: ExprRef<'tcx>,
222         rhs: ExprRef<'tcx>,
223     },
224     AssignOp {
225         op: BinOp,
226         lhs: ExprRef<'tcx>,
227         rhs: ExprRef<'tcx>,
228     },
229     Field {
230         lhs: ExprRef<'tcx>,
231         name: Field,
232     },
233     Index {
234         lhs: ExprRef<'tcx>,
235         index: ExprRef<'tcx>,
236     },
237     VarRef {
238         id: ast::NodeId,
239     },
240     /// first argument, used for self in a closure
241     SelfRef,
242     StaticRef {
243         id: DefId,
244     },
245     Borrow {
246         region: Region<'tcx>,
247         borrow_kind: BorrowKind,
248         arg: ExprRef<'tcx>,
249     },
250     Break {
251         label: region::Scope,
252         value: Option<ExprRef<'tcx>>,
253     },
254     Continue {
255         label: region::Scope,
256     },
257     Return {
258         value: Option<ExprRef<'tcx>>,
259     },
260     Repeat {
261         value: ExprRef<'tcx>,
262         count: u64,
263     },
264     Array {
265         fields: Vec<ExprRef<'tcx>>,
266     },
267     Tuple {
268         fields: Vec<ExprRef<'tcx>>,
269     },
270     Adt {
271         adt_def: &'tcx AdtDef,
272         variant_index: VariantIdx,
273         substs: &'tcx Substs<'tcx>,
274
275         /// Optional user-given substs: for something like `let x =
276         /// Bar::<T> { ... }`.
277         user_ty: Option<UserTypeAnnotation<'tcx>>,
278
279         fields: Vec<FieldExprRef<'tcx>>,
280         base: Option<FruInfo<'tcx>>
281     },
282     PlaceTypeAscription {
283         source: ExprRef<'tcx>,
284         /// Type that the user gave to this expression
285         user_ty: Option<UserTypeAnnotation<'tcx>>,
286     },
287     ValueTypeAscription {
288         source: ExprRef<'tcx>,
289         /// Type that the user gave to this expression
290         user_ty: Option<UserTypeAnnotation<'tcx>>,
291     },
292     Closure {
293         closure_id: DefId,
294         substs: UpvarSubsts<'tcx>,
295         upvars: Vec<ExprRef<'tcx>>,
296         movability: Option<hir::GeneratorMovability>,
297     },
298     Literal {
299         literal: &'tcx Const<'tcx>,
300         user_ty: Option<UserTypeAnnotation<'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 }