]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/mod.rs
hir, mir: Separate HIR expressions / MIR operands from InlineAsm.
[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     TypedConstVal};
19 use rustc::middle::const_eval::ConstVal;
20 use rustc::middle::def_id::DefId;
21 use rustc::middle::region::CodeExtent;
22 use rustc::middle::subst::Substs;
23 use rustc::middle::ty::{self, AdtDef, ClosureSubsts, Region, Ty};
24 use rustc_front::hir;
25 use syntax::ast;
26 use syntax::codemap::Span;
27 use self::cx::Cx;
28
29 pub mod cx;
30
31 #[derive(Clone, Debug)]
32 pub struct Block<'tcx> {
33     pub extent: CodeExtent,
34     pub span: Span,
35     pub stmts: Vec<StmtRef<'tcx>>,
36     pub expr: Option<ExprRef<'tcx>>,
37 }
38
39 #[derive(Clone, Debug)]
40 pub enum StmtRef<'tcx> {
41     Mirror(Box<Stmt<'tcx>>),
42 }
43
44 #[derive(Clone, Debug)]
45 pub struct Stmt<'tcx> {
46     pub span: Span,
47     pub kind: StmtKind<'tcx>,
48 }
49
50 #[derive(Clone, Debug)]
51 pub enum StmtKind<'tcx> {
52     Expr {
53         /// scope for this statement; may be used as lifetime of temporaries
54         scope: CodeExtent,
55
56         /// expression being evaluated in this statement
57         expr: ExprRef<'tcx>,
58     },
59
60     Let {
61         /// scope for variables bound in this let; covers this and
62         /// remaining statements in block
63         remainder_scope: CodeExtent,
64
65         /// scope for the initialization itself; might be used as
66         /// lifetime of temporaries
67         init_scope: CodeExtent,
68
69         /// let <PAT> = ...
70         pattern: Pattern<'tcx>,
71
72         /// let pat = <INIT> ...
73         initializer: Option<ExprRef<'tcx>>
74     },
75 }
76
77 /// The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
78 /// into instances of this `Expr` enum. This translation can be done
79 /// basically as lazilly or as eagerly as desired: every recursive
80 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
81 /// may in turn be another instance of this enum (boxed), or else an
82 /// untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
83 /// shortlived. They are created by `Hair::to_expr`, analyzed and
84 /// converted into MIR, and then discarded.
85 ///
86 /// If you compare `Expr` to the full compiler AST, you will see it is
87 /// a good bit simpler. In fact, a number of the more straight-forward
88 /// MIR simplifications are already done in the impl of `Hair`. For
89 /// example, method calls and overloaded operators are absent: they are
90 /// expected to be converted into `Expr::Call` instances.
91 #[derive(Clone, Debug)]
92 pub struct Expr<'tcx> {
93     /// type of this expression
94     pub ty: Ty<'tcx>,
95
96     /// lifetime of this expression if it should be spilled into a
97     /// temporary; should be None only if in a constant context
98     pub temp_lifetime: Option<CodeExtent>,
99
100     /// span of the expression in the source
101     pub span: Span,
102
103     /// kind of expression
104     pub kind: ExprKind<'tcx>,
105 }
106
107 #[derive(Clone, Debug)]
108 pub enum ExprKind<'tcx> {
109     Scope {
110         extent: CodeExtent,
111         value: ExprRef<'tcx>,
112     },
113     Box {
114         value: ExprRef<'tcx>,
115         value_extents: CodeExtent,
116     },
117     Call {
118         ty: ty::Ty<'tcx>,
119         fun: ExprRef<'tcx>,
120         args: Vec<ExprRef<'tcx>>,
121     },
122     Deref {
123         arg: ExprRef<'tcx>,
124     }, // NOT overloaded!
125     Binary {
126         op: BinOp,
127         lhs: ExprRef<'tcx>,
128         rhs: ExprRef<'tcx>,
129     }, // NOT overloaded!
130     LogicalOp {
131         op: LogicalOp,
132         lhs: ExprRef<'tcx>,
133         rhs: ExprRef<'tcx>,
134     },
135     Unary {
136         op: UnOp,
137         arg: ExprRef<'tcx>,
138     }, // NOT overloaded!
139     Cast {
140         source: ExprRef<'tcx>,
141     },
142     ReifyFnPointer {
143         source: ExprRef<'tcx>,
144     },
145     UnsafeFnPointer {
146         source: ExprRef<'tcx>,
147     },
148     Unsize {
149         source: ExprRef<'tcx>,
150     },
151     If {
152         condition: ExprRef<'tcx>,
153         then: ExprRef<'tcx>,
154         otherwise: Option<ExprRef<'tcx>>,
155     },
156     Loop {
157         condition: Option<ExprRef<'tcx>>,
158         body: ExprRef<'tcx>,
159     },
160     Match {
161         discriminant: ExprRef<'tcx>,
162         arms: Vec<Arm<'tcx>>,
163     },
164     Block {
165         body: &'tcx hir::Block,
166     },
167     Assign {
168         lhs: ExprRef<'tcx>,
169         rhs: ExprRef<'tcx>,
170     },
171     AssignOp {
172         op: BinOp,
173         lhs: ExprRef<'tcx>,
174         rhs: ExprRef<'tcx>,
175     },
176     Field {
177         lhs: ExprRef<'tcx>,
178         name: Field,
179     },
180     Index {
181         lhs: ExprRef<'tcx>,
182         index: ExprRef<'tcx>,
183     },
184     VarRef {
185         id: ast::NodeId,
186     },
187     /// first argument, used for self in a closure
188     SelfRef,
189     StaticRef {
190         id: DefId,
191     },
192     Borrow {
193         region: Region,
194         borrow_kind: BorrowKind,
195         arg: ExprRef<'tcx>,
196     },
197     Break {
198         label: Option<CodeExtent>,
199     },
200     Continue {
201         label: Option<CodeExtent>,
202     },
203     Return {
204         value: Option<ExprRef<'tcx>>,
205     },
206     Repeat {
207         value: ExprRef<'tcx>,
208         count: TypedConstVal<'tcx>,
209     },
210     Vec {
211         fields: Vec<ExprRef<'tcx>>,
212     },
213     Tuple {
214         fields: Vec<ExprRef<'tcx>>,
215     },
216     Adt {
217         adt_def: AdtDef<'tcx>,
218         variant_index: usize,
219         substs: &'tcx Substs<'tcx>,
220         fields: Vec<FieldExprRef<'tcx>>,
221         base: Option<FruInfo<'tcx>>
222     },
223     Closure {
224         closure_id: DefId,
225         substs: &'tcx ClosureSubsts<'tcx>,
226         upvars: Vec<ExprRef<'tcx>>,
227     },
228     Literal {
229         literal: Literal<'tcx>,
230     },
231     InlineAsm {
232         asm: &'tcx hir::InlineAsm,
233         outputs: Vec<ExprRef<'tcx>>,
234         inputs: Vec<ExprRef<'tcx>>
235     },
236 }
237
238 #[derive(Clone, Debug)]
239 pub enum ExprRef<'tcx> {
240     Hair(&'tcx hir::Expr),
241     Mirror(Box<Expr<'tcx>>),
242 }
243
244 #[derive(Clone, Debug)]
245 pub struct FieldExprRef<'tcx> {
246     pub name: Field,
247     pub expr: ExprRef<'tcx>,
248 }
249
250 #[derive(Clone, Debug)]
251 pub struct FruInfo<'tcx> {
252     pub base: ExprRef<'tcx>,
253     pub field_types: Vec<Ty<'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     /// box P, &P, &mut P, etc
303     Deref {
304         subpattern: Pattern<'tcx>,
305     },
306
307     Constant {
308         value: ConstVal,
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 }