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.
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.
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
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};
30 pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
31 pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
35 #[derive(Copy, Clone, Debug)]
42 pub fn is_explicit(self) -> bool {
44 LintLevel::Inherited => false,
45 LintLevel::Explicit(_) => true
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>,
56 pub stmts: Vec<StmtRef<'tcx>>,
57 pub expr: Option<ExprRef<'tcx>>,
58 pub safety_mode: BlockSafety,
61 #[derive(Copy, Clone, Debug)]
62 pub enum BlockSafety {
64 ExplicitUnsafe(ast::NodeId),
69 #[derive(Clone, Debug)]
70 pub enum StmtRef<'tcx> {
71 Mirror(Box<Stmt<'tcx>>),
74 #[derive(Clone, Debug)]
75 pub struct StatementSpan(pub Span);
77 #[derive(Clone, Debug)]
78 pub struct Stmt<'tcx> {
79 pub kind: StmtKind<'tcx>,
80 pub opt_destruction_scope: Option<region::Scope>,
81 pub span: StatementSpan,
84 #[derive(Clone, Debug)]
85 pub enum StmtKind<'tcx> {
87 /// scope for this statement; may be used as lifetime of temporaries
90 /// expression being evaluated in this statement
95 /// scope for variables bound in this let; covers this and
96 /// remaining statements in block
97 remainder_scope: region::Scope,
99 /// scope for the initialization itself; might be used as
100 /// lifetime of temporaries
101 init_scope: region::Scope,
103 /// `let <PAT> = ...`
105 /// if a type is included, it is added as an ascription pattern
106 pattern: Pattern<'tcx>,
108 /// let pat: ty = <INIT> ...
109 initializer: Option<ExprRef<'tcx>>,
111 /// the lint level for this let-statement
112 lint_level: LintLevel,
116 /// The Hair trait implementor lowers their expressions (`&'tcx H::Expr`)
117 /// into instances of this `Expr` enum. This lowering can be done
118 /// basically as lazily or as eagerly as desired: every recursive
119 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
120 /// may in turn be another instance of this enum (boxed), or else an
121 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
122 /// shortlived. They are created by `Hair::to_expr`, analyzed and
123 /// converted into MIR, and then discarded.
125 /// If you compare `Expr` to the full compiler AST, you will see it is
126 /// a good bit simpler. In fact, a number of the more straight-forward
127 /// MIR simplifications are already done in the impl of `Hair`. For
128 /// example, method calls and overloaded operators are absent: they are
129 /// expected to be converted into `Expr::Call` instances.
130 #[derive(Clone, Debug)]
131 pub struct Expr<'tcx> {
132 /// type of this expression
135 /// lifetime of this expression if it should be spilled into a
136 /// temporary; should be None only if in a constant context
137 pub temp_lifetime: Option<region::Scope>,
139 /// span of the expression in the source
142 /// kind of expression
143 pub kind: ExprKind<'tcx>,
146 #[derive(Clone, Debug)]
147 pub enum ExprKind<'tcx> {
149 region_scope: region::Scope,
150 lint_level: LintLevel,
151 value: ExprRef<'tcx>,
154 value: ExprRef<'tcx>,
159 args: Vec<ExprRef<'tcx>>,
160 // Whether this is from a call in HIR, rather than from an overloaded
161 // operator. True for overloaded function call.
166 }, // NOT overloaded!
171 }, // NOT overloaded!
176 }, // NOT overloaded!
177 // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
181 }, // NOT overloaded!
183 source: ExprRef<'tcx>,
186 source: ExprRef<'tcx>,
187 }, // Use a lexpr to get a vexpr.
189 source: ExprRef<'tcx>,
192 source: ExprRef<'tcx>,
195 source: ExprRef<'tcx>,
198 source: ExprRef<'tcx>,
201 source: ExprRef<'tcx>,
204 condition: ExprRef<'tcx>,
206 otherwise: Option<ExprRef<'tcx>>,
209 condition: Option<ExprRef<'tcx>>,
213 discriminant: ExprRef<'tcx>,
214 arms: Vec<Arm<'tcx>>,
217 body: &'tcx hir::Block,
234 index: ExprRef<'tcx>,
239 /// first argument, used for self in a closure
245 region: Region<'tcx>,
246 borrow_kind: BorrowKind,
250 label: region::Scope,
251 value: Option<ExprRef<'tcx>>,
254 label: region::Scope,
257 value: Option<ExprRef<'tcx>>,
260 value: ExprRef<'tcx>,
264 fields: Vec<ExprRef<'tcx>>,
267 fields: Vec<ExprRef<'tcx>>,
270 adt_def: &'tcx AdtDef,
271 variant_index: usize,
272 substs: &'tcx Substs<'tcx>,
274 /// Optional user-given substs: for something like `let x =
275 /// Bar::<T> { ... }`.
276 user_ty: Option<UserTypeAnnotation<'tcx>>,
278 fields: Vec<FieldExprRef<'tcx>>,
279 base: Option<FruInfo<'tcx>>
281 PlaceTypeAscription {
282 source: ExprRef<'tcx>,
283 /// Type that the user gave to this expression
284 user_ty: Option<UserTypeAnnotation<'tcx>>,
286 ValueTypeAscription {
287 source: ExprRef<'tcx>,
288 /// Type that the user gave to this expression
289 user_ty: Option<UserTypeAnnotation<'tcx>>,
293 substs: UpvarSubsts<'tcx>,
294 upvars: Vec<ExprRef<'tcx>>,
295 movability: Option<hir::GeneratorMovability>,
298 literal: &'tcx Const<'tcx>,
299 user_ty: Option<UserTypeAnnotation<'tcx>>,
302 asm: &'tcx hir::InlineAsm,
303 outputs: Vec<ExprRef<'tcx>>,
304 inputs: Vec<ExprRef<'tcx>>
307 value: ExprRef<'tcx>,
311 #[derive(Clone, Debug)]
312 pub enum ExprRef<'tcx> {
313 Hair(&'tcx hir::Expr),
314 Mirror(Box<Expr<'tcx>>),
317 #[derive(Clone, Debug)]
318 pub struct FieldExprRef<'tcx> {
320 pub expr: ExprRef<'tcx>,
323 #[derive(Clone, Debug)]
324 pub struct FruInfo<'tcx> {
325 pub base: ExprRef<'tcx>,
326 pub field_types: Vec<Ty<'tcx>>
329 #[derive(Clone, Debug)]
330 pub struct Arm<'tcx> {
331 pub patterns: Vec<Pattern<'tcx>>,
332 pub guard: Option<Guard<'tcx>>,
333 pub body: ExprRef<'tcx>,
334 pub lint_level: LintLevel,
337 #[derive(Clone, Debug)]
338 pub enum Guard<'tcx> {
342 #[derive(Copy, Clone, Debug)]
348 impl<'tcx> ExprRef<'tcx> {
349 pub fn span(&self) -> Span {
351 ExprRef::Hair(expr) => expr.span,
352 ExprRef::Mirror(expr) => expr.span,
357 ///////////////////////////////////////////////////////////////////////////
360 /// "Mirroring" is the process of converting from a HIR type into one
361 /// of the HAIR types defined in this file. This is basically a "on
362 /// the fly" desugaring step that hides a lot of the messiness in the
363 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
366 /// Mirroring is gradual: when you mirror an outer expression like `e1
367 /// + e2`, the references to the inner expressions `e1` and `e2` are
368 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
369 /// mirrored. This allows a single AST node from the compiler to
370 /// expand into one or more Hair nodes, which lets the Hair nodes be
372 pub trait Mirror<'tcx> {
375 fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output;
378 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
379 type Output = Expr<'tcx>;
381 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
386 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
387 type Output = Expr<'tcx>;
389 fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
391 ExprRef::Hair(h) => h.make_mirror(hir),
392 ExprRef::Mirror(m) => *m,
397 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
398 type Output = Stmt<'tcx>;
400 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
405 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
406 type Output = Stmt<'tcx>;
408 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
410 StmtRef::Mirror(m) => *m,
415 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
416 type Output = Block<'tcx>;
418 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {