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
::interpret
::AllocId
;
21 use rustc_middle
::mir
::{
22 BinOp
, BorrowKind
, FakeReadCause
, Field
, Mutability
, UnOp
, UserTypeProjection
,
24 use rustc_middle
::ty
::adjustment
::PointerCast
;
25 use rustc_middle
::ty
::subst
::SubstsRef
;
26 use rustc_middle
::ty
::{self, AdtDef, Const, Ty, UpvarSubsts, UserType}
;
27 use rustc_middle
::ty
::{
28 CanonicalUserType
, CanonicalUserTypeAnnotation
, CanonicalUserTypeAnnotations
,
30 use rustc_span
::{Span, Symbol, DUMMY_SP}
;
31 use rustc_target
::abi
::VariantIdx
;
32 use rustc_target
::asm
::InlineAsmRegOrRegClass
;
37 pub mod abstract_const
;
41 /// An index to an [`Arm`] stored in [`Thir::arms`]
49 /// An index to an [`Expr`] stored in [`Thir::exprs`]
58 /// An index to a [`Stmt`] stored in [`Thir::stmts`]
64 macro_rules
! thir_with_elements
{
65 ($
($name
:ident
: $id
:ty
=> $value
:ty
,)*) => {
66 /// A container for a THIR body.
68 /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
69 #[derive(Debug, HashStable)]
70 pub struct Thir
<'tcx
> {
72 pub $name
: IndexVec
<$id
, $value
>,
76 impl<'tcx
> Thir
<'tcx
> {
77 pub fn new() -> Thir
<'tcx
> {
80 $name
: IndexVec
::new(),
87 impl<'tcx
> Index
<$id
> for Thir
<'tcx
> {
89 fn index(&self, index
: $id
) -> &Self::Output
{
98 arms
: ArmId
=> Arm
<'tcx
>,
99 exprs
: ExprId
=> Expr
<'tcx
>,
100 stmts
: StmtId
=> Stmt
<'tcx
>,
103 #[derive(Copy, Clone, Debug, HashStable)]
106 Explicit(hir
::HirId
),
109 #[derive(Debug, HashStable)]
111 /// Whether the block itself has a label. Used by `label: {}`
112 /// and `try` blocks.
114 /// This does *not* include labels on loops, e.g. `'label: loop {}`.
115 pub targeted_by_break
: bool
,
116 pub region_scope
: region
::Scope
,
117 pub opt_destruction_scope
: Option
<region
::Scope
>,
118 /// The span of the block, including the opening braces,
119 /// the label, and the `unsafe` keyword, if present.
121 /// The statements in the blocK.
122 pub stmts
: Box
<[StmtId
]>,
123 /// The trailing expression of the block, if any.
124 pub expr
: Option
<ExprId
>,
125 pub safety_mode
: BlockSafety
,
128 #[derive(Debug, HashStable)]
129 pub struct Adt
<'tcx
> {
130 /// The ADT we're constructing.
131 pub adt_def
: AdtDef
<'tcx
>,
132 /// The variant of the ADT.
133 pub variant_index
: VariantIdx
,
134 pub substs
: SubstsRef
<'tcx
>,
136 /// Optional user-given substs: for something like `let x =
137 /// Bar::<T> { ... }`.
138 pub user_ty
: Option
<Canonical
<'tcx
, UserType
<'tcx
>>>,
140 pub fields
: Box
<[FieldExpr
]>,
141 /// The base, e.g. `Foo {x: 1, .. base}`.
142 pub base
: Option
<FruInfo
<'tcx
>>,
145 #[derive(Copy, Clone, Debug, HashStable)]
146 pub enum BlockSafety
{
148 /// A compiler-generated unsafe block
150 /// An `unsafe` block. The `HirId` is the ID of the block.
151 ExplicitUnsafe(hir
::HirId
),
154 #[derive(Debug, HashStable)]
155 pub struct Stmt
<'tcx
> {
156 pub kind
: StmtKind
<'tcx
>,
157 pub opt_destruction_scope
: Option
<region
::Scope
>,
160 #[derive(Debug, HashStable)]
161 pub enum StmtKind
<'tcx
> {
162 /// An expression with a trailing semicolon.
164 /// The scope for this statement; may be used as lifetime of temporaries.
165 scope
: region
::Scope
,
167 /// The expression being evaluated in this statement.
173 /// The scope for variables bound in this `let`; it covers this and
174 /// all the remaining statements in the block.
175 remainder_scope
: region
::Scope
,
177 /// The scope for the initialization itself; might be used as
178 /// lifetime of temporaries.
179 init_scope
: region
::Scope
,
181 /// `let <PAT> = ...`
183 /// If a type annotation is included, it is added as an ascription pattern.
186 /// `let pat: ty = <INIT>`
187 initializer
: Option
<ExprId
>,
189 /// The lint level for this `let` statement.
190 lint_level
: LintLevel
,
194 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
195 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
196 rustc_data_structures
::static_assert_size
!(Expr
<'_
>, 104);
198 /// A THIR expression.
199 #[derive(Debug, HashStable)]
200 pub struct Expr
<'tcx
> {
201 /// The type of this expression
204 /// The lifetime of this expression if it should be spilled into a
205 /// temporary; should be `None` only if in a constant context
206 pub temp_lifetime
: Option
<region
::Scope
>,
208 /// span of the expression in the source
211 /// kind of expression
212 pub kind
: ExprKind
<'tcx
>,
215 #[derive(Debug, HashStable)]
216 pub enum ExprKind
<'tcx
> {
217 /// `Scope`s are used to explicitly mark destruction scopes,
218 /// and to track the `HirId` of the expressions within the scope.
220 region_scope
: region
::Scope
,
221 lint_level
: LintLevel
,
224 /// A `box <value>` expression.
228 /// An `if` expression.
230 if_then_scope
: region
::Scope
,
233 else_opt
: Option
<ExprId
>,
235 /// A function call. Method calls and overloaded operators are converted to plain function calls.
237 /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
239 /// [`FnDef`]: ty::TyKind::FnDef
240 /// [`FnPtr`]: ty::TyKind::FnPtr
242 /// The function itself.
244 /// The arguments passed to the function.
246 /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
247 /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
249 /// Whether this is from an overloaded operator rather than a
250 /// function call from HIR. `true` for overloaded function call.
252 /// The span of the function, without the dot and receiver
253 /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
256 /// A *non-overloaded* dereference.
260 /// A *non-overloaded* binary operation.
266 /// A logical operation. This is distinct from `BinaryOp` because
267 /// the operands need to be lazily evaluated.
273 /// A *non-overloaded* unary operation. Note that here the deref (`*`)
274 /// operator is represented by `ExprKind::Deref`.
279 /// A cast: `<source> as <type>`. The type we cast to is the type of
280 /// the parent expression.
286 }, // Use a lexpr to get a vexpr.
287 /// A coercion from `!` to any type.
291 /// A pointer cast. More information can be found in [`PointerCast`].
296 /// A `loop` expression.
304 /// A `match` expression.
313 /// An assignment: `lhs = rhs`.
318 /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
324 /// Access to a struct or tuple field.
327 /// This can be a named (`.foo`) or unnamed (`.0`) field.
330 /// A *non-overloaded* indexing operation.
335 /// A local variable.
339 /// Used to represent upvars mentioned in a closure/generator
341 /// DefId of the closure/generator
342 closure_def_id
: DefId
,
344 /// HirId of the root variable
345 var_hir_id
: hir
::HirId
,
347 /// A borrow, e.g. `&arg`.
349 borrow_kind
: BorrowKind
,
352 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
354 mutability
: hir
::Mutability
,
357 /// A `break` expression.
359 label
: region
::Scope
,
360 value
: Option
<ExprId
>,
362 /// A `continue` expression.
364 label
: region
::Scope
,
366 /// A `return` expression.
368 value
: Option
<ExprId
>,
370 /// An inline `const` block, e.g. `const {}`.
373 substs
: SubstsRef
<'tcx
>,
375 /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
380 /// An array, e.g. `[a, b, c, d]`.
382 fields
: Box
<[ExprId
]>,
384 /// A tuple, e.g. `(a, b, c, d)`.
386 fields
: Box
<[ExprId
]>,
388 /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
390 /// A type ascription on a place.
391 PlaceTypeAscription
{
393 /// Type that the user gave to this expression
394 user_ty
: Option
<Canonical
<'tcx
, UserType
<'tcx
>>>,
396 /// A type ascription on a value, e.g. `42: i32`.
397 ValueTypeAscription
{
399 /// Type that the user gave to this expression
400 user_ty
: Option
<Canonical
<'tcx
, UserType
<'tcx
>>>,
402 /// A closure definition.
405 substs
: UpvarSubsts
<'tcx
>,
406 upvars
: Box
<[ExprId
]>,
407 movability
: Option
<hir
::Movability
>,
408 fake_reads
: Vec
<(ExprId
, FakeReadCause
, hir
::HirId
)>,
415 /// For literals that don't correspond to anything in the HIR
418 user_ty
: Option
<Canonical
<'tcx
, UserType
<'tcx
>>>,
420 /// Associated constants and named constants
423 substs
: SubstsRef
<'tcx
>,
424 user_ty
: Option
<Canonical
<'tcx
, UserType
<'tcx
>>>,
427 param
: ty
::ParamConst
,
430 // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
431 /// A literal containing the address of a `static`.
433 /// This is only distinguished from `Literal` so that we can register some
434 /// info for diagnostics.
440 /// Inline assembly, i.e. `asm!()`.
442 template
: &'tcx
[InlineAsmTemplatePiece
],
443 operands
: Box
<[InlineAsmOperand
<'tcx
>]>,
444 options
: InlineAsmOptions
,
445 line_spans
: &'tcx
[Span
],
447 /// An expression taking a reference to a thread local.
448 ThreadLocalRef(DefId
),
449 /// A `yield` expression.
455 impl<'tcx
> ExprKind
<'tcx
> {
456 pub fn zero_sized_literal(user_ty
: Option
<Canonical
<'tcx
, UserType
<'tcx
>>>) -> Self {
457 ExprKind
::NonHirLiteral { lit: ty::ScalarInt::ZST, user_ty }
461 /// Represents the association of a field identifier and an expression.
463 /// This is used in struct constructors.
464 #[derive(Debug, HashStable)]
465 pub struct FieldExpr
{
470 #[derive(Debug, HashStable)]
471 pub struct FruInfo
<'tcx
> {
473 pub field_types
: Box
<[Ty
<'tcx
>]>,
477 #[derive(Debug, HashStable)]
478 pub struct Arm
<'tcx
> {
479 pub pattern
: Pat
<'tcx
>,
480 pub guard
: Option
<Guard
<'tcx
>>,
482 pub lint_level
: LintLevel
,
483 pub scope
: region
::Scope
,
488 #[derive(Debug, HashStable)]
489 pub enum Guard
<'tcx
> {
491 IfLet(Pat
<'tcx
>, ExprId
),
494 #[derive(Copy, Clone, Debug, HashStable)]
496 /// The `&&` operator.
498 /// The `||` operator.
502 #[derive(Debug, HashStable)]
503 pub enum InlineAsmOperand
<'tcx
> {
505 reg
: InlineAsmRegOrRegClass
,
509 reg
: InlineAsmRegOrRegClass
,
511 expr
: Option
<ExprId
>,
514 reg
: InlineAsmRegOrRegClass
,
519 reg
: InlineAsmRegOrRegClass
,
522 out_expr
: Option
<ExprId
>,
536 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
537 pub enum BindingMode
{
542 #[derive(Clone, Debug, PartialEq, HashStable)]
543 pub struct FieldPat
<'tcx
> {
545 pub pattern
: Pat
<'tcx
>,
548 #[derive(Clone, Debug, PartialEq, HashStable)]
549 pub struct Pat
<'tcx
> {
552 pub kind
: Box
<PatKind
<'tcx
>>,
555 impl<'tcx
> Pat
<'tcx
> {
556 pub fn wildcard_from_ty(ty
: Ty
<'tcx
>) -> Self {
557 Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) }
561 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
562 pub struct PatTyProj
<'tcx
> {
563 pub user_ty
: CanonicalUserType
<'tcx
>,
566 impl<'tcx
> PatTyProj
<'tcx
> {
567 pub fn from_user_type(user_annotation
: CanonicalUserType
<'tcx
>) -> Self {
568 Self { user_ty: user_annotation }
573 annotations
: &mut CanonicalUserTypeAnnotations
<'tcx
>,
574 inferred_ty
: Ty
<'tcx
>,
576 ) -> UserTypeProjection
{
578 base
: annotations
.push(CanonicalUserTypeAnnotation
{
580 user_ty
: self.user_ty
,
588 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
589 pub struct Ascription
<'tcx
> {
590 pub user_ty
: PatTyProj
<'tcx
>,
591 /// Variance to use when relating the type `user_ty` to the **type of the value being
592 /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
593 /// have a type that is some subtype of the ascribed type.
595 /// Note that this variance does not apply for any bindings within subpatterns. The type
596 /// assigned to those bindings must be exactly equal to the `user_ty` given here.
598 /// The only place where this field is not `Covariant` is when matching constants, where
599 /// we currently use `Contravariant` -- this is because the constant type just needs to
600 /// be "comparable" to the type of the input value. So, for example:
603 /// match x { "foo" => .. }
606 /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
607 /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
608 /// of the old type-check for now. See #57280 for details.
609 pub variance
: ty
::Variance
,
610 pub user_ty_span
: Span
,
613 #[derive(Clone, Debug, PartialEq, HashStable)]
614 pub enum PatKind
<'tcx
> {
615 /// A wildward pattern: `_`.
619 ascription
: Ascription
<'tcx
>,
620 subpattern
: Pat
<'tcx
>,
623 /// `x`, `ref x`, `x @ P`, etc.
625 mutability
: Mutability
,
630 subpattern
: Option
<Pat
<'tcx
>>,
631 /// Is this the leftmost occurrence of the binding, i.e., is `var` the
632 /// `HirId` of this pattern?
636 /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
637 /// multiple variants.
639 adt_def
: AdtDef
<'tcx
>,
640 substs
: SubstsRef
<'tcx
>,
641 variant_index
: VariantIdx
,
642 subpatterns
: Vec
<FieldPat
<'tcx
>>,
645 /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
646 /// a single variant.
648 subpatterns
: Vec
<FieldPat
<'tcx
>>,
651 /// `box P`, `&P`, `&mut P`, etc.
653 subpattern
: Pat
<'tcx
>,
656 /// One of the following:
657 /// * `&str`, which will be handled as a string pattern and thus exhaustiveness
658 /// checking will detect if you use the same string twice in different patterns.
659 /// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly
660 /// its own value, similar to `&str`, but these values are much simpler.
661 /// * Opaque constants, that must not be matched structurally. So anything that does not derive
662 /// `PartialEq` and `Eq`.
664 value
: ty
::Const
<'tcx
>,
667 Range(PatRange
<'tcx
>),
669 /// Matches against a slice, checking the length and extracting elements.
670 /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
671 /// e.g., `&[ref xs @ ..]`.
673 prefix
: Vec
<Pat
<'tcx
>>,
674 slice
: Option
<Pat
<'tcx
>>,
675 suffix
: Vec
<Pat
<'tcx
>>,
678 /// Fixed match against an array; irrefutable.
680 prefix
: Vec
<Pat
<'tcx
>>,
681 slice
: Option
<Pat
<'tcx
>>,
682 suffix
: Vec
<Pat
<'tcx
>>,
685 /// An or-pattern, e.g. `p | q`.
686 /// Invariant: `pats.len() >= 2`.
688 pats
: Vec
<Pat
<'tcx
>>,
692 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
693 pub struct PatRange
<'tcx
> {
694 pub lo
: ty
::Const
<'tcx
>,
695 pub hi
: ty
::Const
<'tcx
>,
699 impl<'tcx
> fmt
::Display
for Pat
<'tcx
> {
700 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
701 // Printing lists is a chore.
702 let mut first
= true;
703 let mut start_or_continue
= |s
| {
711 let mut start_or_comma
= || start_or_continue(", ");
714 PatKind
::Wild
=> write
!(f
, "_"),
715 PatKind
::AscribeUserType { ref subpattern, .. }
=> write
!(f
, "{}: _", subpattern
),
716 PatKind
::Binding { mutability, name, mode, ref subpattern, .. }
=> {
717 let is_mut
= match mode
{
718 BindingMode
::ByValue
=> mutability
== Mutability
::Mut
,
719 BindingMode
::ByRef(bk
) => {
721 matches
!(bk
, BorrowKind
::Mut { .. }
)
727 write
!(f
, "{}", name
)?
;
728 if let Some(ref subpattern
) = *subpattern
{
729 write
!(f
, " @ {}", subpattern
)?
;
733 PatKind
::Variant { ref subpatterns, .. }
| PatKind
::Leaf { ref subpatterns }
=> {
734 let variant
= match *self.kind
{
735 PatKind
::Variant { adt_def, variant_index, .. }
=> {
736 Some(adt_def
.variant(variant_index
))
738 _
=> self.ty
.ty_adt_def().and_then(|adt
| {
739 if !adt
.is_enum() { Some(adt.non_enum_variant()) }
else { None }
743 if let Some(variant
) = variant
{
744 write
!(f
, "{}", variant
.name
)?
;
746 // Only for Adt we can have `S {...}`,
747 // which we handle separately here.
748 if variant
.ctor_kind
== CtorKind
::Fictive
{
752 for p
in subpatterns
{
753 if let PatKind
::Wild
= *p
.pattern
.kind
{
756 let name
= variant
.fields
[p
.field
.index()].name
;
757 write
!(f
, "{}{}: {}", start_or_comma(), name
, p
.pattern
)?
;
761 if printed
< variant
.fields
.len() {
762 write
!(f
, "{}..", start_or_comma())?
;
765 return write
!(f
, " }}");
769 let num_fields
= variant
.map_or(subpatterns
.len(), |v
| v
.fields
.len());
770 if num_fields
!= 0 || variant
.is_none() {
772 for i
in 0..num_fields
{
773 write
!(f
, "{}", start_or_comma())?
;
775 // Common case: the field is where we expect it.
776 if let Some(p
) = subpatterns
.get(i
) {
777 if p
.field
.index() == i
{
778 write
!(f
, "{}", p
.pattern
)?
;
783 // Otherwise, we have to go looking for it.
784 if let Some(p
) = subpatterns
.iter().find(|p
| p
.field
.index() == i
) {
785 write
!(f
, "{}", p
.pattern
)?
;
795 PatKind
::Deref { ref subpattern }
=> {
796 match self.ty
.kind() {
797 ty
::Adt(def
, _
) if def
.is_box() => write
!(f
, "box ")?
,
798 ty
::Ref(_
, _
, mutbl
) => {
799 write
!(f
, "&{}", mutbl
.prefix_str())?
;
801 _
=> bug
!("{} is a bad Deref pattern type", self.ty
),
803 write
!(f
, "{}", subpattern
)
805 PatKind
::Constant { value }
=> write
!(f
, "{}", value
),
806 PatKind
::Range(PatRange { lo, hi, end }
) => {
807 write
!(f
, "{}", lo
)?
;
808 write
!(f
, "{}", end
)?
;
811 PatKind
::Slice { ref prefix, ref slice, ref suffix }
812 | PatKind
::Array { ref prefix, ref slice, ref suffix }
=> {
815 write
!(f
, "{}{}", start_or_comma(), p
)?
;
817 if let Some(ref slice
) = *slice
{
818 write
!(f
, "{}", start_or_comma())?
;
821 _
=> write
!(f
, "{}", slice
)?
,
826 write
!(f
, "{}{}", start_or_comma(), p
)?
;
830 PatKind
::Or { ref pats }
=> {
832 write
!(f
, "{}{}", start_or_continue(" | "), pat
)?
;