]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/mod.rs
Rename ExprKind::Vec to Array in HIR and HAIR.
[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::{BinOp, BorrowKind, Field, Literal, UnOp, TypedConstVal};
18 use rustc::hir::def_id::DefId;
19 use rustc::middle::region::CodeExtent;
20 use rustc::ty::subst::Substs;
21 use rustc::ty::{self, AdtDef, ClosureSubsts, Region, Ty};
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 use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
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     Use {
143         source: ExprRef<'tcx>,
144     }, // Use a lexpr to get a vexpr.
145     NeverToAny {
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     /// first argument, used for self in a closure
194     SelfRef,
195     StaticRef {
196         id: DefId,
197     },
198     Borrow {
199         region: &'tcx Region,
200         borrow_kind: BorrowKind,
201         arg: ExprRef<'tcx>,
202     },
203     Break {
204         label: Option<CodeExtent>,
205         value: Option<ExprRef<'tcx>>,
206     },
207     Continue {
208         label: Option<CodeExtent>,
209     },
210     Return {
211         value: Option<ExprRef<'tcx>>,
212     },
213     Repeat {
214         value: ExprRef<'tcx>,
215         count: TypedConstVal<'tcx>,
216     },
217     Array {
218         fields: Vec<ExprRef<'tcx>>,
219     },
220     Tuple {
221         fields: Vec<ExprRef<'tcx>>,
222     },
223     Adt {
224         adt_def: &'tcx AdtDef,
225         variant_index: usize,
226         substs: &'tcx Substs<'tcx>,
227         fields: Vec<FieldExprRef<'tcx>>,
228         base: Option<FruInfo<'tcx>>
229     },
230     Closure {
231         closure_id: DefId,
232         substs: ClosureSubsts<'tcx>,
233         upvars: Vec<ExprRef<'tcx>>,
234     },
235     Literal {
236         literal: Literal<'tcx>,
237     },
238     InlineAsm {
239         asm: &'tcx hir::InlineAsm,
240         outputs: Vec<ExprRef<'tcx>>,
241         inputs: Vec<ExprRef<'tcx>>
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 FruInfo<'tcx> {
259     pub base: ExprRef<'tcx>,
260     pub field_types: Vec<Ty<'tcx>>
261 }
262
263 #[derive(Clone, Debug)]
264 pub struct Arm<'tcx> {
265     pub patterns: Vec<Pattern<'tcx>>,
266     pub guard: Option<ExprRef<'tcx>>,
267     pub body: ExprRef<'tcx>,
268 }
269
270 #[derive(Copy, Clone, Debug)]
271 pub enum LogicalOp {
272     And,
273     Or,
274 }
275
276 ///////////////////////////////////////////////////////////////////////////
277 // The Mirror trait
278
279 /// "Mirroring" is the process of converting from a HIR type into one
280 /// of the HAIR types defined in this file. This is basically a "on
281 /// the fly" desugaring step that hides a lot of the messiness in the
282 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
283 /// `Expr<'tcx>`.
284 ///
285 /// Mirroring is gradual: when you mirror an outer expression like `e1
286 /// + e2`, the references to the inner expressions `e1` and `e2` are
287 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
288 /// mirrored.  This allows a single AST node from the compiler to
289 /// expand into one or more Hair nodes, which lets the Hair nodes be
290 /// simpler.
291 pub trait Mirror<'tcx> {
292     type Output;
293
294     fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output;
295 }
296
297 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
298     type Output = Expr<'tcx>;
299
300     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
301         self
302     }
303 }
304
305 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
306     type Output = Expr<'tcx>;
307
308     fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
309         match self {
310             ExprRef::Hair(h) => h.make_mirror(hir),
311             ExprRef::Mirror(m) => *m,
312         }
313     }
314 }
315
316 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
317     type Output = Stmt<'tcx>;
318
319     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
320         self
321     }
322 }
323
324 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
325     type Output = Stmt<'tcx>;
326
327     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
328         match self {
329             StmtRef::Mirror(m) => *m,
330         }
331     }
332 }
333
334 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
335     type Output = Block<'tcx>;
336
337     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {
338         self
339     }
340 }