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