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::infer::canonical::Canonical;
19 use rustc_middle::middle::region;
20 use rustc_middle::mir::{
21 BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp, UserTypeProjection,
23 use rustc_middle::ty::adjustment::PointerCast;
24 use rustc_middle::ty::subst::SubstsRef;
25 use rustc_middle::ty::{self, AdtDef, Const, Ty, UpvarSubsts, UserType};
26 use rustc_middle::ty::{
27 CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
29 use rustc_span::{Span, Symbol, DUMMY_SP};
30 use rustc_target::abi::VariantIdx;
31 use rustc_target::asm::InlineAsmRegOrRegClass;
36 pub mod abstract_const;
40 /// An index to an [`Arm`] stored in [`Thir::arms`]
48 /// An index to an [`Expr`] stored in [`Thir::exprs`]
57 /// An index to a [`Stmt`] stored in [`Thir::stmts`]
63 macro_rules! thir_with_elements {
64 ($($name:ident: $id:ty => $value:ty,)*) => {
65 /// A container for a THIR body.
67 /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
68 #[derive(Debug, HashStable)]
69 pub struct Thir<'tcx> {
71 pub $name: IndexVec<$id, $value>,
75 impl<'tcx> Thir<'tcx> {
76 pub fn new() -> Thir<'tcx> {
79 $name: IndexVec::new(),
86 impl<'tcx> Index<$id> for Thir<'tcx> {
88 fn index(&self, index: $id) -> &Self::Output {
97 arms: ArmId => Arm<'tcx>,
98 exprs: ExprId => Expr<'tcx>,
99 stmts: StmtId => Stmt<'tcx>,
102 #[derive(Copy, Clone, Debug, HashStable)]
105 Explicit(hir::HirId),
108 #[derive(Debug, HashStable)]
110 /// Whether the block itself has a label. Used by `label: {}`
111 /// and `try` blocks.
113 /// This does *not* include labels on loops, e.g. `'label: loop {}`.
114 pub targeted_by_break: bool,
115 pub region_scope: region::Scope,
116 pub opt_destruction_scope: Option<region::Scope>,
117 /// The span of the block, including the opening braces,
118 /// the label, and the `unsafe` keyword, if present.
120 /// The statements in the blocK.
121 pub stmts: Box<[StmtId]>,
122 /// The trailing expression of the block, if any.
123 pub expr: Option<ExprId>,
124 pub safety_mode: BlockSafety,
127 #[derive(Debug, HashStable)]
128 pub struct Adt<'tcx> {
129 /// The ADT we're constructing.
130 pub adt_def: &'tcx AdtDef,
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: Option<Canonical<'tcx, UserType<'tcx>>>,
139 pub fields: Box<[FieldExpr]>,
140 /// The base, e.g. `Foo {x: 1, .. base}`.
141 pub base: Option<FruInfo<'tcx>>,
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(Debug, HashStable)]
154 pub struct Stmt<'tcx> {
155 pub kind: StmtKind<'tcx>,
156 pub opt_destruction_scope: Option<region::Scope>,
159 #[derive(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.
185 /// `let pat: ty = <INIT>`
186 initializer: Option<ExprId>,
188 /// The lint level for this `let` statement.
189 lint_level: LintLevel,
193 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
194 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
195 rustc_data_structures::static_assert_size!(Expr<'_>, 104);
197 /// A THIR expression.
198 #[derive(Debug, HashStable)]
199 pub struct Expr<'tcx> {
200 /// The type of this expression
203 /// The lifetime of this expression if it should be spilled into a
204 /// temporary; should be `None` only if in a constant context
205 pub temp_lifetime: Option<region::Scope>,
207 /// span of the expression in the source
210 /// kind of expression
211 pub kind: ExprKind<'tcx>,
214 #[derive(Debug, HashStable)]
215 pub enum ExprKind<'tcx> {
216 /// `Scope`s are used to explicitely mark destruction scopes,
217 /// and to track the `HirId` of the expressions within the scope.
219 region_scope: region::Scope,
220 lint_level: LintLevel,
223 /// A `box <value>` expression.
227 /// An `if` expression.
229 if_then_scope: region::Scope,
232 else_opt: Option<ExprId>,
234 /// A function call. Method calls and overloaded operators are converted to plain function calls.
236 /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
238 /// [`FnDef`]: ty::TyKind::FnDef
239 /// [`FnPtr`]: ty::TyKind::FnPtr
241 /// The function itself.
243 /// The arguments passed to the function.
245 /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
246 /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
248 /// Whether this is from an overloaded operator rather than a
249 /// function call from HIR. `true` for overloaded function call.
251 /// The span of the function, without the dot and receiver
252 /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
255 /// A *non-overloaded* dereference.
259 /// A *non-overloaded* binary operation.
265 /// A logical operation. This is distinct from `BinaryOp` because
266 /// the operands need to be lazily evaluated.
272 /// A *non-overloaded* unary operation. Note that here the deref (`*`)
273 /// operator is represented by `ExprKind::Deref`.
278 /// A cast: `<source> as <type>`. The type we cast to is the type of
279 /// the parent expression.
285 }, // Use a lexpr to get a vexpr.
286 /// A coercion from `!` to any type.
290 /// A pointer cast. More information can be found in [`PointerCast`].
295 /// A `loop` expression.
303 /// A `match` expression.
312 /// An assignment: `lhs = rhs`.
317 /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
323 /// Access to a struct or tuple field.
326 /// This can be a named (`.foo`) or unnamed (`.0`) field.
329 /// A *non-overloaded* indexing operation.
334 /// A local variable.
338 /// Used to represent upvars mentioned in a closure/generator
340 /// DefId of the closure/generator
341 closure_def_id: DefId,
343 /// HirId of the root variable
344 var_hir_id: hir::HirId,
346 /// A borrow, e.g. `&arg`.
348 borrow_kind: BorrowKind,
351 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
353 mutability: hir::Mutability,
356 /// A `break` expression.
358 label: region::Scope,
359 value: Option<ExprId>,
361 /// A `continue` expression.
363 label: region::Scope,
365 /// A `return` expression.
367 value: Option<ExprId>,
369 /// An inline `const` block, e.g. `const {}`.
371 value: &'tcx Const<'tcx>,
373 /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
376 count: &'tcx Const<'tcx>,
378 /// An array, e.g. `[a, b, c, d]`.
380 fields: Box<[ExprId]>,
382 /// A tuple, e.g. `(a, b, c, d)`.
384 fields: Box<[ExprId]>,
386 /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
388 /// A type ascription on a place.
389 PlaceTypeAscription {
391 /// Type that the user gave to this expression
392 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
394 /// A type ascription on a value, e.g. `42: i32`.
395 ValueTypeAscription {
397 /// Type that the user gave to this expression
398 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
400 /// A closure definition.
403 substs: UpvarSubsts<'tcx>,
404 upvars: Box<[ExprId]>,
405 movability: Option<hir::Movability>,
406 fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
410 literal: &'tcx Const<'tcx>,
411 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
412 /// The `DefId` of the `const` item this literal
413 /// was produced from, if this is not a user-written
415 const_id: Option<DefId>,
417 /// A literal containing the address of a `static`.
419 /// This is only distinguished from `Literal` so that we can register some
420 /// info for diagnostics.
422 literal: &'tcx Const<'tcx>,
425 /// Inline assembly, i.e. `asm!()`.
427 template: &'tcx [InlineAsmTemplatePiece],
428 operands: Box<[InlineAsmOperand<'tcx>]>,
429 options: InlineAsmOptions,
430 line_spans: &'tcx [Span],
432 /// An expression taking a reference to a thread local.
433 ThreadLocalRef(DefId),
434 /// Inline LLVM assembly, i.e. `llvm_asm!()`.
436 asm: &'tcx hir::LlvmInlineAsmInner,
437 outputs: Box<[ExprId]>,
438 inputs: Box<[ExprId]>,
440 /// A `yield` expression.
446 /// Represents the association of a field identifier and an expression.
448 /// This is used in struct constructors.
449 #[derive(Debug, HashStable)]
450 pub struct FieldExpr {
455 #[derive(Debug, HashStable)]
456 pub struct FruInfo<'tcx> {
458 pub field_types: Box<[Ty<'tcx>]>,
462 #[derive(Debug, HashStable)]
463 pub struct Arm<'tcx> {
464 pub pattern: Pat<'tcx>,
465 pub guard: Option<Guard<'tcx>>,
467 pub lint_level: LintLevel,
468 pub scope: region::Scope,
473 #[derive(Debug, HashStable)]
474 pub enum Guard<'tcx> {
476 IfLet(Pat<'tcx>, ExprId),
479 #[derive(Copy, Clone, Debug, HashStable)]
481 /// The `&&` operator.
483 /// The `||` operator.
487 #[derive(Debug, HashStable)]
488 pub enum InlineAsmOperand<'tcx> {
490 reg: InlineAsmRegOrRegClass,
494 reg: InlineAsmRegOrRegClass,
496 expr: Option<ExprId>,
499 reg: InlineAsmRegOrRegClass,
504 reg: InlineAsmRegOrRegClass,
507 out_expr: Option<ExprId>,
510 value: &'tcx Const<'tcx>,
521 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
522 pub enum BindingMode {
527 #[derive(Clone, Debug, PartialEq, HashStable)]
528 pub struct FieldPat<'tcx> {
530 pub pattern: Pat<'tcx>,
533 #[derive(Clone, Debug, PartialEq, HashStable)]
534 pub struct Pat<'tcx> {
537 pub kind: Box<PatKind<'tcx>>,
540 impl<'tcx> Pat<'tcx> {
541 pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
542 Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) }
546 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
547 pub struct PatTyProj<'tcx> {
548 pub user_ty: CanonicalUserType<'tcx>,
551 impl<'tcx> PatTyProj<'tcx> {
552 pub fn from_user_type(user_annotation: CanonicalUserType<'tcx>) -> Self {
553 Self { user_ty: user_annotation }
558 annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
559 inferred_ty: Ty<'tcx>,
561 ) -> UserTypeProjection {
563 base: annotations.push(CanonicalUserTypeAnnotation {
565 user_ty: self.user_ty,
573 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
574 pub struct Ascription<'tcx> {
575 pub user_ty: PatTyProj<'tcx>,
576 /// Variance to use when relating the type `user_ty` to the **type of the value being
577 /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
578 /// have a type that is some subtype of the ascribed type.
580 /// Note that this variance does not apply for any bindings within subpatterns. The type
581 /// assigned to those bindings must be exactly equal to the `user_ty` given here.
583 /// The only place where this field is not `Covariant` is when matching constants, where
584 /// we currently use `Contravariant` -- this is because the constant type just needs to
585 /// be "comparable" to the type of the input value. So, for example:
588 /// match x { "foo" => .. }
591 /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
592 /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
593 /// of the old type-check for now. See #57280 for details.
594 pub variance: ty::Variance,
595 pub user_ty_span: Span,
598 #[derive(Clone, Debug, PartialEq, HashStable)]
599 pub enum PatKind<'tcx> {
600 /// A wildward pattern: `_`.
604 ascription: Ascription<'tcx>,
605 subpattern: Pat<'tcx>,
608 /// `x`, `ref x`, `x @ P`, etc.
610 mutability: Mutability,
615 subpattern: Option<Pat<'tcx>>,
616 /// Is this the leftmost occurrence of the binding, i.e., is `var` the
617 /// `HirId` of this pattern?
621 /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
622 /// multiple variants.
624 adt_def: &'tcx AdtDef,
625 substs: SubstsRef<'tcx>,
626 variant_index: VariantIdx,
627 subpatterns: Vec<FieldPat<'tcx>>,
630 /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
631 /// a single variant.
633 subpatterns: Vec<FieldPat<'tcx>>,
636 /// `box P`, `&P`, `&mut P`, etc.
638 subpattern: Pat<'tcx>,
641 /// One of the following:
642 /// * `&str`, which will be handled as a string pattern and thus exhaustiveness
643 /// checking will detect if you use the same string twice in different patterns.
644 /// * integer, bool, char or float, which will be handled by exhaustivenes to cover exactly
645 /// its own value, similar to `&str`, but these values are much simpler.
646 /// * Opaque constants, that must not be matched structurally. So anything that does not derive
647 /// `PartialEq` and `Eq`.
649 value: &'tcx ty::Const<'tcx>,
652 Range(PatRange<'tcx>),
654 /// Matches against a slice, checking the length and extracting elements.
655 /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
656 /// e.g., `&[ref xs @ ..]`.
658 prefix: Vec<Pat<'tcx>>,
659 slice: Option<Pat<'tcx>>,
660 suffix: Vec<Pat<'tcx>>,
663 /// Fixed match against an array; irrefutable.
665 prefix: Vec<Pat<'tcx>>,
666 slice: Option<Pat<'tcx>>,
667 suffix: Vec<Pat<'tcx>>,
670 /// An or-pattern, e.g. `p | q`.
671 /// Invariant: `pats.len() >= 2`.
673 pats: Vec<Pat<'tcx>>,
677 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
678 pub struct PatRange<'tcx> {
679 pub lo: &'tcx ty::Const<'tcx>,
680 pub hi: &'tcx ty::Const<'tcx>,
684 impl<'tcx> fmt::Display for Pat<'tcx> {
685 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
686 // Printing lists is a chore.
687 let mut first = true;
688 let mut start_or_continue = |s| {
696 let mut start_or_comma = || start_or_continue(", ");
699 PatKind::Wild => write!(f, "_"),
700 PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
701 PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
702 let is_mut = match mode {
703 BindingMode::ByValue => mutability == Mutability::Mut,
704 BindingMode::ByRef(bk) => {
706 matches!(bk, BorrowKind::Mut { .. })
712 write!(f, "{}", name)?;
713 if let Some(ref subpattern) = *subpattern {
714 write!(f, " @ {}", subpattern)?;
718 PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
719 let variant = match *self.kind {
720 PatKind::Variant { adt_def, variant_index, .. } => {
721 Some(&adt_def.variants[variant_index])
723 _ => self.ty.ty_adt_def().and_then(|adt| {
724 if !adt.is_enum() { Some(adt.non_enum_variant()) } else { None }
728 if let Some(variant) = variant {
729 write!(f, "{}", variant.ident)?;
731 // Only for Adt we can have `S {...}`,
732 // which we handle separately here.
733 if variant.ctor_kind == CtorKind::Fictive {
737 for p in subpatterns {
738 if let PatKind::Wild = *p.pattern.kind {
741 let name = variant.fields[p.field.index()].ident;
742 write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
746 if printed < variant.fields.len() {
747 write!(f, "{}..", start_or_comma())?;
750 return write!(f, " }}");
754 let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len());
755 if num_fields != 0 || variant.is_none() {
757 for i in 0..num_fields {
758 write!(f, "{}", start_or_comma())?;
760 // Common case: the field is where we expect it.
761 if let Some(p) = subpatterns.get(i) {
762 if p.field.index() == i {
763 write!(f, "{}", p.pattern)?;
768 // Otherwise, we have to go looking for it.
769 if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
770 write!(f, "{}", p.pattern)?;
780 PatKind::Deref { ref subpattern } => {
781 match self.ty.kind() {
782 ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
783 ty::Ref(_, _, mutbl) => {
784 write!(f, "&{}", mutbl.prefix_str())?;
786 _ => bug!("{} is a bad Deref pattern type", self.ty),
788 write!(f, "{}", subpattern)
790 PatKind::Constant { value } => write!(f, "{}", value),
791 PatKind::Range(PatRange { lo, hi, end }) => {
792 write!(f, "{}", lo)?;
793 write!(f, "{}", end)?;
796 PatKind::Slice { ref prefix, ref slice, ref suffix }
797 | PatKind::Array { ref prefix, ref slice, ref suffix } => {
800 write!(f, "{}{}", start_or_comma(), p)?;
802 if let Some(ref slice) = *slice {
803 write!(f, "{}", start_or_comma())?;
806 _ => write!(f, "{}", slice)?,
811 write!(f, "{}{}", start_or_comma(), p)?;
815 PatKind::Or { ref pats } => {
817 write!(f, "{}{}", start_or_continue(" | "), pat)?;