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