]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/hair/mod.rs
New upstream version 1.13.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_pos::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 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(Clone, Debug)]
270 pub struct Pattern<'tcx> {
271 pub ty: Ty<'tcx>,
272 pub span: Span,
273 pub kind: Box<PatternKind<'tcx>>,
274 }
275
276 #[derive(Copy, Clone, Debug)]
277 pub enum LogicalOp {
278 And,
279 Or,
280 }
281
282 #[derive(Clone, Debug)]
283 pub enum PatternKind<'tcx> {
284 Wild,
285
286 /// x, ref x, x @ P, etc
287 Binding {
288 mutability: Mutability,
289 name: ast::Name,
290 mode: BindingMode<'tcx>,
291 var: ast::NodeId,
292 ty: Ty<'tcx>,
293 subpattern: Option<Pattern<'tcx>>,
294 },
295
296 /// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
297 Variant {
298 adt_def: AdtDef<'tcx>,
299 variant_index: usize,
300 subpatterns: Vec<FieldPattern<'tcx>>,
301 },
302
303 /// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
304 Leaf {
305 subpatterns: Vec<FieldPattern<'tcx>>,
306 },
307
308 /// box P, &P, &mut P, etc
309 Deref {
310 subpattern: Pattern<'tcx>,
311 },
312
313 Constant {
314 value: ConstVal,
315 },
316
317 Range {
318 lo: Literal<'tcx>,
319 hi: Literal<'tcx>,
320 },
321
322 /// matches against a slice, checking the length and extracting elements
323 Slice {
324 prefix: Vec<Pattern<'tcx>>,
325 slice: Option<Pattern<'tcx>>,
326 suffix: Vec<Pattern<'tcx>>,
327 },
328
329 /// fixed match against an array, irrefutable
330 Array {
331 prefix: Vec<Pattern<'tcx>>,
332 slice: Option<Pattern<'tcx>>,
333 suffix: Vec<Pattern<'tcx>>,
334 },
335 }
336
337 #[derive(Copy, Clone, Debug)]
338 pub enum BindingMode<'tcx> {
339 ByValue,
340 ByRef(&'tcx Region, BorrowKind),
341 }
342
343 #[derive(Clone, Debug)]
344 pub struct FieldPattern<'tcx> {
345 pub field: Field,
346 pub pattern: Pattern<'tcx>,
347 }
348
349 ///////////////////////////////////////////////////////////////////////////
350 // The Mirror trait
351
352 /// "Mirroring" is the process of converting from a HIR type into one
353 /// of the HAIR types defined in this file. This is basically a "on
354 /// the fly" desugaring step that hides a lot of the messiness in the
355 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
356 /// `Expr<'tcx>`.
357 ///
358 /// Mirroring is gradual: when you mirror an outer expression like `e1
359 /// + e2`, the references to the inner expressions `e1` and `e2` are
360 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
361 /// mirrored. This allows a single AST node from the compiler to
362 /// expand into one or more Hair nodes, which lets the Hair nodes be
363 /// simpler.
364 pub trait Mirror<'tcx> {
365 type Output;
366
367 fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output;
368 }
369
370 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
371 type Output = Expr<'tcx>;
372
373 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
374 self
375 }
376 }
377
378 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
379 type Output = Expr<'tcx>;
380
381 fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
382 match self {
383 ExprRef::Hair(h) => h.make_mirror(hir),
384 ExprRef::Mirror(m) => *m,
385 }
386 }
387 }
388
389 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
390 type Output = Stmt<'tcx>;
391
392 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
393 self
394 }
395 }
396
397 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
398 type Output = Stmt<'tcx>;
399
400 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
401 match self {
402 StmtRef::Mirror(m) => *m,
403 }
404 }
405 }
406
407 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
408 type Output = Block<'tcx>;
409
410 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {
411 self
412 }
413 }