]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/mod.rs
rustdoc: pretty-print Unevaluated expressions in types.
[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_const_math::ConstUsize;
18 use rustc::mir::{BinOp, BorrowKind, Field, Literal, UnOp};
19 use rustc::hir::def_id::DefId;
20 use rustc::middle::region;
21 use rustc::ty::subst::Substs;
22 use rustc::ty::{self, AdtDef, ClosureSubsts, Region, Ty, GeneratorInterior};
23 use rustc::hir;
24 use syntax::ast;
25 use syntax_pos::Span;
26 use self::cx::Cx;
27
28 pub mod cx;
29
30 pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
31
32 #[derive(Clone, Debug)]
33 pub struct Block<'tcx> {
34     pub targeted_by_break: bool,
35     pub region_scope: region::Scope,
36     pub opt_destruction_scope: Option<region::Scope>,
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     Mirror(Box<Stmt<'tcx>>),
45 }
46
47 #[derive(Clone, Debug)]
48 pub struct Stmt<'tcx> {
49     pub kind: StmtKind<'tcx>,
50     pub opt_destruction_scope: Option<region::Scope>,
51 }
52
53 #[derive(Clone, Debug)]
54 pub enum StmtKind<'tcx> {
55     Expr {
56         /// scope for this statement; may be used as lifetime of temporaries
57         scope: region::Scope,
58
59         /// expression being evaluated in this statement
60         expr: ExprRef<'tcx>,
61     },
62
63     Let {
64         /// scope for variables bound in this let; covers this and
65         /// remaining statements in block
66         remainder_scope: region::Scope,
67
68         /// scope for the initialization itself; might be used as
69         /// lifetime of temporaries
70         init_scope: region::Scope,
71
72         /// let <PAT> = ...
73         pattern: Pattern<'tcx>,
74
75         /// let pat = <INIT> ...
76         initializer: Option<ExprRef<'tcx>>
77     },
78 }
79
80 /// The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
81 /// into instances of this `Expr` enum. This translation can be done
82 /// basically as lazily or as eagerly as desired: every recursive
83 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
84 /// may in turn be another instance of this enum (boxed), or else an
85 /// untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
86 /// shortlived. They are created by `Hair::to_expr`, analyzed and
87 /// converted into MIR, and then discarded.
88 ///
89 /// If you compare `Expr` to the full compiler AST, you will see it is
90 /// a good bit simpler. In fact, a number of the more straight-forward
91 /// MIR simplifications are already done in the impl of `Hair`. For
92 /// example, method calls and overloaded operators are absent: they are
93 /// expected to be converted into `Expr::Call` instances.
94 #[derive(Clone, Debug)]
95 pub struct Expr<'tcx> {
96     /// type of this expression
97     pub ty: Ty<'tcx>,
98
99     /// lifetime of this expression if it should be spilled into a
100     /// temporary; should be None only if in a constant context
101     pub temp_lifetime: Option<region::Scope>,
102
103     /// span of the expression in the source
104     pub span: Span,
105
106     /// kind of expression
107     pub kind: ExprKind<'tcx>,
108 }
109
110 #[derive(Clone, Debug)]
111 pub enum ExprKind<'tcx> {
112     Scope {
113         region_scope: region::Scope,
114         value: ExprRef<'tcx>,
115     },
116     Box {
117         value: ExprRef<'tcx>,
118     },
119     Call {
120         ty: ty::Ty<'tcx>,
121         fun: ExprRef<'tcx>,
122         args: Vec<ExprRef<'tcx>>,
123     },
124     Deref {
125         arg: ExprRef<'tcx>,
126     }, // NOT overloaded!
127     Binary {
128         op: BinOp,
129         lhs: ExprRef<'tcx>,
130         rhs: ExprRef<'tcx>,
131     }, // NOT overloaded!
132     LogicalOp {
133         op: LogicalOp,
134         lhs: ExprRef<'tcx>,
135         rhs: ExprRef<'tcx>,
136     }, // NOT overloaded!
137        // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
138     Unary {
139         op: UnOp,
140         arg: ExprRef<'tcx>,
141     }, // NOT overloaded!
142     Cast {
143         source: ExprRef<'tcx>,
144     },
145     Use {
146         source: ExprRef<'tcx>,
147     }, // Use a lexpr to get a vexpr.
148     NeverToAny {
149         source: ExprRef<'tcx>,
150     },
151     ReifyFnPointer {
152         source: ExprRef<'tcx>,
153     },
154     ClosureFnPointer {
155         source: ExprRef<'tcx>,
156     },
157     UnsafeFnPointer {
158         source: ExprRef<'tcx>,
159     },
160     Unsize {
161         source: ExprRef<'tcx>,
162     },
163     If {
164         condition: ExprRef<'tcx>,
165         then: ExprRef<'tcx>,
166         otherwise: Option<ExprRef<'tcx>>,
167     },
168     Loop {
169         condition: Option<ExprRef<'tcx>>,
170         body: ExprRef<'tcx>,
171     },
172     Match {
173         discriminant: ExprRef<'tcx>,
174         arms: Vec<Arm<'tcx>>,
175     },
176     Block {
177         body: &'tcx hir::Block,
178     },
179     Assign {
180         lhs: ExprRef<'tcx>,
181         rhs: ExprRef<'tcx>,
182     },
183     AssignOp {
184         op: BinOp,
185         lhs: ExprRef<'tcx>,
186         rhs: ExprRef<'tcx>,
187     },
188     Field {
189         lhs: ExprRef<'tcx>,
190         name: Field,
191     },
192     Index {
193         lhs: ExprRef<'tcx>,
194         index: ExprRef<'tcx>,
195     },
196     VarRef {
197         id: ast::NodeId,
198     },
199     /// first argument, used for self in a closure
200     SelfRef,
201     StaticRef {
202         id: DefId,
203     },
204     Borrow {
205         region: Region<'tcx>,
206         borrow_kind: BorrowKind,
207         arg: ExprRef<'tcx>,
208     },
209     Break {
210         label: region::Scope,
211         value: Option<ExprRef<'tcx>>,
212     },
213     Continue {
214         label: region::Scope,
215     },
216     Return {
217         value: Option<ExprRef<'tcx>>,
218     },
219     Repeat {
220         value: ExprRef<'tcx>,
221         count: ConstUsize,
222     },
223     Array {
224         fields: Vec<ExprRef<'tcx>>,
225     },
226     Tuple {
227         fields: Vec<ExprRef<'tcx>>,
228     },
229     Adt {
230         adt_def: &'tcx AdtDef,
231         variant_index: usize,
232         substs: &'tcx Substs<'tcx>,
233         fields: Vec<FieldExprRef<'tcx>>,
234         base: Option<FruInfo<'tcx>>
235     },
236     Closure {
237         closure_id: DefId,
238         substs: ClosureSubsts<'tcx>,
239         upvars: Vec<ExprRef<'tcx>>,
240         interior: Option<GeneratorInterior<'tcx>>,
241     },
242     Literal {
243         literal: Literal<'tcx>,
244     },
245     InlineAsm {
246         asm: &'tcx hir::InlineAsm,
247         outputs: Vec<ExprRef<'tcx>>,
248         inputs: Vec<ExprRef<'tcx>>
249     },
250     Yield {
251         value: ExprRef<'tcx>,
252     },
253 }
254
255 #[derive(Clone, Debug)]
256 pub enum ExprRef<'tcx> {
257     Hair(&'tcx hir::Expr),
258     Mirror(Box<Expr<'tcx>>),
259 }
260
261 #[derive(Clone, Debug)]
262 pub struct FieldExprRef<'tcx> {
263     pub name: Field,
264     pub expr: ExprRef<'tcx>,
265 }
266
267 #[derive(Clone, Debug)]
268 pub struct FruInfo<'tcx> {
269     pub base: ExprRef<'tcx>,
270     pub field_types: Vec<Ty<'tcx>>
271 }
272
273 #[derive(Clone, Debug)]
274 pub struct Arm<'tcx> {
275     pub patterns: Vec<Pattern<'tcx>>,
276     pub guard: Option<ExprRef<'tcx>>,
277     pub body: ExprRef<'tcx>,
278 }
279
280 #[derive(Copy, Clone, Debug)]
281 pub enum LogicalOp {
282     And,
283     Or,
284 }
285
286 ///////////////////////////////////////////////////////////////////////////
287 // The Mirror trait
288
289 /// "Mirroring" is the process of converting from a HIR type into one
290 /// of the HAIR types defined in this file. This is basically a "on
291 /// the fly" desugaring step that hides a lot of the messiness in the
292 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
293 /// `Expr<'tcx>`.
294 ///
295 /// Mirroring is gradual: when you mirror an outer expression like `e1
296 /// + e2`, the references to the inner expressions `e1` and `e2` are
297 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
298 /// mirrored.  This allows a single AST node from the compiler to
299 /// expand into one or more Hair nodes, which lets the Hair nodes be
300 /// simpler.
301 pub trait Mirror<'tcx> {
302     type Output;
303
304     fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output;
305 }
306
307 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
308     type Output = Expr<'tcx>;
309
310     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
311         self
312     }
313 }
314
315 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
316     type Output = Expr<'tcx>;
317
318     fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
319         match self {
320             ExprRef::Hair(h) => h.make_mirror(hir),
321             ExprRef::Mirror(m) => *m,
322         }
323     }
324 }
325
326 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
327     type Output = Stmt<'tcx>;
328
329     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
330         self
331     }
332 }
333
334 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
335     type Output = Stmt<'tcx>;
336
337     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
338         match self {
339             StmtRef::Mirror(m) => *m,
340         }
341     }
342 }
343
344 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
345     type Output = Block<'tcx>;
346
347     fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {
348         self
349     }
350 }