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
9 use rustc::hir::def_id::DefId;
10 use rustc::infer::canonical::Canonical;
11 use rustc::middle::region;
12 use rustc::mir::{BinOp, BorrowKind, Field, UnOp};
13 use rustc::ty::adjustment::PointerCast;
14 use rustc::ty::layout::VariantIdx;
15 use rustc::ty::subst::SubstsRef;
16 use rustc::ty::{AdtDef, Const, Ty, UpvarSubsts, UserType};
23 pub(crate) use self::pattern::PatTyProj;
24 pub use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
28 #[derive(Copy, Clone, Debug)]
34 #[derive(Clone, Debug)]
35 pub struct Block<'tcx> {
36 pub targeted_by_break: bool,
37 pub region_scope: region::Scope,
38 pub opt_destruction_scope: Option<region::Scope>,
40 pub stmts: Vec<StmtRef<'tcx>>,
41 pub expr: Option<ExprRef<'tcx>>,
42 pub safety_mode: BlockSafety,
45 #[derive(Copy, Clone, Debug)]
46 pub enum BlockSafety {
48 ExplicitUnsafe(hir::HirId),
53 #[derive(Clone, Debug)]
54 pub enum StmtRef<'tcx> {
55 Mirror(Box<Stmt<'tcx>>),
58 #[derive(Clone, Debug)]
59 pub struct Stmt<'tcx> {
60 pub kind: StmtKind<'tcx>,
61 pub opt_destruction_scope: Option<region::Scope>,
64 #[derive(Clone, Debug)]
65 pub enum StmtKind<'tcx> {
67 /// scope for this statement; may be used as lifetime of temporaries
70 /// expression being evaluated in this statement
75 /// scope for variables bound in this let; covers this and
76 /// remaining statements in block
77 remainder_scope: region::Scope,
79 /// scope for the initialization itself; might be used as
80 /// lifetime of temporaries
81 init_scope: region::Scope,
85 /// if a type is included, it is added as an ascription pattern
88 /// let pat: ty = <INIT> ...
89 initializer: Option<ExprRef<'tcx>>,
91 /// the lint level for this let-statement
92 lint_level: LintLevel,
96 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
97 #[cfg(target_arch = "x86_64")]
98 rustc_data_structures::static_assert_size!(Expr<'_>, 168);
100 /// The Hair trait implementor lowers their expressions (`&'tcx H::Expr`)
101 /// into instances of this `Expr` enum. This lowering can be done
102 /// basically as lazily or as eagerly as desired: every recursive
103 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
104 /// may in turn be another instance of this enum (boxed), or else an
105 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
106 /// short-lived. They are created by `Hair::to_expr`, analyzed and
107 /// converted into MIR, and then discarded.
109 /// If you compare `Expr` to the full compiler AST, you will see it is
110 /// a good bit simpler. In fact, a number of the more straight-forward
111 /// MIR simplifications are already done in the impl of `Hair`. For
112 /// example, method calls and overloaded operators are absent: they are
113 /// expected to be converted into `Expr::Call` instances.
114 #[derive(Clone, Debug)]
115 pub struct Expr<'tcx> {
116 /// type of this expression
119 /// lifetime of this expression if it should be spilled into a
120 /// temporary; should be None only if in a constant context
121 pub temp_lifetime: Option<region::Scope>,
123 /// span of the expression in the source
126 /// kind of expression
127 pub kind: ExprKind<'tcx>,
130 #[derive(Clone, Debug)]
131 pub enum ExprKind<'tcx> {
133 region_scope: region::Scope,
134 lint_level: LintLevel,
135 value: ExprRef<'tcx>,
138 value: ExprRef<'tcx>,
143 args: Vec<ExprRef<'tcx>>,
144 // Whether this is from a call in HIR, rather than from an overloaded
145 // operator. True for overloaded function call.
150 }, // NOT overloaded!
155 }, // NOT overloaded!
160 }, // NOT overloaded!
161 // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
165 }, // NOT overloaded!
167 source: ExprRef<'tcx>,
170 source: ExprRef<'tcx>,
171 }, // Use a lexpr to get a vexpr.
173 source: ExprRef<'tcx>,
177 source: ExprRef<'tcx>,
183 scrutinee: ExprRef<'tcx>,
184 arms: Vec<Arm<'tcx>>,
187 body: &'tcx hir::Block,
204 index: ExprRef<'tcx>,
209 /// first argument, used for self in a closure
212 borrow_kind: BorrowKind,
215 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
217 mutability: hir::Mutability,
221 label: region::Scope,
222 value: Option<ExprRef<'tcx>>,
225 label: region::Scope,
228 value: Option<ExprRef<'tcx>>,
231 value: ExprRef<'tcx>,
235 fields: Vec<ExprRef<'tcx>>,
238 fields: Vec<ExprRef<'tcx>>,
241 adt_def: &'tcx AdtDef,
242 variant_index: VariantIdx,
243 substs: SubstsRef<'tcx>,
245 /// Optional user-given substs: for something like `let x =
246 /// Bar::<T> { ... }`.
247 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
249 fields: Vec<FieldExprRef<'tcx>>,
250 base: Option<FruInfo<'tcx>>,
252 PlaceTypeAscription {
253 source: ExprRef<'tcx>,
254 /// Type that the user gave to this expression
255 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
257 ValueTypeAscription {
258 source: ExprRef<'tcx>,
259 /// Type that the user gave to this expression
260 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
264 substs: UpvarSubsts<'tcx>,
265 upvars: Vec<ExprRef<'tcx>>,
266 movability: Option<hir::Movability>,
269 literal: &'tcx Const<'tcx>,
270 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
272 /// A literal containing the address of a `static`.
274 /// This is only distinguished from `Literal` so that we can register some
275 /// info for diagnostics.
277 literal: &'tcx Const<'tcx>,
281 asm: &'tcx hir::InlineAsmInner,
282 outputs: Vec<ExprRef<'tcx>>,
283 inputs: Vec<ExprRef<'tcx>>,
286 value: ExprRef<'tcx>,
290 #[derive(Clone, Debug)]
291 pub enum ExprRef<'tcx> {
292 Hair(&'tcx hir::Expr),
293 Mirror(Box<Expr<'tcx>>),
296 #[derive(Clone, Debug)]
297 pub struct FieldExprRef<'tcx> {
299 pub expr: ExprRef<'tcx>,
302 #[derive(Clone, Debug)]
303 pub struct FruInfo<'tcx> {
304 pub base: ExprRef<'tcx>,
305 pub field_types: Vec<Ty<'tcx>>,
308 #[derive(Clone, Debug)]
309 pub struct Arm<'tcx> {
310 pub pattern: Pat<'tcx>,
311 pub guard: Option<Guard<'tcx>>,
312 pub body: ExprRef<'tcx>,
313 pub lint_level: LintLevel,
314 pub scope: region::Scope,
319 // HACK(or_patterns; Centril | dlrobertson): Remove this and
320 // correctly handle each case in which this method is used.
321 pub fn top_pats_hack(&self) -> &[Pat<'tcx>] {
322 match &*self.pattern.kind {
323 PatKind::Or { pats } => pats,
324 _ => std::slice::from_ref(&self.pattern),
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(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
370 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
371 type Output = Expr<'tcx>;
373 fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
378 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
379 type Output = Expr<'tcx>;
381 fn make_mirror(self, hir: &mut Cx<'a, '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(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
397 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
398 type Output = Stmt<'tcx>;
400 fn make_mirror(self, _: &mut Cx<'_, '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(self, _: &mut Cx<'_, 'tcx>) -> Block<'tcx> {