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};
22 use rustc::ty::layout::VariantIdx;
32 pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
33 pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
37 #[derive(Copy, Clone, Debug)]
44 pub fn is_explicit(self) -> bool {
46 LintLevel::Inherited => false,
47 LintLevel::Explicit(_) => true
52 #[derive(Clone, Debug)]
53 pub struct Block<'tcx> {
54 pub targeted_by_break: bool,
55 pub region_scope: region::Scope,
56 pub opt_destruction_scope: Option<region::Scope>,
58 pub stmts: Vec<StmtRef<'tcx>>,
59 pub expr: Option<ExprRef<'tcx>>,
60 pub safety_mode: BlockSafety,
63 #[derive(Copy, Clone, Debug)]
64 pub enum BlockSafety {
66 ExplicitUnsafe(ast::NodeId),
71 #[derive(Clone, Debug)]
72 pub enum StmtRef<'tcx> {
73 Mirror(Box<Stmt<'tcx>>),
76 #[derive(Clone, Debug)]
77 pub struct StatementSpan(pub Span);
79 #[derive(Clone, Debug)]
80 pub struct Stmt<'tcx> {
81 pub kind: StmtKind<'tcx>,
82 pub opt_destruction_scope: Option<region::Scope>,
83 pub span: StatementSpan,
86 #[derive(Clone, Debug)]
87 pub enum StmtKind<'tcx> {
89 /// scope for this statement; may be used as lifetime of temporaries
92 /// expression being evaluated in this statement
97 /// scope for variables bound in this let; covers this and
98 /// remaining statements in block
99 remainder_scope: region::Scope,
101 /// scope for the initialization itself; might be used as
102 /// lifetime of temporaries
103 init_scope: region::Scope,
105 /// `let <PAT> = ...`
107 /// if a type is included, it is added as an ascription pattern
108 pattern: Pattern<'tcx>,
110 /// let pat: ty = <INIT> ...
111 initializer: Option<ExprRef<'tcx>>,
113 /// the lint level for this let-statement
114 lint_level: LintLevel,
118 /// The Hair trait implementor lowers their expressions (`&'tcx H::Expr`)
119 /// into instances of this `Expr` enum. This lowering can be done
120 /// basically as lazily or as eagerly as desired: every recursive
121 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
122 /// may in turn be another instance of this enum (boxed), or else an
123 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
124 /// short-lived. They are created by `Hair::to_expr`, analyzed and
125 /// converted into MIR, and then discarded.
127 /// If you compare `Expr` to the full compiler AST, you will see it is
128 /// a good bit simpler. In fact, a number of the more straight-forward
129 /// MIR simplifications are already done in the impl of `Hair`. For
130 /// example, method calls and overloaded operators are absent: they are
131 /// expected to be converted into `Expr::Call` instances.
132 #[derive(Clone, Debug)]
133 pub struct Expr<'tcx> {
134 /// type of this expression
137 /// lifetime of this expression if it should be spilled into a
138 /// temporary; should be None only if in a constant context
139 pub temp_lifetime: Option<region::Scope>,
141 /// span of the expression in the source
144 /// kind of expression
145 pub kind: ExprKind<'tcx>,
148 #[derive(Clone, Debug)]
149 pub enum ExprKind<'tcx> {
151 region_scope: region::Scope,
152 lint_level: LintLevel,
153 value: ExprRef<'tcx>,
156 value: ExprRef<'tcx>,
161 args: Vec<ExprRef<'tcx>>,
162 // Whether this is from a call in HIR, rather than from an overloaded
163 // operator. True for overloaded function call.
168 }, // NOT overloaded!
173 }, // NOT overloaded!
178 }, // NOT overloaded!
179 // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
183 }, // NOT overloaded!
185 source: ExprRef<'tcx>,
188 source: ExprRef<'tcx>,
189 }, // Use a lexpr to get a vexpr.
191 source: ExprRef<'tcx>,
194 source: ExprRef<'tcx>,
197 source: ExprRef<'tcx>,
200 source: ExprRef<'tcx>,
203 source: ExprRef<'tcx>,
206 condition: ExprRef<'tcx>,
208 otherwise: Option<ExprRef<'tcx>>,
211 condition: Option<ExprRef<'tcx>>,
215 discriminant: ExprRef<'tcx>,
216 arms: Vec<Arm<'tcx>>,
219 body: &'tcx hir::Block,
236 index: ExprRef<'tcx>,
241 /// first argument, used for self in a closure
247 region: Region<'tcx>,
248 borrow_kind: BorrowKind,
252 label: region::Scope,
253 value: Option<ExprRef<'tcx>>,
256 label: region::Scope,
259 value: Option<ExprRef<'tcx>>,
262 value: ExprRef<'tcx>,
266 fields: Vec<ExprRef<'tcx>>,
269 fields: Vec<ExprRef<'tcx>>,
272 adt_def: &'tcx AdtDef,
273 variant_index: VariantIdx,
274 substs: &'tcx Substs<'tcx>,
276 /// Optional user-given substs: for something like `let x =
277 /// Bar::<T> { ... }`.
278 user_ty: Option<UserTypeAnnotation<'tcx>>,
280 fields: Vec<FieldExprRef<'tcx>>,
281 base: Option<FruInfo<'tcx>>
283 PlaceTypeAscription {
284 source: ExprRef<'tcx>,
285 /// Type that the user gave to this expression
286 user_ty: Option<UserTypeAnnotation<'tcx>>,
288 ValueTypeAscription {
289 source: ExprRef<'tcx>,
290 /// Type that the user gave to this expression
291 user_ty: Option<UserTypeAnnotation<'tcx>>,
295 substs: UpvarSubsts<'tcx>,
296 upvars: Vec<ExprRef<'tcx>>,
297 movability: Option<hir::GeneratorMovability>,
300 literal: &'tcx Const<'tcx>,
301 user_ty: Option<UserTypeAnnotation<'tcx>>,
304 asm: &'tcx hir::InlineAsm,
305 outputs: Vec<ExprRef<'tcx>>,
306 inputs: Vec<ExprRef<'tcx>>
309 value: ExprRef<'tcx>,
313 #[derive(Clone, Debug)]
314 pub enum ExprRef<'tcx> {
315 Hair(&'tcx hir::Expr),
316 Mirror(Box<Expr<'tcx>>),
319 #[derive(Clone, Debug)]
320 pub struct FieldExprRef<'tcx> {
322 pub expr: ExprRef<'tcx>,
325 #[derive(Clone, Debug)]
326 pub struct FruInfo<'tcx> {
327 pub base: ExprRef<'tcx>,
328 pub field_types: Vec<Ty<'tcx>>
331 #[derive(Clone, Debug)]
332 pub struct Arm<'tcx> {
333 pub patterns: Vec<Pattern<'tcx>>,
334 pub guard: Option<Guard<'tcx>>,
335 pub body: ExprRef<'tcx>,
336 pub lint_level: LintLevel,
339 #[derive(Clone, Debug)]
340 pub enum Guard<'tcx> {
344 #[derive(Copy, Clone, Debug)]
350 impl<'tcx> ExprRef<'tcx> {
351 pub fn span(&self) -> Span {
353 ExprRef::Hair(expr) => expr.span,
354 ExprRef::Mirror(expr) => expr.span,
359 ///////////////////////////////////////////////////////////////////////////
362 /// "Mirroring" is the process of converting from a HIR type into one
363 /// of the HAIR types defined in this file. This is basically a "on
364 /// the fly" desugaring step that hides a lot of the messiness in the
365 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
368 /// Mirroring is gradual: when you mirror an outer expression like `e1
369 /// + e2`, the references to the inner expressions `e1` and `e2` are
370 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
371 /// mirrored. This allows a single AST node from the compiler to
372 /// expand into one or more Hair nodes, which lets the Hair nodes be
374 pub trait Mirror<'tcx> {
377 fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output;
380 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
381 type Output = Expr<'tcx>;
383 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
388 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
389 type Output = Expr<'tcx>;
391 fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
393 ExprRef::Hair(h) => h.make_mirror(hir),
394 ExprRef::Mirror(m) => *m,
399 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
400 type Output = Stmt<'tcx>;
402 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
407 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
408 type Output = Stmt<'tcx>;
410 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
412 StmtRef::Mirror(m) => *m,
417 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
418 type Output = Block<'tcx>;
420 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {