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