1 //! The MIR is built from some typed high-level IR
2 //! (THIR). This section defines the THIR 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
8 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
10 use rustc_hir::def_id::DefId;
11 use rustc_middle::infer::canonical::Canonical;
12 use rustc_middle::middle::region;
13 use rustc_middle::mir::{BinOp, BorrowKind, Field, UnOp};
14 use rustc_middle::ty::adjustment::PointerCast;
15 use rustc_middle::ty::subst::SubstsRef;
16 use rustc_middle::ty::{AdtDef, Const, Ty, UpvarSubsts, UserType};
18 use rustc_target::abi::VariantIdx;
19 use rustc_target::asm::InlineAsmRegOrRegClass;
25 crate use self::pattern::PatTyProj;
26 crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
30 #[derive(Copy, Clone, Debug)]
31 crate enum LintLevel {
36 #[derive(Clone, Debug)]
37 crate struct Block<'tcx> {
38 crate targeted_by_break: bool,
39 crate region_scope: region::Scope,
40 crate opt_destruction_scope: Option<region::Scope>,
42 crate stmts: Vec<StmtRef<'tcx>>,
43 crate expr: Option<ExprRef<'tcx>>,
44 crate safety_mode: BlockSafety,
47 #[derive(Copy, Clone, Debug)]
48 crate enum BlockSafety {
50 ExplicitUnsafe(hir::HirId),
55 #[derive(Clone, Debug)]
56 crate enum StmtRef<'tcx> {
57 Mirror(Box<Stmt<'tcx>>),
60 #[derive(Clone, Debug)]
61 crate struct Stmt<'tcx> {
62 crate kind: StmtKind<'tcx>,
63 crate opt_destruction_scope: Option<region::Scope>,
66 #[derive(Clone, Debug)]
67 crate enum StmtKind<'tcx> {
69 /// scope for this statement; may be used as lifetime of temporaries
72 /// expression being evaluated in this statement
77 /// scope for variables bound in this let; covers this and
78 /// remaining statements in block
79 remainder_scope: region::Scope,
81 /// scope for the initialization itself; might be used as
82 /// lifetime of temporaries
83 init_scope: region::Scope,
87 /// if a type is included, it is added as an ascription pattern
90 /// let pat: ty = <INIT> ...
91 initializer: Option<ExprRef<'tcx>>,
93 /// the lint level for this let-statement
94 lint_level: LintLevel,
98 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
99 #[cfg(target_arch = "x86_64")]
100 rustc_data_structures::static_assert_size!(Expr<'_>, 168);
102 /// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
103 /// into instances of this `Expr` enum. This lowering can be done
104 /// basically as lazily or as eagerly as desired: every recursive
105 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
106 /// may in turn be another instance of this enum (boxed), or else an
107 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
108 /// short-lived. They are created by `Thir::to_expr`, analyzed and
109 /// converted into MIR, and then discarded.
111 /// If you compare `Expr` to the full compiler AST, you will see it is
112 /// a good bit simpler. In fact, a number of the more straight-forward
113 /// MIR simplifications are already done in the impl of `Thir`. For
114 /// example, method calls and overloaded operators are absent: they are
115 /// expected to be converted into `Expr::Call` instances.
116 #[derive(Clone, Debug)]
117 crate struct Expr<'tcx> {
118 /// type of this expression
121 /// lifetime of this expression if it should be spilled into a
122 /// temporary; should be None only if in a constant context
123 crate temp_lifetime: Option<region::Scope>,
125 /// span of the expression in the source
128 /// kind of expression
129 crate kind: ExprKind<'tcx>,
132 #[derive(Clone, Debug)]
133 crate enum ExprKind<'tcx> {
135 region_scope: region::Scope,
136 lint_level: LintLevel,
137 value: ExprRef<'tcx>,
140 value: ExprRef<'tcx>,
145 args: Vec<ExprRef<'tcx>>,
146 // Whether this is from a call in HIR, rather than from an overloaded
147 // operator. True for overloaded function call.
149 /// This `Span` is the span of the function, without the dot and receiver
150 /// (e.g. `foo(a, b)` in `x.foo(a, b)`
155 }, // NOT overloaded!
160 }, // NOT overloaded!
165 }, // NOT overloaded!
166 // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
170 }, // NOT overloaded!
172 source: ExprRef<'tcx>,
175 source: ExprRef<'tcx>,
176 }, // Use a lexpr to get a vexpr.
178 source: ExprRef<'tcx>,
182 source: ExprRef<'tcx>,
188 scrutinee: ExprRef<'tcx>,
189 arms: Vec<Arm<'tcx>>,
192 body: &'tcx hir::Block<'tcx>,
209 index: ExprRef<'tcx>,
214 /// Used to represent upvars mentioned in a closure/generator
216 /// DefId of the closure/generator
217 closure_def_id: DefId,
219 /// HirId of the root variable
220 var_hir_id: hir::HirId,
222 /// first argument, used for self in a closure
225 borrow_kind: BorrowKind,
228 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
230 mutability: hir::Mutability,
234 label: region::Scope,
235 value: Option<ExprRef<'tcx>>,
238 label: region::Scope,
241 value: Option<ExprRef<'tcx>>,
244 value: &'tcx Const<'tcx>,
247 value: ExprRef<'tcx>,
248 count: &'tcx Const<'tcx>,
251 fields: Vec<ExprRef<'tcx>>,
254 fields: Vec<ExprRef<'tcx>>,
257 adt_def: &'tcx AdtDef,
258 variant_index: VariantIdx,
259 substs: SubstsRef<'tcx>,
261 /// Optional user-given substs: for something like `let x =
262 /// Bar::<T> { ... }`.
263 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
265 fields: Vec<FieldExprRef<'tcx>>,
266 base: Option<FruInfo<'tcx>>,
268 PlaceTypeAscription {
269 source: ExprRef<'tcx>,
270 /// Type that the user gave to this expression
271 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
273 ValueTypeAscription {
274 source: ExprRef<'tcx>,
275 /// Type that the user gave to this expression
276 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
280 substs: UpvarSubsts<'tcx>,
281 upvars: Vec<ExprRef<'tcx>>,
282 movability: Option<hir::Movability>,
285 literal: &'tcx Const<'tcx>,
286 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
287 /// The `DefId` of the `const` item this literal
288 /// was produced from, if this is not a user-written
290 const_id: Option<DefId>,
292 /// A literal containing the address of a `static`.
294 /// This is only distinguished from `Literal` so that we can register some
295 /// info for diagnostics.
297 literal: &'tcx Const<'tcx>,
301 template: &'tcx [InlineAsmTemplatePiece],
302 operands: Vec<InlineAsmOperand<'tcx>>,
303 options: InlineAsmOptions,
304 line_spans: &'tcx [Span],
306 /// An expression taking a reference to a thread local.
307 ThreadLocalRef(DefId),
309 asm: &'tcx hir::LlvmInlineAsmInner,
310 outputs: Vec<ExprRef<'tcx>>,
311 inputs: Vec<ExprRef<'tcx>>,
314 value: ExprRef<'tcx>,
318 #[derive(Clone, Debug)]
319 crate enum ExprRef<'tcx> {
320 Thir(&'tcx hir::Expr<'tcx>),
321 Mirror(Box<Expr<'tcx>>),
324 #[derive(Clone, Debug)]
325 crate struct FieldExprRef<'tcx> {
327 crate expr: ExprRef<'tcx>,
330 #[derive(Clone, Debug)]
331 crate struct FruInfo<'tcx> {
332 crate base: ExprRef<'tcx>,
333 crate field_types: Vec<Ty<'tcx>>,
336 #[derive(Clone, Debug)]
337 crate struct Arm<'tcx> {
338 crate pattern: Pat<'tcx>,
339 crate guard: Option<Guard<'tcx>>,
340 crate body: ExprRef<'tcx>,
341 crate lint_level: LintLevel,
342 crate scope: region::Scope,
346 #[derive(Clone, Debug)]
347 crate enum Guard<'tcx> {
351 #[derive(Copy, Clone, Debug)]
352 crate enum LogicalOp {
357 impl<'tcx> ExprRef<'tcx> {
358 crate fn span(&self) -> Span {
360 ExprRef::Thir(expr) => expr.span,
361 ExprRef::Mirror(expr) => expr.span,
366 #[derive(Clone, Debug)]
367 crate enum InlineAsmOperand<'tcx> {
369 reg: InlineAsmRegOrRegClass,
373 reg: InlineAsmRegOrRegClass,
375 expr: Option<ExprRef<'tcx>>,
378 reg: InlineAsmRegOrRegClass,
383 reg: InlineAsmRegOrRegClass,
385 in_expr: ExprRef<'tcx>,
386 out_expr: Option<ExprRef<'tcx>>,
399 ///////////////////////////////////////////////////////////////////////////
402 /// "Mirroring" is the process of converting from a HIR type into one
403 /// of the THIR types defined in this file. This is basically a "on
404 /// the fly" desugaring step that hides a lot of the messiness in the
405 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
408 /// Mirroring is gradual: when you mirror an outer expression like `e1
409 /// + e2`, the references to the inner expressions `e1` and `e2` are
410 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
411 /// mirrored. This allows a single AST node from the compiler to
412 /// expand into one or more Thir nodes, which lets the Thir nodes be
414 crate trait Mirror<'tcx> {
417 fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
420 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
421 type Output = Expr<'tcx>;
423 fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
428 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
429 type Output = Expr<'tcx>;
431 fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
433 ExprRef::Thir(h) => h.make_mirror(hir),
434 ExprRef::Mirror(m) => *m,
439 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
440 type Output = Stmt<'tcx>;
442 fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
447 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
448 type Output = Stmt<'tcx>;
450 fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
452 StmtRef::Mirror(m) => *m,
457 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
458 type Output = Block<'tcx>;
460 fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Block<'tcx> {