1 //! THIR datatypes and definitions. See the [rustc dev guide] for more info.
3 //! If you compare the THIR [`ExprKind`] to [`hir::ExprKind`], you will see it is
4 //! a good bit simpler. In fact, a number of the more straight-forward
5 //! MIR simplifications are already done in the lowering to THIR. For
6 //! example, method calls and overloaded operators are absent: they are
7 //! expected to be converted into [`ExprKind::Call`] instances.
9 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
11 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
13 use rustc_hir::def::CtorKind;
14 use rustc_hir::def_id::DefId;
15 use rustc_hir::RangeEnd;
16 use rustc_index::newtype_index;
17 use rustc_index::vec::IndexVec;
18 use rustc_middle::middle::region;
19 use rustc_middle::mir::interpret::AllocId;
20 use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
21 use rustc_middle::ty::adjustment::PointerCast;
22 use rustc_middle::ty::subst::SubstsRef;
23 use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
24 use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
25 use rustc_span::def_id::LocalDefId;
26 use rustc_span::{Span, Symbol, DUMMY_SP};
27 use rustc_target::abi::VariantIdx;
28 use rustc_target::asm::InlineAsmRegOrRegClass;
34 macro_rules! thir_with_elements {
35 ($($name:ident: $id:ty => $value:ty => $format:literal,)*) => {
40 DEBUG_FORMAT = $format
45 /// A container for a THIR body.
47 /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
48 #[derive(Debug, HashStable, Clone)]
49 pub struct Thir<'tcx> {
51 pub $name: IndexVec<$id, $value>,
55 impl<'tcx> Thir<'tcx> {
56 pub fn new() -> Thir<'tcx> {
59 $name: IndexVec::new(),
66 impl<'tcx> Index<$id> for Thir<'tcx> {
68 fn index(&self, index: $id) -> &Self::Output {
77 arms: ArmId => Arm<'tcx> => "a{}",
78 blocks: BlockId => Block => "b{}",
79 exprs: ExprId => Expr<'tcx> => "e{}",
80 stmts: StmtId => Stmt<'tcx> => "s{}",
83 #[derive(Copy, Clone, Debug, HashStable)]
89 #[derive(Clone, Debug, HashStable)]
91 /// Whether the block itself has a label. Used by `label: {}`
94 /// This does *not* include labels on loops, e.g. `'label: loop {}`.
95 pub targeted_by_break: bool,
96 pub region_scope: region::Scope,
97 pub opt_destruction_scope: Option<region::Scope>,
98 /// The span of the block, including the opening braces,
99 /// the label, and the `unsafe` keyword, if present.
101 /// The statements in the blocK.
102 pub stmts: Box<[StmtId]>,
103 /// The trailing expression of the block, if any.
104 pub expr: Option<ExprId>,
105 pub safety_mode: BlockSafety,
108 type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>;
110 #[derive(Clone, Debug, HashStable)]
111 pub struct AdtExpr<'tcx> {
112 /// The ADT we're constructing.
113 pub adt_def: AdtDef<'tcx>,
114 /// The variant of the ADT.
115 pub variant_index: VariantIdx,
116 pub substs: SubstsRef<'tcx>,
118 /// Optional user-given substs: for something like `let x =
119 /// Bar::<T> { ... }`.
120 pub user_ty: UserTy<'tcx>,
122 pub fields: Box<[FieldExpr]>,
123 /// The base, e.g. `Foo {x: 1, .. base}`.
124 pub base: Option<FruInfo<'tcx>>,
127 #[derive(Clone, Debug, HashStable)]
128 pub struct ClosureExpr<'tcx> {
129 pub closure_id: LocalDefId,
130 pub substs: UpvarSubsts<'tcx>,
131 pub upvars: Box<[ExprId]>,
132 pub movability: Option<hir::Movability>,
133 pub fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
136 #[derive(Clone, Debug, HashStable)]
137 pub struct InlineAsmExpr<'tcx> {
138 pub template: &'tcx [InlineAsmTemplatePiece],
139 pub operands: Box<[InlineAsmOperand<'tcx>]>,
140 pub options: InlineAsmOptions,
141 pub line_spans: &'tcx [Span],
144 #[derive(Copy, Clone, Debug, HashStable)]
145 pub enum BlockSafety {
147 /// A compiler-generated unsafe block
149 /// An `unsafe` block. The `HirId` is the ID of the block.
150 ExplicitUnsafe(hir::HirId),
153 #[derive(Clone, Debug, HashStable)]
154 pub struct Stmt<'tcx> {
155 pub kind: StmtKind<'tcx>,
156 pub opt_destruction_scope: Option<region::Scope>,
159 #[derive(Clone, Debug, HashStable)]
160 pub enum StmtKind<'tcx> {
161 /// An expression with a trailing semicolon.
163 /// The scope for this statement; may be used as lifetime of temporaries.
164 scope: region::Scope,
166 /// The expression being evaluated in this statement.
172 /// The scope for variables bound in this `let`; it covers this and
173 /// all the remaining statements in the block.
174 remainder_scope: region::Scope,
176 /// The scope for the initialization itself; might be used as
177 /// lifetime of temporaries.
178 init_scope: region::Scope,
180 /// `let <PAT> = ...`
182 /// If a type annotation is included, it is added as an ascription pattern.
183 pattern: Box<Pat<'tcx>>,
185 /// `let pat: ty = <INIT>`
186 initializer: Option<ExprId>,
188 /// `let pat: ty = <INIT> else { <ELSE> }
189 else_block: Option<BlockId>,
191 /// The lint level for this `let` statement.
192 lint_level: LintLevel,
196 #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
197 #[derive(TypeFoldable, TypeVisitable)]
198 pub struct LocalVarId(pub hir::HirId);
200 /// A THIR expression.
201 #[derive(Clone, Debug, HashStable)]
202 pub struct Expr<'tcx> {
203 /// The type of this expression
206 /// The lifetime of this expression if it should be spilled into a
207 /// temporary; should be `None` only if in a constant context
208 pub temp_lifetime: Option<region::Scope>,
210 /// span of the expression in the source
213 /// kind of expression
214 pub kind: ExprKind<'tcx>,
217 #[derive(Clone, Debug, HashStable)]
218 pub enum ExprKind<'tcx> {
219 /// `Scope`s are used to explicitly mark destruction scopes,
220 /// and to track the `HirId` of the expressions within the scope.
222 region_scope: region::Scope,
223 lint_level: LintLevel,
226 /// A `box <value>` expression.
230 /// An `if` expression.
232 if_then_scope: region::Scope,
235 else_opt: Option<ExprId>,
237 /// A function call. Method calls and overloaded operators are converted to plain function calls.
239 /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
241 /// [`FnDef`]: ty::TyKind::FnDef
242 /// [`FnPtr`]: ty::TyKind::FnPtr
244 /// The function itself.
246 /// The arguments passed to the function.
248 /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
249 /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
251 /// Whether this is from an overloaded operator rather than a
252 /// function call from HIR. `true` for overloaded function call.
254 /// The span of the function, without the dot and receiver
255 /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
258 /// A *non-overloaded* dereference.
262 /// A *non-overloaded* binary operation.
268 /// A logical operation. This is distinct from `BinaryOp` because
269 /// the operands need to be lazily evaluated.
275 /// A *non-overloaded* unary operation. Note that here the deref (`*`)
276 /// operator is represented by `ExprKind::Deref`.
281 /// A cast: `<source> as <type>`. The type we cast to is the type of
282 /// the parent expression.
288 }, // Use a lexpr to get a vexpr.
289 /// A coercion from `!` to any type.
293 /// A pointer cast. More information can be found in [`PointerCast`].
298 /// A `loop` expression.
306 /// A `match` expression.
315 /// An assignment: `lhs = rhs`.
320 /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
326 /// Access to a field of a struct, a tuple, an union, or an enum.
329 /// Variant containing the field.
330 variant_index: VariantIdx,
331 /// This can be a named (`.foo`) or unnamed (`.0`) field.
334 /// A *non-overloaded* indexing operation.
339 /// A local variable.
343 /// Used to represent upvars mentioned in a closure/generator
345 /// DefId of the closure/generator
346 closure_def_id: DefId,
348 /// HirId of the root variable
349 var_hir_id: LocalVarId,
351 /// A borrow, e.g. `&arg`.
353 borrow_kind: BorrowKind,
356 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
358 mutability: hir::Mutability,
361 /// A `break` expression.
363 label: region::Scope,
364 value: Option<ExprId>,
366 /// A `continue` expression.
368 label: region::Scope,
370 /// A `return` expression.
372 value: Option<ExprId>,
374 /// An inline `const` block, e.g. `const {}`.
377 substs: SubstsRef<'tcx>,
379 /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
382 count: ty::Const<'tcx>,
384 /// An array, e.g. `[a, b, c, d]`.
386 fields: Box<[ExprId]>,
388 /// A tuple, e.g. `(a, b, c, d)`.
390 fields: Box<[ExprId]>,
392 /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
393 Adt(Box<AdtExpr<'tcx>>),
394 /// A type ascription on a place.
395 PlaceTypeAscription {
397 /// Type that the user gave to this expression
398 user_ty: UserTy<'tcx>,
400 /// A type ascription on a value, e.g. `42: i32`.
401 ValueTypeAscription {
403 /// Type that the user gave to this expression
404 user_ty: UserTy<'tcx>,
406 /// A closure definition.
407 Closure(Box<ClosureExpr<'tcx>>),
413 /// For literals that don't correspond to anything in the HIR
416 user_ty: UserTy<'tcx>,
418 /// A literal of a ZST type.
420 user_ty: UserTy<'tcx>,
422 /// Associated constants and named constants
425 substs: SubstsRef<'tcx>,
426 user_ty: UserTy<'tcx>,
429 param: ty::ParamConst,
432 // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
433 /// A literal containing the address of a `static`.
435 /// This is only distinguished from `Literal` so that we can register some
436 /// info for diagnostics.
442 /// Inline assembly, i.e. `asm!()`.
443 InlineAsm(Box<InlineAsmExpr<'tcx>>),
444 /// An expression taking a reference to a thread local.
445 ThreadLocalRef(DefId),
446 /// A `yield` expression.
452 /// Represents the association of a field identifier and an expression.
454 /// This is used in struct constructors.
455 #[derive(Clone, Debug, HashStable)]
456 pub struct FieldExpr {
461 #[derive(Clone, Debug, HashStable)]
462 pub struct FruInfo<'tcx> {
464 pub field_types: Box<[Ty<'tcx>]>,
468 #[derive(Clone, Debug, HashStable)]
469 pub struct Arm<'tcx> {
470 pub pattern: Box<Pat<'tcx>>,
471 pub guard: Option<Guard<'tcx>>,
473 pub lint_level: LintLevel,
474 pub scope: region::Scope,
479 #[derive(Clone, Debug, HashStable)]
480 pub enum Guard<'tcx> {
482 IfLet(Box<Pat<'tcx>>, ExprId),
485 #[derive(Copy, Clone, Debug, HashStable)]
487 /// The `&&` operator.
489 /// The `||` operator.
493 #[derive(Clone, Debug, HashStable)]
494 pub enum InlineAsmOperand<'tcx> {
496 reg: InlineAsmRegOrRegClass,
500 reg: InlineAsmRegOrRegClass,
502 expr: Option<ExprId>,
505 reg: InlineAsmRegOrRegClass,
510 reg: InlineAsmRegOrRegClass,
513 out_expr: Option<ExprId>,
516 value: mir::ConstantKind<'tcx>,
520 value: mir::ConstantKind<'tcx>,
528 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
529 pub enum BindingMode {
534 #[derive(Clone, Debug, HashStable)]
535 pub struct FieldPat<'tcx> {
537 pub pattern: Box<Pat<'tcx>>,
540 #[derive(Clone, Debug, HashStable)]
541 pub struct Pat<'tcx> {
544 pub kind: PatKind<'tcx>,
547 impl<'tcx> Pat<'tcx> {
548 pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
549 Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
553 #[derive(Clone, Debug, HashStable)]
554 pub struct Ascription<'tcx> {
555 pub annotation: CanonicalUserTypeAnnotation<'tcx>,
556 /// Variance to use when relating the `user_ty` to the **type of the value being
557 /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
558 /// have a type that is some subtype of the ascribed type.
560 /// Note that this variance does not apply for any bindings within subpatterns. The type
561 /// assigned to those bindings must be exactly equal to the `user_ty` given here.
563 /// The only place where this field is not `Covariant` is when matching constants, where
564 /// we currently use `Contravariant` -- this is because the constant type just needs to
565 /// be "comparable" to the type of the input value. So, for example:
568 /// match x { "foo" => .. }
571 /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
572 /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
573 /// of the old type-check for now. See #57280 for details.
574 pub variance: ty::Variance,
577 #[derive(Clone, Debug, HashStable)]
578 pub enum PatKind<'tcx> {
579 /// A wildcard pattern: `_`.
583 ascription: Ascription<'tcx>,
584 subpattern: Box<Pat<'tcx>>,
587 /// `x`, `ref x`, `x @ P`, etc.
589 mutability: Mutability,
594 subpattern: Option<Box<Pat<'tcx>>>,
595 /// Is this the leftmost occurrence of the binding, i.e., is `var` the
596 /// `HirId` of this pattern?
600 /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
601 /// multiple variants.
603 adt_def: AdtDef<'tcx>,
604 substs: SubstsRef<'tcx>,
605 variant_index: VariantIdx,
606 subpatterns: Vec<FieldPat<'tcx>>,
609 /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
610 /// a single variant.
612 subpatterns: Vec<FieldPat<'tcx>>,
615 /// `box P`, `&P`, `&mut P`, etc.
617 subpattern: Box<Pat<'tcx>>,
620 /// One of the following:
621 /// * `&str`, which will be handled as a string pattern and thus exhaustiveness
622 /// checking will detect if you use the same string twice in different patterns.
623 /// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly
624 /// its own value, similar to `&str`, but these values are much simpler.
625 /// * Opaque constants, that must not be matched structurally. So anything that does not derive
626 /// `PartialEq` and `Eq`.
628 value: mir::ConstantKind<'tcx>,
631 Range(Box<PatRange<'tcx>>),
633 /// Matches against a slice, checking the length and extracting elements.
634 /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
635 /// e.g., `&[ref xs @ ..]`.
637 prefix: Vec<Box<Pat<'tcx>>>,
638 slice: Option<Box<Pat<'tcx>>>,
639 suffix: Vec<Box<Pat<'tcx>>>,
642 /// Fixed match against an array; irrefutable.
644 prefix: Vec<Box<Pat<'tcx>>>,
645 slice: Option<Box<Pat<'tcx>>>,
646 suffix: Vec<Box<Pat<'tcx>>>,
649 /// An or-pattern, e.g. `p | q`.
650 /// Invariant: `pats.len() >= 2`.
652 pats: Vec<Box<Pat<'tcx>>>,
656 #[derive(Clone, Debug, PartialEq, HashStable)]
657 pub struct PatRange<'tcx> {
658 pub lo: mir::ConstantKind<'tcx>,
659 pub hi: mir::ConstantKind<'tcx>,
663 impl<'tcx> fmt::Display for Pat<'tcx> {
664 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
665 // Printing lists is a chore.
666 let mut first = true;
667 let mut start_or_continue = |s| {
675 let mut start_or_comma = || start_or_continue(", ");
678 PatKind::Wild => write!(f, "_"),
679 PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
680 PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
681 let is_mut = match mode {
682 BindingMode::ByValue => mutability == Mutability::Mut,
683 BindingMode::ByRef(bk) => {
685 matches!(bk, BorrowKind::Mut { .. })
691 write!(f, "{}", name)?;
692 if let Some(ref subpattern) = *subpattern {
693 write!(f, " @ {}", subpattern)?;
697 PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
698 let variant = match self.kind {
699 PatKind::Variant { adt_def, variant_index, .. } => {
700 Some(adt_def.variant(variant_index))
702 _ => self.ty.ty_adt_def().and_then(|adt| {
703 if !adt.is_enum() { Some(adt.non_enum_variant()) } else { None }
707 if let Some(variant) = variant {
708 write!(f, "{}", variant.name)?;
710 // Only for Adt we can have `S {...}`,
711 // which we handle separately here.
712 if variant.ctor_kind == CtorKind::Fictive {
716 for p in subpatterns {
717 if let PatKind::Wild = p.pattern.kind {
720 let name = variant.fields[p.field.index()].name;
721 write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
725 if printed < variant.fields.len() {
726 write!(f, "{}..", start_or_comma())?;
729 return write!(f, " }}");
733 let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len());
734 if num_fields != 0 || variant.is_none() {
736 for i in 0..num_fields {
737 write!(f, "{}", start_or_comma())?;
739 // Common case: the field is where we expect it.
740 if let Some(p) = subpatterns.get(i) {
741 if p.field.index() == i {
742 write!(f, "{}", p.pattern)?;
747 // Otherwise, we have to go looking for it.
748 if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
749 write!(f, "{}", p.pattern)?;
759 PatKind::Deref { ref subpattern } => {
760 match self.ty.kind() {
761 ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
762 ty::Ref(_, _, mutbl) => {
763 write!(f, "&{}", mutbl.prefix_str())?;
765 _ => bug!("{} is a bad Deref pattern type", self.ty),
767 write!(f, "{}", subpattern)
769 PatKind::Constant { value } => write!(f, "{}", value),
770 PatKind::Range(box PatRange { lo, hi, end }) => {
771 write!(f, "{}", lo)?;
772 write!(f, "{}", end)?;
775 PatKind::Slice { ref prefix, ref slice, ref suffix }
776 | PatKind::Array { ref prefix, ref slice, ref suffix } => {
779 write!(f, "{}{}", start_or_comma(), p)?;
781 if let Some(ref slice) = *slice {
782 write!(f, "{}", start_or_comma())?;
785 _ => write!(f, "{}", slice)?,
790 write!(f, "{}{}", start_or_comma(), p)?;
794 PatKind::Or { ref pats } => {
796 write!(f, "{}{}", start_or_continue(" | "), pat)?;
804 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
805 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
808 // These are in alphabetical order, which is easy to maintain.
809 static_assert_size!(Block, 56);
810 static_assert_size!(Expr<'_>, 64);
811 static_assert_size!(ExprKind<'_>, 40);
812 static_assert_size!(Pat<'_>, 80);
813 static_assert_size!(PatKind<'_>, 64);
814 static_assert_size!(Stmt<'_>, 56);
815 static_assert_size!(StmtKind<'_>, 48);