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