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