]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/hair/mod.rs
Imported Upstream version 1.9.0+dfsg1
[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::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp,
18 TypedConstVal};
19 use rustc::middle::const_val::ConstVal;
20 use rustc::hir::def_id::DefId;
21 use rustc::middle::region::CodeExtent;
22 use rustc::ty::subst::Substs;
23 use rustc::ty::{self, AdtDef, ClosureSubsts, Region, Ty};
24 use rustc::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 }