1 //! The MIR is built from some high-level abstract IR
2 //! (HAIR). This section defines the HAIR along with a trait for
3 //! accessing it. The intention is to allow MIR construction to be
4 //! unit-tested and separated from the Rust source and compiler data
7 use rustc::mir::{BinOp, BorrowKind, Field, UnOp};
8 use rustc::hir::def_id::DefId;
9 use rustc::infer::canonical::Canonical;
10 use rustc::middle::region;
11 use rustc::ty::subst::Substs;
12 use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserType};
13 use rustc::ty::layout::VariantIdx;
23 pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternRange, FieldPattern};
24 pub(crate) use self::pattern::PatternTypeProjection;
28 #[derive(Copy, Clone, Debug)]
35 pub fn is_explicit(self) -> bool {
37 LintLevel::Inherited => false,
38 LintLevel::Explicit(_) => true
43 #[derive(Clone, Debug)]
44 pub struct Block<'tcx> {
45 pub targeted_by_break: bool,
46 pub region_scope: region::Scope,
47 pub opt_destruction_scope: Option<region::Scope>,
49 pub stmts: Vec<StmtRef<'tcx>>,
50 pub expr: Option<ExprRef<'tcx>>,
51 pub safety_mode: BlockSafety,
54 #[derive(Copy, Clone, Debug)]
55 pub enum BlockSafety {
57 ExplicitUnsafe(ast::NodeId),
62 #[derive(Clone, Debug)]
63 pub enum StmtRef<'tcx> {
64 Mirror(Box<Stmt<'tcx>>),
67 #[derive(Clone, Debug)]
68 pub struct StatementSpan(pub Span);
70 #[derive(Clone, Debug)]
71 pub struct Stmt<'tcx> {
72 pub kind: StmtKind<'tcx>,
73 pub opt_destruction_scope: Option<region::Scope>,
74 pub span: StatementSpan,
77 #[derive(Clone, Debug)]
78 pub enum StmtKind<'tcx> {
80 /// scope for this statement; may be used as lifetime of temporaries
83 /// expression being evaluated in this statement
88 /// scope for variables bound in this let; covers this and
89 /// remaining statements in block
90 remainder_scope: region::Scope,
92 /// scope for the initialization itself; might be used as
93 /// lifetime of temporaries
94 init_scope: region::Scope,
98 /// if a type is included, it is added as an ascription pattern
99 pattern: Pattern<'tcx>,
101 /// let pat: ty = <INIT> ...
102 initializer: Option<ExprRef<'tcx>>,
104 /// the lint level for this let-statement
105 lint_level: LintLevel,
109 /// The Hair trait implementor lowers their expressions (`&'tcx H::Expr`)
110 /// into instances of this `Expr` enum. This lowering can be done
111 /// basically as lazily or as eagerly as desired: every recursive
112 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
113 /// may in turn be another instance of this enum (boxed), or else an
114 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
115 /// short-lived. They are created by `Hair::to_expr`, analyzed and
116 /// converted into MIR, and then discarded.
118 /// If you compare `Expr` to the full compiler AST, you will see it is
119 /// a good bit simpler. In fact, a number of the more straight-forward
120 /// MIR simplifications are already done in the impl of `Hair`. For
121 /// example, method calls and overloaded operators are absent: they are
122 /// expected to be converted into `Expr::Call` instances.
123 #[derive(Clone, Debug)]
124 pub struct Expr<'tcx> {
125 /// type of this expression
128 /// lifetime of this expression if it should be spilled into a
129 /// temporary; should be None only if in a constant context
130 pub temp_lifetime: Option<region::Scope>,
132 /// span of the expression in the source
135 /// kind of expression
136 pub kind: ExprKind<'tcx>,
139 #[derive(Clone, Debug)]
140 pub enum ExprKind<'tcx> {
142 region_scope: region::Scope,
143 lint_level: LintLevel,
144 value: ExprRef<'tcx>,
147 value: ExprRef<'tcx>,
152 args: Vec<ExprRef<'tcx>>,
153 // Whether this is from a call in HIR, rather than from an overloaded
154 // operator. True for overloaded function call.
159 }, // NOT overloaded!
164 }, // NOT overloaded!
169 }, // NOT overloaded!
170 // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
174 }, // NOT overloaded!
176 source: ExprRef<'tcx>,
179 source: ExprRef<'tcx>,
180 }, // Use a lexpr to get a vexpr.
182 source: ExprRef<'tcx>,
185 source: ExprRef<'tcx>,
188 source: ExprRef<'tcx>,
191 source: ExprRef<'tcx>,
194 source: ExprRef<'tcx>,
197 condition: ExprRef<'tcx>,
199 otherwise: Option<ExprRef<'tcx>>,
202 condition: Option<ExprRef<'tcx>>,
206 discriminant: ExprRef<'tcx>,
207 arms: Vec<Arm<'tcx>>,
210 body: &'tcx hir::Block,
227 index: ExprRef<'tcx>,
232 /// first argument, used for self in a closure
238 borrow_kind: BorrowKind,
242 label: region::Scope,
243 value: Option<ExprRef<'tcx>>,
246 label: region::Scope,
249 value: Option<ExprRef<'tcx>>,
252 value: ExprRef<'tcx>,
256 fields: Vec<ExprRef<'tcx>>,
259 fields: Vec<ExprRef<'tcx>>,
262 adt_def: &'tcx AdtDef,
263 variant_index: VariantIdx,
264 substs: &'tcx Substs<'tcx>,
266 /// Optional user-given substs: for something like `let x =
267 /// Bar::<T> { ... }`.
268 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
270 fields: Vec<FieldExprRef<'tcx>>,
271 base: Option<FruInfo<'tcx>>
273 PlaceTypeAscription {
274 source: ExprRef<'tcx>,
275 /// Type that the user gave to this expression
276 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
278 ValueTypeAscription {
279 source: ExprRef<'tcx>,
280 /// Type that the user gave to this expression
281 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
285 substs: UpvarSubsts<'tcx>,
286 upvars: Vec<ExprRef<'tcx>>,
287 movability: Option<hir::GeneratorMovability>,
290 literal: &'tcx LazyConst<'tcx>,
291 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
294 asm: &'tcx hir::InlineAsm,
295 outputs: Vec<ExprRef<'tcx>>,
296 inputs: Vec<ExprRef<'tcx>>
299 value: ExprRef<'tcx>,
303 #[derive(Clone, Debug)]
304 pub enum ExprRef<'tcx> {
305 Hair(&'tcx hir::Expr),
306 Mirror(Box<Expr<'tcx>>),
309 #[derive(Clone, Debug)]
310 pub struct FieldExprRef<'tcx> {
312 pub expr: ExprRef<'tcx>,
315 #[derive(Clone, Debug)]
316 pub struct FruInfo<'tcx> {
317 pub base: ExprRef<'tcx>,
318 pub field_types: Vec<Ty<'tcx>>
321 #[derive(Clone, Debug)]
322 pub struct Arm<'tcx> {
323 pub patterns: Vec<Pattern<'tcx>>,
324 pub guard: Option<Guard<'tcx>>,
325 pub body: ExprRef<'tcx>,
326 pub lint_level: LintLevel,
329 #[derive(Clone, Debug)]
330 pub enum Guard<'tcx> {
334 #[derive(Copy, Clone, Debug)]
340 impl<'tcx> ExprRef<'tcx> {
341 pub fn span(&self) -> Span {
343 ExprRef::Hair(expr) => expr.span,
344 ExprRef::Mirror(expr) => expr.span,
349 ///////////////////////////////////////////////////////////////////////////
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
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
364 pub trait Mirror<'tcx> {
367 fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output;
370 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
371 type Output = Expr<'tcx>;
373 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
378 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
379 type Output = Expr<'tcx>;
381 fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
383 ExprRef::Hair(h) => h.make_mirror(hir),
384 ExprRef::Mirror(m) => *m,
389 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
390 type Output = Stmt<'tcx>;
392 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
397 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
398 type Output = Stmt<'tcx>;
400 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> {
402 StmtRef::Mirror(m) => *m,
407 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
408 type Output = Block<'tcx>;
410 fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {