]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/mod.rs
Fix two UI tests with locale-dependent output
[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 #[derive(Copy, Clone, Debug)]
33 pub enum LintLevel {
34     Inherited,
35     Explicit(ast::NodeId)
36 }
37
38 impl LintLevel {
39     pub fn is_explicit(self) -> bool {
40         match self {
41             LintLevel::Inherited => false,
42             LintLevel::Explicit(_) => true
43         }
44     }
45 }
46
47 #[derive(Clone, Debug)]
48 pub struct Block<'tcx> {
49     pub targeted_by_break: bool,
50     pub region_scope: region::Scope,
51     pub opt_destruction_scope: Option<region::Scope>,
52     pub span: Span,
53     pub stmts: Vec<StmtRef<'tcx>>,
54     pub expr: Option<ExprRef<'tcx>>,
55     pub safety_mode: BlockSafety,
56 }
57
58 #[derive(Copy, Clone, Debug)]
59 pub enum BlockSafety {
60     Safe,
61     ExplicitUnsafe(ast::NodeId),
62     PushUnsafe,
63     PopUnsafe
64 }
65
66 #[derive(Clone, Debug)]
67 pub enum StmtRef<'tcx> {
68     Mirror(Box<Stmt<'tcx>>),
69 }
70
71 #[derive(Clone, Debug)]
72 pub struct Stmt<'tcx> {
73     pub kind: StmtKind<'tcx>,
74     pub opt_destruction_scope: Option<region::Scope>,
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 /// shortlived. 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     },
154     Deref {
155         arg: ExprRef<'tcx>,
156     }, // NOT overloaded!
157     Binary {
158         op: BinOp,
159         lhs: ExprRef<'tcx>,
160         rhs: ExprRef<'tcx>,
161     }, // NOT overloaded!
162     LogicalOp {
163         op: LogicalOp,
164         lhs: ExprRef<'tcx>,
165         rhs: ExprRef<'tcx>,
166     }, // NOT overloaded!
167        // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
168     Unary {
169         op: UnOp,
170         arg: ExprRef<'tcx>,
171     }, // NOT overloaded!
172     Cast {
173         source: ExprRef<'tcx>,
174     },
175     Use {
176         source: ExprRef<'tcx>,
177     }, // Use a lexpr to get a vexpr.
178     NeverToAny {
179         source: ExprRef<'tcx>,
180     },
181     ReifyFnPointer {
182         source: ExprRef<'tcx>,
183     },
184     ClosureFnPointer {
185         source: ExprRef<'tcx>,
186     },
187     UnsafeFnPointer {
188         source: ExprRef<'tcx>,
189     },
190     Unsize {
191         source: ExprRef<'tcx>,
192     },
193     If {
194         condition: ExprRef<'tcx>,
195         then: ExprRef<'tcx>,
196         otherwise: Option<ExprRef<'tcx>>,
197     },
198     Loop {
199         condition: Option<ExprRef<'tcx>>,
200         body: ExprRef<'tcx>,
201     },
202     Match {
203         discriminant: ExprRef<'tcx>,
204         arms: Vec<Arm<'tcx>>,
205     },
206     Block {
207         body: &'tcx hir::Block,
208     },
209     Assign {
210         lhs: ExprRef<'tcx>,
211         rhs: ExprRef<'tcx>,
212     },
213     AssignOp {
214         op: BinOp,
215         lhs: ExprRef<'tcx>,
216         rhs: ExprRef<'tcx>,
217     },
218     Field {
219         lhs: ExprRef<'tcx>,
220         name: Field,
221     },
222     Index {
223         lhs: ExprRef<'tcx>,
224         index: ExprRef<'tcx>,
225     },
226     VarRef {
227         id: ast::NodeId,
228     },
229     /// first argument, used for self in a closure
230     SelfRef,
231     StaticRef {
232         id: DefId,
233     },
234     Borrow {
235         region: Region<'tcx>,
236         borrow_kind: BorrowKind,
237         arg: ExprRef<'tcx>,
238     },
239     Break {
240         label: region::Scope,
241         value: Option<ExprRef<'tcx>>,
242     },
243     Continue {
244         label: region::Scope,
245     },
246     Return {
247         value: Option<ExprRef<'tcx>>,
248     },
249     Repeat {
250         value: ExprRef<'tcx>,
251         count: u64,
252     },
253     Array {
254         fields: Vec<ExprRef<'tcx>>,
255     },
256     Tuple {
257         fields: Vec<ExprRef<'tcx>>,
258     },
259     Adt {
260         adt_def: &'tcx AdtDef,
261         variant_index: usize,
262         substs: &'tcx Substs<'tcx>,
263
264         /// Optional user-given substs: for something like `let x =
265         /// Bar::<T> { ... }`.
266         user_ty: Option<CanonicalTy<'tcx>>,
267
268         fields: Vec<FieldExprRef<'tcx>>,
269         base: Option<FruInfo<'tcx>>
270     },
271     PlaceTypeAscription {
272         source: ExprRef<'tcx>,
273         /// Type that the user gave to this expression
274         user_ty: CanonicalTy<'tcx>,
275     },
276     ValueTypeAscription {
277         source: ExprRef<'tcx>,
278         /// Type that the user gave to this expression
279         user_ty: CanonicalTy<'tcx>,
280     },
281     Closure {
282         closure_id: DefId,
283         substs: UpvarSubsts<'tcx>,
284         upvars: Vec<ExprRef<'tcx>>,
285         movability: Option<hir::GeneratorMovability>,
286     },
287     Literal {
288         literal: &'tcx Const<'tcx>,
289
290         /// Optional user-given type: for something like
291         /// `collect::<Vec<_>>`, this would be present and would
292         /// indicate that `Vec<_>` was explicitly specified.
293         ///
294         /// Needed for NLL to impose user-given type constraints.
295         user_ty: Option<CanonicalTy<'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 }