]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/mod.rs
Auto merge of #30724 - nikomatsakis:feature-gate-defaulted-type-parameters, r=pnkfelix
[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 translated 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::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp, ItemKind};
18 use rustc::middle::const_eval::ConstVal;
19 use rustc::middle::def_id::DefId;
20 use rustc::middle::region::CodeExtent;
21 use rustc::middle::subst::Substs;
22 use rustc::middle::ty::{self, AdtDef, ClosureSubsts, Region, Ty};
23 use rustc_front::hir;
24 use syntax::ast;
25 use syntax::codemap::Span;
26 use self::cx::Cx;
27
28 pub mod cx;
29
30 #[derive(Clone, Debug)]
31 pub struct ItemRef<'tcx> {
32     pub ty: Ty<'tcx>,
33     pub kind: ItemKind,
34     pub def_id: DefId,
35     pub substs: &'tcx Substs<'tcx>,
36 }
37
38 #[derive(Clone, Debug)]
39 pub struct Block<'tcx> {
40     pub extent: CodeExtent,
41     pub span: Span,
42     pub stmts: Vec<StmtRef<'tcx>>,
43     pub expr: Option<ExprRef<'tcx>>,
44 }
45
46 #[derive(Clone, Debug)]
47 pub enum StmtRef<'tcx> {
48     Mirror(Box<Stmt<'tcx>>),
49 }
50
51 #[derive(Clone, Debug)]
52 pub struct Stmt<'tcx> {
53     pub span: Span,
54     pub kind: StmtKind<'tcx>,
55 }
56
57 #[derive(Clone, Debug)]
58 pub enum StmtKind<'tcx> {
59     Expr {
60         /// scope for this statement; may be used as lifetime of temporaries
61         scope: CodeExtent,
62
63         /// expression being evaluated in this statement
64         expr: ExprRef<'tcx>,
65     },
66
67     Let {
68         /// scope for variables bound in this let; covers this and
69         /// remaining statements in block
70         remainder_scope: CodeExtent,
71
72         /// scope for the initialization itself; might be used as
73         /// lifetime of temporaries
74         init_scope: CodeExtent,
75
76         /// let <PAT> = ...
77         pattern: Pattern<'tcx>,
78
79         /// let pat = <INIT> ...
80         initializer: Option<ExprRef<'tcx>>,
81
82         /// let pat = init; <STMTS>
83         stmts: Vec<StmtRef<'tcx>>,
84     },
85 }
86
87 // The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
88 // into instances of this `Expr` enum. This translation can be done
89 // basically as lazilly or as eagerly as desired: every recursive
90 // reference to an expression in this enum is an `ExprRef<'tcx>`, which
91 // may in turn be another instance of this enum (boxed), or else an
92 // untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
93 // shortlived. They are created by `Hair::to_expr`, analyzed and
94 // converted into MIR, and then discarded.
95 //
96 // If you compare `Expr` to the full compiler AST, you will see it is
97 // a good bit simpler. In fact, a number of the more straight-forward
98 // MIR simplifications are already done in the impl of `Hair`. For
99 // example, method calls and overloaded operators are absent: they are
100 // expected to be converted into `Expr::Call` instances.
101 #[derive(Clone, Debug)]
102 pub struct Expr<'tcx> {
103     // type of this expression
104     pub ty: Ty<'tcx>,
105
106     // lifetime of this expression if it should be spilled into a
107     // temporary; should be None only if in a constant context
108     pub temp_lifetime: Option<CodeExtent>,
109
110     // span of the expression in the source
111     pub span: Span,
112
113     // kind of expression
114     pub kind: ExprKind<'tcx>,
115 }
116
117 #[derive(Clone, Debug)]
118 pub enum ExprKind<'tcx> {
119     Scope {
120         extent: CodeExtent,
121         value: ExprRef<'tcx>,
122     },
123     Box {
124         value: ExprRef<'tcx>,
125     },
126     Call {
127         ty: ty::Ty<'tcx>,
128         fun: ExprRef<'tcx>,
129         args: Vec<ExprRef<'tcx>>,
130     },
131     Deref {
132         arg: ExprRef<'tcx>,
133     }, // NOT overloaded!
134     Binary {
135         op: BinOp,
136         lhs: ExprRef<'tcx>,
137         rhs: ExprRef<'tcx>,
138     }, // NOT overloaded!
139     LogicalOp {
140         op: LogicalOp,
141         lhs: ExprRef<'tcx>,
142         rhs: ExprRef<'tcx>,
143     },
144     Unary {
145         op: UnOp,
146         arg: ExprRef<'tcx>,
147     }, // NOT overloaded!
148     Cast {
149         source: ExprRef<'tcx>,
150     },
151     ReifyFnPointer {
152         source: ExprRef<'tcx>,
153     },
154     UnsafeFnPointer {
155         source: ExprRef<'tcx>,
156     },
157     Unsize {
158         source: ExprRef<'tcx>,
159     },
160     If {
161         condition: ExprRef<'tcx>,
162         then: ExprRef<'tcx>,
163         otherwise: Option<ExprRef<'tcx>>,
164     },
165     Loop {
166         condition: Option<ExprRef<'tcx>>,
167         body: ExprRef<'tcx>,
168     },
169     Match {
170         discriminant: ExprRef<'tcx>,
171         arms: Vec<Arm<'tcx>>,
172     },
173     Block {
174         body: &'tcx hir::Block,
175     },
176     Assign {
177         lhs: ExprRef<'tcx>,
178         rhs: ExprRef<'tcx>,
179     },
180     AssignOp {
181         op: BinOp,
182         lhs: ExprRef<'tcx>,
183         rhs: ExprRef<'tcx>,
184     },
185     Field {
186         lhs: ExprRef<'tcx>,
187         name: Field,
188     },
189     Index {
190         lhs: ExprRef<'tcx>,
191         index: ExprRef<'tcx>,
192     },
193     VarRef {
194         id: ast::NodeId,
195     },
196     SelfRef, // first argument, used for self in a closure
197     StaticRef {
198         id: DefId,
199     },
200     Borrow {
201         region: Region,
202         borrow_kind: BorrowKind,
203         arg: ExprRef<'tcx>,
204     },
205     Break {
206         label: Option<CodeExtent>,
207     },
208     Continue {
209         label: Option<CodeExtent>,
210     },
211     Return {
212         value: Option<ExprRef<'tcx>>,
213     },
214     Repeat {
215         value: ExprRef<'tcx>,
216         // FIXME(#29789): Add a separate hair::Constant<'tcx> so this could be more explicit about
217         // its contained data. Currently this should only contain expression of ExprKind::Literal
218         // kind.
219         count: ExprRef<'tcx>,
220     },
221     Vec {
222         fields: Vec<ExprRef<'tcx>>,
223     },
224     Tuple {
225         fields: Vec<ExprRef<'tcx>>,
226     },
227     Adt {
228         adt_def: AdtDef<'tcx>,
229         variant_index: usize,
230         substs: &'tcx Substs<'tcx>,
231         fields: Vec<FieldExprRef<'tcx>>,
232         base: Option<ExprRef<'tcx>>,
233     },
234     Closure {
235         closure_id: DefId,
236         substs: &'tcx ClosureSubsts<'tcx>,
237         upvars: Vec<ExprRef<'tcx>>,
238     },
239     Literal {
240         literal: Literal<'tcx>,
241     },
242     InlineAsm {
243         asm: &'tcx hir::InlineAsm,
244     },
245 }
246
247 #[derive(Clone, Debug)]
248 pub enum ExprRef<'tcx> {
249     Hair(&'tcx hir::Expr),
250     Mirror(Box<Expr<'tcx>>),
251 }
252
253 #[derive(Clone, Debug)]
254 pub struct FieldExprRef<'tcx> {
255     pub name: Field,
256     pub expr: ExprRef<'tcx>,
257 }
258
259 #[derive(Clone, Debug)]
260 pub struct Arm<'tcx> {
261     pub patterns: Vec<Pattern<'tcx>>,
262     pub guard: Option<ExprRef<'tcx>>,
263     pub body: ExprRef<'tcx>,
264 }
265
266 #[derive(Clone, Debug)]
267 pub struct Pattern<'tcx> {
268     pub ty: Ty<'tcx>,
269     pub span: Span,
270     pub kind: Box<PatternKind<'tcx>>,
271 }
272
273 #[derive(Copy, Clone, Debug)]
274 pub enum LogicalOp {
275     And,
276     Or,
277 }
278
279 #[derive(Clone, Debug)]
280 pub enum PatternKind<'tcx> {
281     Wild,
282
283     // x, ref x, x @ P, etc
284     Binding {
285         mutability: Mutability,
286         name: ast::Name,
287         mode: BindingMode,
288         var: ast::NodeId,
289         ty: Ty<'tcx>,
290         subpattern: Option<Pattern<'tcx>>,
291     },
292
293     // Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
294     Variant {
295         adt_def: AdtDef<'tcx>,
296         variant_index: usize,
297         subpatterns: Vec<FieldPattern<'tcx>>,
298     },
299
300     // (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
301     Leaf {
302         subpatterns: Vec<FieldPattern<'tcx>>,
303     },
304
305     Deref {
306         subpattern: Pattern<'tcx>,
307     }, // box P, &P, &mut P, etc
308
309     Constant {
310         value: ConstVal,
311     },
312
313     Range {
314         lo: Literal<'tcx>,
315         hi: Literal<'tcx>,
316     },
317
318     // matches against a slice, checking the length and extracting elements
319     Slice {
320         prefix: Vec<Pattern<'tcx>>,
321         slice: Option<Pattern<'tcx>>,
322         suffix: Vec<Pattern<'tcx>>,
323     },
324
325     // fixed match against an array, irrefutable
326     Array {
327         prefix: Vec<Pattern<'tcx>>,
328         slice: Option<Pattern<'tcx>>,
329         suffix: Vec<Pattern<'tcx>>,
330     },
331 }
332
333 #[derive(Copy, Clone, Debug)]
334 pub enum BindingMode {
335     ByValue,
336     ByRef(Region, BorrowKind),
337 }
338
339 #[derive(Clone, Debug)]
340 pub struct FieldPattern<'tcx> {
341     pub field: Field,
342     pub pattern: Pattern<'tcx>,
343 }
344
345 ///////////////////////////////////////////////////////////////////////////
346 // The Mirror trait
347
348 /// "Mirroring" is the process of converting from a HIR type into one
349 /// of the HAIR types defined in this file. This is basically a "on
350 /// the fly" desugaring step that hides a lot of the messiness in the
351 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
352 /// `Expr<'tcx>`.
353 ///
354 /// Mirroring is gradual: when you mirror an outer expression like `e1
355 /// + e2`, the references to the inner expressions `e1` and `e2` are
356 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
357 /// mirrored.  This allows a single AST node from the compiler to
358 /// expand into one or more Hair nodes, which lets the Hair nodes be
359 /// simpler.
360 pub trait Mirror<'tcx> {
361     type Output;
362
363     fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Self::Output;
364 }
365
366 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
367     type Output = Expr<'tcx>;
368
369     fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
370         self
371     }
372 }
373
374 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
375     type Output = Expr<'tcx>;
376
377     fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
378         match self {
379             ExprRef::Hair(h) => h.make_mirror(hir),
380             ExprRef::Mirror(m) => *m,
381         }
382     }
383 }
384
385 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
386     type Output = Stmt<'tcx>;
387
388     fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> {
389         self
390     }
391 }
392
393 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
394     type Output = Stmt<'tcx>;
395
396     fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Stmt<'tcx> {
397         match self {
398             StmtRef::Mirror(m) => *m,
399         }
400     }
401 }
402
403 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
404     type Output = Block<'tcx>;
405
406     fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Block<'tcx> {
407         self
408     }
409 }