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};
12 use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
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::{sym, 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,)*) => {
39 #[debug_format = $format]
44 /// A container for a THIR body.
46 /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
47 #[derive(Debug, HashStable, Clone)]
48 pub struct Thir<'tcx> {
50 pub $name: IndexVec<$id, $value>,
54 impl<'tcx> Thir<'tcx> {
55 pub fn new() -> Thir<'tcx> {
58 $name: IndexVec::new(),
65 impl<'tcx> Index<$id> for Thir<'tcx> {
67 fn index(&self, index: $id) -> &Self::Output {
75 pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
78 arms: ArmId => Arm<'tcx> => "a{}",
79 blocks: BlockId => Block => "b{}",
80 exprs: ExprId => Expr<'tcx> => "e{}",
81 stmts: StmtId => Stmt<'tcx> => "s{}",
82 params: ParamId => Param<'tcx> => "p{}",
85 /// Description of a type-checked function parameter.
86 #[derive(Clone, Debug, HashStable)]
87 pub struct Param<'tcx> {
88 /// The pattern that appears in the parameter list, or None for implicit parameters.
89 pub pat: Option<Box<Pat<'tcx>>>,
90 /// The possibly inferred type.
92 /// Span of the explicitly provided type, or None if inferred for closures.
93 pub ty_span: Option<Span>,
94 /// Whether this param is `self`, and how it is bound.
95 pub self_kind: Option<hir::ImplicitSelfKind>,
97 pub hir_id: Option<hir::HirId>,
100 #[derive(Copy, Clone, Debug, HashStable)]
103 Explicit(hir::HirId),
106 #[derive(Clone, Debug, HashStable)]
108 /// Whether the block itself has a label. Used by `label: {}`
109 /// and `try` blocks.
111 /// This does *not* include labels on loops, e.g. `'label: loop {}`.
112 pub targeted_by_break: bool,
113 pub region_scope: region::Scope,
114 pub opt_destruction_scope: Option<region::Scope>,
115 /// The span of the block, including the opening braces,
116 /// the label, and the `unsafe` keyword, if present.
118 /// The statements in the blocK.
119 pub stmts: Box<[StmtId]>,
120 /// The trailing expression of the block, if any.
121 pub expr: Option<ExprId>,
122 pub safety_mode: BlockSafety,
125 type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>;
127 #[derive(Clone, Debug, HashStable)]
128 pub struct AdtExpr<'tcx> {
129 /// The ADT we're constructing.
130 pub adt_def: AdtDef<'tcx>,
131 /// The variant of the ADT.
132 pub variant_index: VariantIdx,
133 pub substs: SubstsRef<'tcx>,
135 /// Optional user-given substs: for something like `let x =
136 /// Bar::<T> { ... }`.
137 pub user_ty: UserTy<'tcx>,
139 pub fields: Box<[FieldExpr]>,
140 /// The base, e.g. `Foo {x: 1, .. base}`.
141 pub base: Option<FruInfo<'tcx>>,
144 #[derive(Clone, Debug, HashStable)]
145 pub struct ClosureExpr<'tcx> {
146 pub closure_id: LocalDefId,
147 pub substs: UpvarSubsts<'tcx>,
148 pub upvars: Box<[ExprId]>,
149 pub movability: Option<hir::Movability>,
150 pub fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
153 #[derive(Clone, Debug, HashStable)]
154 pub struct InlineAsmExpr<'tcx> {
155 pub template: &'tcx [InlineAsmTemplatePiece],
156 pub operands: Box<[InlineAsmOperand<'tcx>]>,
157 pub options: InlineAsmOptions,
158 pub line_spans: &'tcx [Span],
161 #[derive(Copy, Clone, Debug, HashStable)]
162 pub enum BlockSafety {
164 /// A compiler-generated unsafe block
166 /// An `unsafe` block. The `HirId` is the ID of the block.
167 ExplicitUnsafe(hir::HirId),
170 #[derive(Clone, Debug, HashStable)]
171 pub struct Stmt<'tcx> {
172 pub kind: StmtKind<'tcx>,
173 pub opt_destruction_scope: Option<region::Scope>,
176 #[derive(Clone, Debug, HashStable)]
177 pub enum StmtKind<'tcx> {
178 /// An expression with a trailing semicolon.
180 /// The scope for this statement; may be used as lifetime of temporaries.
181 scope: region::Scope,
183 /// The expression being evaluated in this statement.
189 /// The scope for variables bound in this `let`; it covers this and
190 /// all the remaining statements in the block.
191 remainder_scope: region::Scope,
193 /// The scope for the initialization itself; might be used as
194 /// lifetime of temporaries.
195 init_scope: region::Scope,
197 /// `let <PAT> = ...`
199 /// If a type annotation is included, it is added as an ascription pattern.
200 pattern: Box<Pat<'tcx>>,
202 /// `let pat: ty = <INIT>`
203 initializer: Option<ExprId>,
205 /// `let pat: ty = <INIT> else { <ELSE> }`
206 else_block: Option<BlockId>,
208 /// The lint level for this `let` statement.
209 lint_level: LintLevel,
213 #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
214 #[derive(TypeFoldable, TypeVisitable)]
215 pub struct LocalVarId(pub hir::HirId);
217 /// A THIR expression.
218 #[derive(Clone, Debug, HashStable)]
219 pub struct Expr<'tcx> {
220 /// The type of this expression
223 /// The lifetime of this expression if it should be spilled into a
224 /// temporary; should be `None` only if in a constant context
225 pub temp_lifetime: Option<region::Scope>,
227 /// span of the expression in the source
230 /// kind of expression
231 pub kind: ExprKind<'tcx>,
234 #[derive(Clone, Debug, HashStable)]
235 pub enum ExprKind<'tcx> {
236 /// `Scope`s are used to explicitly mark destruction scopes,
237 /// and to track the `HirId` of the expressions within the scope.
239 region_scope: region::Scope,
240 lint_level: LintLevel,
243 /// A `box <value>` expression.
247 /// An `if` expression.
249 if_then_scope: region::Scope,
252 else_opt: Option<ExprId>,
254 /// A function call. Method calls and overloaded operators are converted to plain function calls.
256 /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
258 /// [`FnDef`]: ty::TyKind::FnDef
259 /// [`FnPtr`]: ty::TyKind::FnPtr
261 /// The function itself.
263 /// The arguments passed to the function.
265 /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
266 /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
268 /// Whether this is from an overloaded operator rather than a
269 /// function call from HIR. `true` for overloaded function call.
271 /// The span of the function, without the dot and receiver
272 /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
275 /// A *non-overloaded* dereference.
279 /// A *non-overloaded* binary operation.
285 /// A logical operation. This is distinct from `BinaryOp` because
286 /// the operands need to be lazily evaluated.
292 /// A *non-overloaded* unary operation. Note that here the deref (`*`)
293 /// operator is represented by `ExprKind::Deref`.
298 /// A cast: `<source> as <type>`. The type we cast to is the type of
299 /// the parent expression.
305 }, // Use a lexpr to get a vexpr.
306 /// A coercion from `!` to any type.
310 /// A pointer cast. More information can be found in [`PointerCast`].
315 /// A `loop` expression.
323 /// A `match` expression.
332 /// An assignment: `lhs = rhs`.
337 /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
343 /// Access to a field of a struct, a tuple, an union, or an enum.
346 /// Variant containing the field.
347 variant_index: VariantIdx,
348 /// This can be a named (`.foo`) or unnamed (`.0`) field.
351 /// A *non-overloaded* indexing operation.
356 /// A local variable.
360 /// Used to represent upvars mentioned in a closure/generator
362 /// DefId of the closure/generator
363 closure_def_id: DefId,
365 /// HirId of the root variable
366 var_hir_id: LocalVarId,
368 /// A borrow, e.g. `&arg`.
370 borrow_kind: BorrowKind,
373 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
375 mutability: hir::Mutability,
378 /// A `break` expression.
380 label: region::Scope,
381 value: Option<ExprId>,
383 /// A `continue` expression.
385 label: region::Scope,
387 /// A `return` expression.
389 value: Option<ExprId>,
391 /// An inline `const` block, e.g. `const {}`.
394 substs: SubstsRef<'tcx>,
396 /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
399 count: ty::Const<'tcx>,
401 /// An array, e.g. `[a, b, c, d]`.
403 fields: Box<[ExprId]>,
405 /// A tuple, e.g. `(a, b, c, d)`.
407 fields: Box<[ExprId]>,
409 /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
410 Adt(Box<AdtExpr<'tcx>>),
411 /// A type ascription on a place.
412 PlaceTypeAscription {
414 /// Type that the user gave to this expression
415 user_ty: UserTy<'tcx>,
417 /// A type ascription on a value, e.g. `42: i32`.
418 ValueTypeAscription {
420 /// Type that the user gave to this expression
421 user_ty: UserTy<'tcx>,
423 /// A closure definition.
424 Closure(Box<ClosureExpr<'tcx>>),
430 /// For literals that don't correspond to anything in the HIR
433 user_ty: UserTy<'tcx>,
435 /// A literal of a ZST type.
437 user_ty: UserTy<'tcx>,
439 /// Associated constants and named constants
442 substs: SubstsRef<'tcx>,
443 user_ty: UserTy<'tcx>,
446 param: ty::ParamConst,
449 // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
450 /// A literal containing the address of a `static`.
452 /// This is only distinguished from `Literal` so that we can register some
453 /// info for diagnostics.
459 /// Inline assembly, i.e. `asm!()`.
460 InlineAsm(Box<InlineAsmExpr<'tcx>>),
461 /// An expression taking a reference to a thread local.
462 ThreadLocalRef(DefId),
463 /// A `yield` expression.
469 /// Represents the association of a field identifier and an expression.
471 /// This is used in struct constructors.
472 #[derive(Clone, Debug, HashStable)]
473 pub struct FieldExpr {
478 #[derive(Clone, Debug, HashStable)]
479 pub struct FruInfo<'tcx> {
481 pub field_types: Box<[Ty<'tcx>]>,
485 #[derive(Clone, Debug, HashStable)]
486 pub struct Arm<'tcx> {
487 pub pattern: Box<Pat<'tcx>>,
488 pub guard: Option<Guard<'tcx>>,
490 pub lint_level: LintLevel,
491 pub scope: region::Scope,
496 #[derive(Clone, Debug, HashStable)]
497 pub enum Guard<'tcx> {
499 IfLet(Box<Pat<'tcx>>, ExprId),
502 #[derive(Copy, Clone, Debug, HashStable)]
504 /// The `&&` operator.
506 /// The `||` operator.
510 #[derive(Clone, Debug, HashStable)]
511 pub enum InlineAsmOperand<'tcx> {
513 reg: InlineAsmRegOrRegClass,
517 reg: InlineAsmRegOrRegClass,
519 expr: Option<ExprId>,
522 reg: InlineAsmRegOrRegClass,
527 reg: InlineAsmRegOrRegClass,
530 out_expr: Option<ExprId>,
533 value: mir::ConstantKind<'tcx>,
537 value: mir::ConstantKind<'tcx>,
545 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
546 pub enum BindingMode {
551 #[derive(Clone, Debug, HashStable)]
552 pub struct FieldPat<'tcx> {
554 pub pattern: Box<Pat<'tcx>>,
557 #[derive(Clone, Debug, HashStable)]
558 pub struct Pat<'tcx> {
561 pub kind: PatKind<'tcx>,
564 impl<'tcx> Pat<'tcx> {
565 pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
566 Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
569 pub fn simple_ident(&self) -> Option<Symbol> {
571 PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => {
579 impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
580 fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
581 format!("{}", self).into_diagnostic_arg()
585 #[derive(Clone, Debug, HashStable)]
586 pub struct Ascription<'tcx> {
587 pub annotation: CanonicalUserTypeAnnotation<'tcx>,
588 /// Variance to use when relating the `user_ty` to the **type of the value being
589 /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
590 /// have a type that is some subtype of the ascribed type.
592 /// Note that this variance does not apply for any bindings within subpatterns. The type
593 /// assigned to those bindings must be exactly equal to the `user_ty` given here.
595 /// The only place where this field is not `Covariant` is when matching constants, where
596 /// we currently use `Contravariant` -- this is because the constant type just needs to
597 /// be "comparable" to the type of the input value. So, for example:
600 /// match x { "foo" => .. }
603 /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
604 /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
605 /// of the old type-check for now. See #57280 for details.
606 pub variance: ty::Variance,
609 #[derive(Clone, Debug, HashStable)]
610 pub enum PatKind<'tcx> {
611 /// A wildcard pattern: `_`.
615 ascription: Ascription<'tcx>,
616 subpattern: Box<Pat<'tcx>>,
619 /// `x`, `ref x`, `x @ P`, etc.
621 mutability: Mutability,
626 subpattern: Option<Box<Pat<'tcx>>>,
627 /// Is this the leftmost occurrence of the binding, i.e., is `var` the
628 /// `HirId` of this pattern?
632 /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
633 /// multiple variants.
635 adt_def: AdtDef<'tcx>,
636 substs: SubstsRef<'tcx>,
637 variant_index: VariantIdx,
638 subpatterns: Vec<FieldPat<'tcx>>,
641 /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
642 /// a single variant.
644 subpatterns: Vec<FieldPat<'tcx>>,
647 /// `box P`, `&P`, `&mut P`, etc.
649 subpattern: Box<Pat<'tcx>>,
652 /// One of the following:
653 /// * `&str`, which will be handled as a string pattern and thus exhaustiveness
654 /// checking will detect if you use the same string twice in different patterns.
655 /// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly
656 /// its own value, similar to `&str`, but these values are much simpler.
657 /// * Opaque constants, that must not be matched structurally. So anything that does not derive
658 /// `PartialEq` and `Eq`.
660 value: mir::ConstantKind<'tcx>,
663 Range(Box<PatRange<'tcx>>),
665 /// Matches against a slice, checking the length and extracting elements.
666 /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
667 /// e.g., `&[ref xs @ ..]`.
669 prefix: Box<[Box<Pat<'tcx>>]>,
670 slice: Option<Box<Pat<'tcx>>>,
671 suffix: Box<[Box<Pat<'tcx>>]>,
674 /// Fixed match against an array; irrefutable.
676 prefix: Box<[Box<Pat<'tcx>>]>,
677 slice: Option<Box<Pat<'tcx>>>,
678 suffix: Box<[Box<Pat<'tcx>>]>,
681 /// An or-pattern, e.g. `p | q`.
682 /// Invariant: `pats.len() >= 2`.
684 pats: Box<[Box<Pat<'tcx>>]>,
688 #[derive(Clone, Debug, PartialEq, HashStable)]
689 pub struct PatRange<'tcx> {
690 pub lo: mir::ConstantKind<'tcx>,
691 pub hi: mir::ConstantKind<'tcx>,
695 impl<'tcx> fmt::Display for Pat<'tcx> {
696 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
697 // Printing lists is a chore.
698 let mut first = true;
699 let mut start_or_continue = |s| {
707 let mut start_or_comma = || start_or_continue(", ");
710 PatKind::Wild => write!(f, "_"),
711 PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
712 PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
713 let is_mut = match mode {
714 BindingMode::ByValue => mutability == Mutability::Mut,
715 BindingMode::ByRef(bk) => {
717 matches!(bk, BorrowKind::Mut { .. })
723 write!(f, "{}", name)?;
724 if let Some(ref subpattern) = *subpattern {
725 write!(f, " @ {}", subpattern)?;
729 PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
730 let variant_and_name = match self.kind {
731 PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
732 let variant = adt_def.variant(variant_index);
733 let adt_did = adt_def.did();
734 let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
735 || tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
737 variant.name.to_string()
739 format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
741 Some((variant, name))
743 _ => self.ty.ty_adt_def().and_then(|adt_def| {
744 if !adt_def.is_enum() {
745 ty::tls::with(|tcx| {
746 Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
754 if let Some((variant, name)) = &variant_and_name {
755 write!(f, "{}", name)?;
757 // Only for Adt we can have `S {...}`,
758 // which we handle separately here.
759 if variant.ctor.is_none() {
763 for p in subpatterns {
764 if let PatKind::Wild = p.pattern.kind {
767 let name = variant.fields[p.field.index()].name;
768 write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
772 if printed < variant.fields.len() {
773 write!(f, "{}..", start_or_comma())?;
776 return write!(f, " }}");
781 variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
782 if num_fields != 0 || variant_and_name.is_none() {
784 for i in 0..num_fields {
785 write!(f, "{}", start_or_comma())?;
787 // Common case: the field is where we expect it.
788 if let Some(p) = subpatterns.get(i) {
789 if p.field.index() == i {
790 write!(f, "{}", p.pattern)?;
795 // Otherwise, we have to go looking for it.
796 if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
797 write!(f, "{}", p.pattern)?;
807 PatKind::Deref { ref subpattern } => {
808 match self.ty.kind() {
809 ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
810 ty::Ref(_, _, mutbl) => {
811 write!(f, "&{}", mutbl.prefix_str())?;
813 _ => bug!("{} is a bad Deref pattern type", self.ty),
815 write!(f, "{}", subpattern)
817 PatKind::Constant { value } => write!(f, "{}", value),
818 PatKind::Range(box PatRange { lo, hi, end }) => {
819 write!(f, "{}", lo)?;
820 write!(f, "{}", end)?;
823 PatKind::Slice { ref prefix, ref slice, ref suffix }
824 | PatKind::Array { ref prefix, ref slice, ref suffix } => {
826 for p in prefix.iter() {
827 write!(f, "{}{}", start_or_comma(), p)?;
829 if let Some(ref slice) = *slice {
830 write!(f, "{}", start_or_comma())?;
833 _ => write!(f, "{}", slice)?,
837 for p in suffix.iter() {
838 write!(f, "{}{}", start_or_comma(), p)?;
842 PatKind::Or { ref pats } => {
843 for pat in pats.iter() {
844 write!(f, "{}{}", start_or_continue(" | "), pat)?;
852 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
853 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
856 // tidy-alphabetical-start
857 static_assert_size!(Block, 56);
858 static_assert_size!(Expr<'_>, 64);
859 static_assert_size!(ExprKind<'_>, 40);
860 static_assert_size!(Pat<'_>, 72);
861 static_assert_size!(PatKind<'_>, 56);
862 static_assert_size!(Stmt<'_>, 48);
863 static_assert_size!(StmtKind<'_>, 40);
864 // tidy-alphabetical-end