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