rustc_middle/
thir.rs

1//! THIR datatypes and definitions. See the [rustc dev guide] for more info.
2//!
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.
8//!
9//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
10
11use std::cmp::Ordering;
12use std::fmt;
13use std::ops::Index;
14use std::sync::Arc;
15
16use rustc_abi::{FieldIdx, Integer, Size, VariantIdx};
17use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
18use rustc_hir as hir;
19use rustc_hir::def_id::DefId;
20use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
21use rustc_index::{IndexVec, newtype_index};
22use rustc_macros::{HashStable, TypeVisitable};
23use rustc_span::def_id::LocalDefId;
24use rustc_span::{ErrorGuaranteed, Span, Symbol};
25use rustc_target::asm::InlineAsmRegOrRegClass;
26use tracing::instrument;
27
28use crate::middle::region;
29use crate::mir::interpret::AllocId;
30use crate::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp};
31use crate::ty::adjustment::PointerCoercion;
32use crate::ty::layout::IntegerExt;
33use crate::ty::{
34    self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, List, Ty,
35    TyCtxt, UpvarArgs,
36};
37
38pub mod visit;
39
40macro_rules! thir_with_elements {
41    (
42        $($name:ident: $id:ty => $value:ty => $format:literal,)*
43    ) => {
44        $(
45            newtype_index! {
46                #[derive(HashStable)]
47                #[debug_format = $format]
48                pub struct $id {}
49            }
50        )*
51
52        /// A container for a THIR body.
53        ///
54        /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
55        #[derive(Debug, HashStable)]
56        pub struct Thir<'tcx> {
57            pub body_type: BodyTy<'tcx>,
58            $(
59                pub $name: IndexVec<$id, $value>,
60            )*
61        }
62
63        impl<'tcx> Thir<'tcx> {
64            pub fn new(body_type: BodyTy<'tcx>) -> Thir<'tcx> {
65                Thir {
66                    body_type,
67                    $(
68                        $name: IndexVec::new(),
69                    )*
70                }
71            }
72        }
73
74        $(
75            impl<'tcx> Index<$id> for Thir<'tcx> {
76                type Output = $value;
77                fn index(&self, index: $id) -> &Self::Output {
78                    &self.$name[index]
79                }
80            }
81        )*
82    }
83}
84
85thir_with_elements! {
86    arms: ArmId => Arm<'tcx> => "a{}",
87    blocks: BlockId => Block => "b{}",
88    exprs: ExprId => Expr<'tcx> => "e{}",
89    stmts: StmtId => Stmt<'tcx> => "s{}",
90    params: ParamId => Param<'tcx> => "p{}",
91}
92
93#[derive(Debug, HashStable)]
94pub enum BodyTy<'tcx> {
95    Const(Ty<'tcx>),
96    Fn(FnSig<'tcx>),
97}
98
99/// Description of a type-checked function parameter.
100#[derive(Debug, HashStable)]
101pub struct Param<'tcx> {
102    /// The pattern that appears in the parameter list, or None for implicit parameters.
103    pub pat: Option<Box<Pat<'tcx>>>,
104    /// The possibly inferred type.
105    pub ty: Ty<'tcx>,
106    /// Span of the explicitly provided type, or None if inferred for closures.
107    pub ty_span: Option<Span>,
108    /// Whether this param is `self`, and how it is bound.
109    pub self_kind: Option<hir::ImplicitSelfKind>,
110    /// HirId for lints.
111    pub hir_id: Option<HirId>,
112}
113
114#[derive(Copy, Clone, Debug, HashStable)]
115pub enum LintLevel {
116    Inherited,
117    Explicit(HirId),
118}
119
120#[derive(Debug, HashStable)]
121pub struct Block {
122    /// Whether the block itself has a label. Used by `label: {}`
123    /// and `try` blocks.
124    ///
125    /// This does *not* include labels on loops, e.g. `'label: loop {}`.
126    pub targeted_by_break: bool,
127    pub region_scope: region::Scope,
128    /// The span of the block, including the opening braces,
129    /// the label, and the `unsafe` keyword, if present.
130    pub span: Span,
131    /// The statements in the blocK.
132    pub stmts: Box<[StmtId]>,
133    /// The trailing expression of the block, if any.
134    pub expr: Option<ExprId>,
135    pub safety_mode: BlockSafety,
136}
137
138type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>;
139
140#[derive(Debug, HashStable)]
141pub struct AdtExpr<'tcx> {
142    /// The ADT we're constructing.
143    pub adt_def: AdtDef<'tcx>,
144    /// The variant of the ADT.
145    pub variant_index: VariantIdx,
146    pub args: GenericArgsRef<'tcx>,
147
148    /// Optional user-given args: for something like `let x =
149    /// Bar::<T> { ... }`.
150    pub user_ty: UserTy<'tcx>,
151
152    pub fields: Box<[FieldExpr]>,
153    /// The base, e.g. `Foo {x: 1, ..base}`.
154    pub base: AdtExprBase<'tcx>,
155}
156
157#[derive(Debug, HashStable)]
158pub enum AdtExprBase<'tcx> {
159    /// A struct expression where all the fields are explicitly enumerated: `Foo { a, b }`.
160    None,
161    /// A struct expression with a "base", an expression of the same type as the outer struct that
162    /// will be used to populate any fields not explicitly mentioned: `Foo { ..base }`
163    Base(FruInfo<'tcx>),
164    /// A struct expression with a `..` tail but no "base" expression. The values from the struct
165    /// fields' default values will be used to populate any fields not explicitly mentioned:
166    /// `Foo { .. }`.
167    DefaultFields(Box<[Ty<'tcx>]>),
168}
169
170#[derive(Debug, HashStable)]
171pub struct ClosureExpr<'tcx> {
172    pub closure_id: LocalDefId,
173    pub args: UpvarArgs<'tcx>,
174    pub upvars: Box<[ExprId]>,
175    pub movability: Option<hir::Movability>,
176    pub fake_reads: Vec<(ExprId, FakeReadCause, HirId)>,
177}
178
179#[derive(Debug, HashStable)]
180pub struct InlineAsmExpr<'tcx> {
181    pub asm_macro: AsmMacro,
182    pub template: &'tcx [InlineAsmTemplatePiece],
183    pub operands: Box<[InlineAsmOperand<'tcx>]>,
184    pub options: InlineAsmOptions,
185    pub line_spans: &'tcx [Span],
186}
187
188#[derive(Copy, Clone, Debug, HashStable)]
189pub enum BlockSafety {
190    Safe,
191    /// A compiler-generated unsafe block
192    BuiltinUnsafe,
193    /// An `unsafe` block. The `HirId` is the ID of the block.
194    ExplicitUnsafe(HirId),
195}
196
197#[derive(Debug, HashStable)]
198pub struct Stmt<'tcx> {
199    pub kind: StmtKind<'tcx>,
200}
201
202#[derive(Debug, HashStable)]
203pub enum StmtKind<'tcx> {
204    /// An expression with a trailing semicolon.
205    Expr {
206        /// The scope for this statement; may be used as lifetime of temporaries.
207        scope: region::Scope,
208
209        /// The expression being evaluated in this statement.
210        expr: ExprId,
211    },
212
213    /// A `let` binding.
214    Let {
215        /// The scope for variables bound in this `let`; it covers this and
216        /// all the remaining statements in the block.
217        remainder_scope: region::Scope,
218
219        /// The scope for the initialization itself; might be used as
220        /// lifetime of temporaries.
221        init_scope: region::Scope,
222
223        /// `let <PAT> = ...`
224        ///
225        /// If a type annotation is included, it is added as an ascription pattern.
226        pattern: Box<Pat<'tcx>>,
227
228        /// `let pat: ty = <INIT>`
229        initializer: Option<ExprId>,
230
231        /// `let pat: ty = <INIT> else { <ELSE> }`
232        else_block: Option<BlockId>,
233
234        /// The lint level for this `let` statement.
235        lint_level: LintLevel,
236
237        /// Span of the `let <PAT> = <INIT>` part.
238        span: Span,
239    },
240}
241
242#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, HashStable)]
243pub struct LocalVarId(pub HirId);
244
245/// A THIR expression.
246#[derive(Debug, HashStable)]
247pub struct Expr<'tcx> {
248    /// kind of expression
249    pub kind: ExprKind<'tcx>,
250
251    /// The type of this expression
252    pub ty: Ty<'tcx>,
253
254    /// The lifetime of this expression if it should be spilled into a
255    /// temporary
256    pub temp_lifetime: TempLifetime,
257
258    /// span of the expression in the source
259    pub span: Span,
260}
261
262/// Temporary lifetime information for THIR expressions
263#[derive(Clone, Copy, Debug, HashStable)]
264pub struct TempLifetime {
265    /// Lifetime for temporaries as expected.
266    /// This should be `None` in a constant context.
267    pub temp_lifetime: Option<region::Scope>,
268    /// If `Some(lt)`, indicates that the lifetime of this temporary will change to `lt` in a future edition.
269    /// If `None`, then no changes are expected, or lints are disabled.
270    pub backwards_incompatible: Option<region::Scope>,
271}
272
273#[derive(Debug, HashStable)]
274pub enum ExprKind<'tcx> {
275    /// `Scope`s are used to explicitly mark destruction scopes,
276    /// and to track the `HirId` of the expressions within the scope.
277    Scope {
278        region_scope: region::Scope,
279        lint_level: LintLevel,
280        value: ExprId,
281    },
282    /// A `box <value>` expression.
283    Box {
284        value: ExprId,
285    },
286    /// An `if` expression.
287    If {
288        if_then_scope: region::Scope,
289        cond: ExprId,
290        then: ExprId,
291        else_opt: Option<ExprId>,
292    },
293    /// A function call. Method calls and overloaded operators are converted to plain function calls.
294    Call {
295        /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
296        ///
297        /// [`FnDef`]: ty::TyKind::FnDef
298        /// [`FnPtr`]: ty::TyKind::FnPtr
299        ty: Ty<'tcx>,
300        /// The function itself.
301        fun: ExprId,
302        /// The arguments passed to the function.
303        ///
304        /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
305        /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
306        args: Box<[ExprId]>,
307        /// Whether this is from an overloaded operator rather than a
308        /// function call from HIR. `true` for overloaded function call.
309        from_hir_call: bool,
310        /// The span of the function, without the dot and receiver
311        /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
312        fn_span: Span,
313    },
314    /// A *non-overloaded* dereference.
315    Deref {
316        arg: ExprId,
317    },
318    /// A *non-overloaded* binary operation.
319    Binary {
320        op: BinOp,
321        lhs: ExprId,
322        rhs: ExprId,
323    },
324    /// A logical operation. This is distinct from `BinaryOp` because
325    /// the operands need to be lazily evaluated.
326    LogicalOp {
327        op: LogicalOp,
328        lhs: ExprId,
329        rhs: ExprId,
330    },
331    /// A *non-overloaded* unary operation. Note that here the deref (`*`)
332    /// operator is represented by `ExprKind::Deref`.
333    Unary {
334        op: UnOp,
335        arg: ExprId,
336    },
337    /// A cast: `<source> as <type>`. The type we cast to is the type of
338    /// the parent expression.
339    Cast {
340        source: ExprId,
341    },
342    /// Forces its contents to be treated as a value expression, not a place
343    /// expression. This is inserted in some places where an operation would
344    /// otherwise be erased completely (e.g. some no-op casts), but we still
345    /// need to ensure that its operand is treated as a value and not a place.
346    Use {
347        source: ExprId,
348    },
349    /// A coercion from `!` to any type.
350    NeverToAny {
351        source: ExprId,
352    },
353    /// A pointer coercion. More information can be found in [`PointerCoercion`].
354    /// Pointer casts that cannot be done by coercions are represented by [`ExprKind::Cast`].
355    PointerCoercion {
356        cast: PointerCoercion,
357        source: ExprId,
358        /// Whether this coercion is written with an `as` cast in the source code.
359        is_from_as_cast: bool,
360    },
361    /// A `loop` expression.
362    Loop {
363        body: ExprId,
364    },
365    /// Special expression representing the `let` part of an `if let` or similar construct
366    /// (including `if let` guards in match arms, and let-chains formed by `&&`).
367    ///
368    /// This isn't considered a real expression in surface Rust syntax, so it can
369    /// only appear in specific situations, such as within the condition of an `if`.
370    ///
371    /// (Not to be confused with [`StmtKind::Let`], which is a normal `let` statement.)
372    Let {
373        expr: ExprId,
374        pat: Box<Pat<'tcx>>,
375    },
376    /// A `match` expression.
377    Match {
378        scrutinee: ExprId,
379        scrutinee_hir_id: HirId,
380        arms: Box<[ArmId]>,
381        match_source: MatchSource,
382    },
383    /// A block.
384    Block {
385        block: BlockId,
386    },
387    /// An assignment: `lhs = rhs`.
388    Assign {
389        lhs: ExprId,
390        rhs: ExprId,
391    },
392    /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
393    AssignOp {
394        op: BinOp,
395        lhs: ExprId,
396        rhs: ExprId,
397    },
398    /// Access to a field of a struct, a tuple, an union, or an enum.
399    Field {
400        lhs: ExprId,
401        /// Variant containing the field.
402        variant_index: VariantIdx,
403        /// This can be a named (`.foo`) or unnamed (`.0`) field.
404        name: FieldIdx,
405    },
406    /// A *non-overloaded* indexing operation.
407    Index {
408        lhs: ExprId,
409        index: ExprId,
410    },
411    /// A local variable.
412    VarRef {
413        id: LocalVarId,
414    },
415    /// Used to represent upvars mentioned in a closure/coroutine
416    UpvarRef {
417        /// DefId of the closure/coroutine
418        closure_def_id: DefId,
419
420        /// HirId of the root variable
421        var_hir_id: LocalVarId,
422    },
423    /// A borrow, e.g. `&arg`.
424    Borrow {
425        borrow_kind: BorrowKind,
426        arg: ExprId,
427    },
428    /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
429    RawBorrow {
430        mutability: hir::Mutability,
431        arg: ExprId,
432    },
433    /// A `break` expression.
434    Break {
435        label: region::Scope,
436        value: Option<ExprId>,
437    },
438    /// A `continue` expression.
439    Continue {
440        label: region::Scope,
441    },
442    /// A `return` expression.
443    Return {
444        value: Option<ExprId>,
445    },
446    /// A `become` expression.
447    Become {
448        value: ExprId,
449    },
450    /// An inline `const` block, e.g. `const {}`.
451    ConstBlock {
452        did: DefId,
453        args: GenericArgsRef<'tcx>,
454    },
455    /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
456    Repeat {
457        value: ExprId,
458        count: ty::Const<'tcx>,
459    },
460    /// An array, e.g. `[a, b, c, d]`.
461    Array {
462        fields: Box<[ExprId]>,
463    },
464    /// A tuple, e.g. `(a, b, c, d)`.
465    Tuple {
466        fields: Box<[ExprId]>,
467    },
468    /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
469    Adt(Box<AdtExpr<'tcx>>),
470    /// A type ascription on a place.
471    PlaceTypeAscription {
472        source: ExprId,
473        /// Type that the user gave to this expression
474        user_ty: UserTy<'tcx>,
475        user_ty_span: Span,
476    },
477    /// A type ascription on a value, e.g. `type_ascribe!(42, i32)` or `42 as i32`.
478    ValueTypeAscription {
479        source: ExprId,
480        /// Type that the user gave to this expression
481        user_ty: UserTy<'tcx>,
482        user_ty_span: Span,
483    },
484    /// An unsafe binder cast on a place, e.g. `unwrap_binder!(*ptr)`.
485    PlaceUnwrapUnsafeBinder {
486        source: ExprId,
487    },
488    /// An unsafe binder cast on a value, e.g. `unwrap_binder!(rvalue())`,
489    /// which makes a temporary.
490    ValueUnwrapUnsafeBinder {
491        source: ExprId,
492    },
493    /// Construct an unsafe binder, e.g. `wrap_binder(&ref)`.
494    WrapUnsafeBinder {
495        source: ExprId,
496    },
497    /// A closure definition.
498    Closure(Box<ClosureExpr<'tcx>>),
499    /// A literal.
500    Literal {
501        lit: &'tcx hir::Lit,
502        neg: bool,
503    },
504    /// For literals that don't correspond to anything in the HIR
505    NonHirLiteral {
506        lit: ty::ScalarInt,
507        user_ty: UserTy<'tcx>,
508    },
509    /// A literal of a ZST type.
510    ZstLiteral {
511        user_ty: UserTy<'tcx>,
512    },
513    /// Associated constants and named constants
514    NamedConst {
515        def_id: DefId,
516        args: GenericArgsRef<'tcx>,
517        user_ty: UserTy<'tcx>,
518    },
519    ConstParam {
520        param: ty::ParamConst,
521        def_id: DefId,
522    },
523    // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
524    /// A literal containing the address of a `static`.
525    ///
526    /// This is only distinguished from `Literal` so that we can register some
527    /// info for diagnostics.
528    StaticRef {
529        alloc_id: AllocId,
530        ty: Ty<'tcx>,
531        def_id: DefId,
532    },
533    /// Inline assembly, i.e. `asm!()`.
534    InlineAsm(Box<InlineAsmExpr<'tcx>>),
535    /// Field offset (`offset_of!`)
536    OffsetOf {
537        container: Ty<'tcx>,
538        fields: &'tcx List<(VariantIdx, FieldIdx)>,
539    },
540    /// An expression taking a reference to a thread local.
541    ThreadLocalRef(DefId),
542    /// A `yield` expression.
543    Yield {
544        value: ExprId,
545    },
546}
547
548/// Represents the association of a field identifier and an expression.
549///
550/// This is used in struct constructors.
551#[derive(Debug, HashStable)]
552pub struct FieldExpr {
553    pub name: FieldIdx,
554    pub expr: ExprId,
555}
556
557#[derive(Debug, HashStable)]
558pub struct FruInfo<'tcx> {
559    pub base: ExprId,
560    pub field_types: Box<[Ty<'tcx>]>,
561}
562
563/// A `match` arm.
564#[derive(Debug, HashStable)]
565pub struct Arm<'tcx> {
566    pub pattern: Box<Pat<'tcx>>,
567    pub guard: Option<ExprId>,
568    pub body: ExprId,
569    pub lint_level: LintLevel,
570    pub scope: region::Scope,
571    pub span: Span,
572}
573
574#[derive(Copy, Clone, Debug, HashStable)]
575pub enum LogicalOp {
576    /// The `&&` operator.
577    And,
578    /// The `||` operator.
579    Or,
580}
581
582#[derive(Debug, HashStable)]
583pub enum InlineAsmOperand<'tcx> {
584    In {
585        reg: InlineAsmRegOrRegClass,
586        expr: ExprId,
587    },
588    Out {
589        reg: InlineAsmRegOrRegClass,
590        late: bool,
591        expr: Option<ExprId>,
592    },
593    InOut {
594        reg: InlineAsmRegOrRegClass,
595        late: bool,
596        expr: ExprId,
597    },
598    SplitInOut {
599        reg: InlineAsmRegOrRegClass,
600        late: bool,
601        in_expr: ExprId,
602        out_expr: Option<ExprId>,
603    },
604    Const {
605        value: mir::Const<'tcx>,
606        span: Span,
607    },
608    SymFn {
609        value: mir::Const<'tcx>,
610        span: Span,
611    },
612    SymStatic {
613        def_id: DefId,
614    },
615    Label {
616        block: BlockId,
617    },
618}
619
620#[derive(Debug, HashStable, TypeVisitable)]
621pub struct FieldPat<'tcx> {
622    pub field: FieldIdx,
623    pub pattern: Pat<'tcx>,
624}
625
626#[derive(Debug, HashStable, TypeVisitable)]
627pub struct Pat<'tcx> {
628    pub ty: Ty<'tcx>,
629    pub span: Span,
630    pub kind: PatKind<'tcx>,
631}
632
633impl<'tcx> Pat<'tcx> {
634    pub fn simple_ident(&self) -> Option<Symbol> {
635        match self.kind {
636            PatKind::Binding {
637                name, mode: BindingMode(ByRef::No, _), subpattern: None, ..
638            } => Some(name),
639            _ => None,
640        }
641    }
642
643    /// Call `f` on every "binding" in a pattern, e.g., on `a` in
644    /// `match foo() { Some(a) => (), None => () }`
645    pub fn each_binding(&self, mut f: impl FnMut(Symbol, ByRef, Ty<'tcx>, Span)) {
646        self.walk_always(|p| {
647            if let PatKind::Binding { name, mode, ty, .. } = p.kind {
648                f(name, mode.0, ty, p.span);
649            }
650        });
651    }
652
653    /// Walk the pattern in left-to-right order.
654    ///
655    /// If `it(pat)` returns `false`, the children are not visited.
656    pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
657        self.walk_(&mut it)
658    }
659
660    fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
661        if !it(self) {
662            return;
663        }
664
665        use PatKind::*;
666        match &self.kind {
667            Wild
668            | Never
669            | Range(..)
670            | Binding { subpattern: None, .. }
671            | Constant { .. }
672            | Error(_) => {}
673            AscribeUserType { subpattern, .. }
674            | Binding { subpattern: Some(subpattern), .. }
675            | Deref { subpattern }
676            | DerefPattern { subpattern, .. }
677            | ExpandedConstant { subpattern, .. } => subpattern.walk_(it),
678            Leaf { subpatterns } | Variant { subpatterns, .. } => {
679                subpatterns.iter().for_each(|field| field.pattern.walk_(it))
680            }
681            Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
682            Array { box ref prefix, ref slice, box ref suffix }
683            | Slice { box ref prefix, ref slice, box ref suffix } => {
684                prefix.iter().chain(slice.as_deref()).chain(suffix.iter()).for_each(|p| p.walk_(it))
685            }
686        }
687    }
688
689    /// Whether the pattern has a `PatKind::Error` nested within.
690    pub fn pat_error_reported(&self) -> Result<(), ErrorGuaranteed> {
691        let mut error = None;
692        self.walk(|pat| {
693            if let PatKind::Error(e) = pat.kind
694                && error.is_none()
695            {
696                error = Some(e);
697            }
698            error.is_none()
699        });
700        match error {
701            None => Ok(()),
702            Some(e) => Err(e),
703        }
704    }
705
706    /// Walk the pattern in left-to-right order.
707    ///
708    /// If you always want to recurse, prefer this method over `walk`.
709    pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
710        self.walk(|p| {
711            it(p);
712            true
713        })
714    }
715
716    /// Whether this a never pattern.
717    pub fn is_never_pattern(&self) -> bool {
718        let mut is_never_pattern = false;
719        self.walk(|pat| match &pat.kind {
720            PatKind::Never => {
721                is_never_pattern = true;
722                false
723            }
724            PatKind::Or { pats } => {
725                is_never_pattern = pats.iter().all(|p| p.is_never_pattern());
726                false
727            }
728            _ => true,
729        });
730        is_never_pattern
731    }
732}
733
734#[derive(Debug, HashStable, TypeVisitable)]
735pub struct Ascription<'tcx> {
736    pub annotation: CanonicalUserTypeAnnotation<'tcx>,
737    /// Variance to use when relating the `user_ty` to the **type of the value being
738    /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
739    /// have a type that is some subtype of the ascribed type.
740    ///
741    /// Note that this variance does not apply for any bindings within subpatterns. The type
742    /// assigned to those bindings must be exactly equal to the `user_ty` given here.
743    ///
744    /// The only place where this field is not `Covariant` is when matching constants, where
745    /// we currently use `Contravariant` -- this is because the constant type just needs to
746    /// be "comparable" to the type of the input value. So, for example:
747    ///
748    /// ```text
749    /// match x { "foo" => .. }
750    /// ```
751    ///
752    /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
753    /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
754    /// of the old type-check for now. See #57280 for details.
755    pub variance: ty::Variance,
756}
757
758#[derive(Debug, HashStable, TypeVisitable)]
759pub enum PatKind<'tcx> {
760    /// A wildcard pattern: `_`.
761    Wild,
762
763    AscribeUserType {
764        ascription: Ascription<'tcx>,
765        subpattern: Box<Pat<'tcx>>,
766    },
767
768    /// `x`, `ref x`, `x @ P`, etc.
769    Binding {
770        name: Symbol,
771        #[type_visitable(ignore)]
772        mode: BindingMode,
773        #[type_visitable(ignore)]
774        var: LocalVarId,
775        ty: Ty<'tcx>,
776        subpattern: Option<Box<Pat<'tcx>>>,
777        /// Is this the leftmost occurrence of the binding, i.e., is `var` the
778        /// `HirId` of this pattern?
779        is_primary: bool,
780    },
781
782    /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
783    /// multiple variants.
784    Variant {
785        adt_def: AdtDef<'tcx>,
786        args: GenericArgsRef<'tcx>,
787        variant_index: VariantIdx,
788        subpatterns: Vec<FieldPat<'tcx>>,
789    },
790
791    /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
792    /// a single variant.
793    Leaf {
794        subpatterns: Vec<FieldPat<'tcx>>,
795    },
796
797    /// `box P`, `&P`, `&mut P`, etc.
798    Deref {
799        subpattern: Box<Pat<'tcx>>,
800    },
801
802    /// Deref pattern, written `box P` for now.
803    DerefPattern {
804        subpattern: Box<Pat<'tcx>>,
805        mutability: hir::Mutability,
806    },
807
808    /// One of the following:
809    /// * `&str`/`&[u8]` (represented as a valtree), which will be handled as a string/slice pattern
810    ///   and thus exhaustiveness checking will detect if you use the same string/slice twice in
811    ///   different patterns.
812    /// * integer, bool, char or float (represented as a valtree), which will be handled by
813    ///   exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
814    ///   much simpler.
815    /// * `String`, if `string_deref_patterns` is enabled.
816    Constant {
817        value: mir::Const<'tcx>,
818    },
819
820    /// Pattern obtained by converting a constant (inline or named) to its pattern
821    /// representation using `const_to_pat`.
822    ExpandedConstant {
823        /// [DefId] of the constant, we need this so that we have a
824        /// reference that can be used by unsafety checking to visit nested
825        /// unevaluated constants and for diagnostics. If the `DefId` doesn't
826        /// correspond to a local crate, it points at the `const` item.
827        def_id: DefId,
828        /// If `false`, then `def_id` points at a `const` item, otherwise it
829        /// corresponds to a local inline const.
830        is_inline: bool,
831        /// If the inline constant is used in a range pattern, this subpattern
832        /// represents the range (if both ends are inline constants, there will
833        /// be multiple InlineConstant wrappers).
834        ///
835        /// Otherwise, the actual pattern that the constant lowered to. As with
836        /// other constants, inline constants are matched structurally where
837        /// possible.
838        subpattern: Box<Pat<'tcx>>,
839    },
840
841    Range(Arc<PatRange<'tcx>>),
842
843    /// Matches against a slice, checking the length and extracting elements.
844    /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
845    /// e.g., `&[ref xs @ ..]`.
846    Slice {
847        prefix: Box<[Pat<'tcx>]>,
848        slice: Option<Box<Pat<'tcx>>>,
849        suffix: Box<[Pat<'tcx>]>,
850    },
851
852    /// Fixed match against an array; irrefutable.
853    Array {
854        prefix: Box<[Pat<'tcx>]>,
855        slice: Option<Box<Pat<'tcx>>>,
856        suffix: Box<[Pat<'tcx>]>,
857    },
858
859    /// An or-pattern, e.g. `p | q`.
860    /// Invariant: `pats.len() >= 2`.
861    Or {
862        pats: Box<[Pat<'tcx>]>,
863    },
864
865    /// A never pattern `!`.
866    Never,
867
868    /// An error has been encountered during lowering. We probably shouldn't report more lints
869    /// related to this pattern.
870    Error(ErrorGuaranteed),
871}
872
873/// A range pattern.
874/// The boundaries must be of the same type and that type must be numeric.
875#[derive(Clone, Debug, PartialEq, HashStable, TypeVisitable)]
876pub struct PatRange<'tcx> {
877    /// Must not be `PosInfinity`.
878    pub lo: PatRangeBoundary<'tcx>,
879    /// Must not be `NegInfinity`.
880    pub hi: PatRangeBoundary<'tcx>,
881    #[type_visitable(ignore)]
882    pub end: RangeEnd,
883    pub ty: Ty<'tcx>,
884}
885
886impl<'tcx> PatRange<'tcx> {
887    /// Whether this range covers the full extent of possible values (best-effort, we ignore floats).
888    #[inline]
889    pub fn is_full_range(&self, tcx: TyCtxt<'tcx>) -> Option<bool> {
890        let (min, max, size, bias) = match *self.ty.kind() {
891            ty::Char => (0, std::char::MAX as u128, Size::from_bits(32), 0),
892            ty::Int(ity) => {
893                let size = Integer::from_int_ty(&tcx, ity).size();
894                let max = size.truncate(u128::MAX);
895                let bias = 1u128 << (size.bits() - 1);
896                (0, max, size, bias)
897            }
898            ty::Uint(uty) => {
899                let size = Integer::from_uint_ty(&tcx, uty).size();
900                let max = size.unsigned_int_max();
901                (0, max, size, 0)
902            }
903            _ => return None,
904        };
905
906        // We want to compare ranges numerically, but the order of the bitwise representation of
907        // signed integers does not match their numeric order. Thus, to correct the ordering, we
908        // need to shift the range of signed integers to correct the comparison. This is achieved by
909        // XORing with a bias (see pattern/deconstruct_pat.rs for another pertinent example of this
910        // pattern).
911        //
912        // Also, for performance, it's important to only do the second `try_to_bits` if necessary.
913        let lo_is_min = match self.lo {
914            PatRangeBoundary::NegInfinity => true,
915            PatRangeBoundary::Finite(value) => {
916                let lo = value.try_to_bits(size).unwrap() ^ bias;
917                lo <= min
918            }
919            PatRangeBoundary::PosInfinity => false,
920        };
921        if lo_is_min {
922            let hi_is_max = match self.hi {
923                PatRangeBoundary::NegInfinity => false,
924                PatRangeBoundary::Finite(value) => {
925                    let hi = value.try_to_bits(size).unwrap() ^ bias;
926                    hi > max || hi == max && self.end == RangeEnd::Included
927                }
928                PatRangeBoundary::PosInfinity => true,
929            };
930            if hi_is_max {
931                return Some(true);
932            }
933        }
934        Some(false)
935    }
936
937    #[inline]
938    pub fn contains(
939        &self,
940        value: mir::Const<'tcx>,
941        tcx: TyCtxt<'tcx>,
942        typing_env: ty::TypingEnv<'tcx>,
943    ) -> Option<bool> {
944        use Ordering::*;
945        debug_assert_eq!(self.ty, value.ty());
946        let ty = self.ty;
947        let value = PatRangeBoundary::Finite(value);
948        // For performance, it's important to only do the second comparison if necessary.
949        Some(
950            match self.lo.compare_with(value, ty, tcx, typing_env)? {
951                Less | Equal => true,
952                Greater => false,
953            } && match value.compare_with(self.hi, ty, tcx, typing_env)? {
954                Less => true,
955                Equal => self.end == RangeEnd::Included,
956                Greater => false,
957            },
958        )
959    }
960
961    #[inline]
962    pub fn overlaps(
963        &self,
964        other: &Self,
965        tcx: TyCtxt<'tcx>,
966        typing_env: ty::TypingEnv<'tcx>,
967    ) -> Option<bool> {
968        use Ordering::*;
969        debug_assert_eq!(self.ty, other.ty);
970        // For performance, it's important to only do the second comparison if necessary.
971        Some(
972            match other.lo.compare_with(self.hi, self.ty, tcx, typing_env)? {
973                Less => true,
974                Equal => self.end == RangeEnd::Included,
975                Greater => false,
976            } && match self.lo.compare_with(other.hi, self.ty, tcx, typing_env)? {
977                Less => true,
978                Equal => other.end == RangeEnd::Included,
979                Greater => false,
980            },
981        )
982    }
983}
984
985impl<'tcx> fmt::Display for PatRange<'tcx> {
986    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
987        if let PatRangeBoundary::Finite(value) = &self.lo {
988            write!(f, "{value}")?;
989        }
990        if let PatRangeBoundary::Finite(value) = &self.hi {
991            write!(f, "{}", self.end)?;
992            write!(f, "{value}")?;
993        } else {
994            // `0..` is parsed as an inclusive range, we must display it correctly.
995            write!(f, "..")?;
996        }
997        Ok(())
998    }
999}
1000
1001/// A (possibly open) boundary of a range pattern.
1002/// If present, the const must be of a numeric type.
1003#[derive(Copy, Clone, Debug, PartialEq, HashStable, TypeVisitable)]
1004pub enum PatRangeBoundary<'tcx> {
1005    Finite(mir::Const<'tcx>),
1006    NegInfinity,
1007    PosInfinity,
1008}
1009
1010impl<'tcx> PatRangeBoundary<'tcx> {
1011    #[inline]
1012    pub fn is_finite(self) -> bool {
1013        matches!(self, Self::Finite(..))
1014    }
1015    #[inline]
1016    pub fn as_finite(self) -> Option<mir::Const<'tcx>> {
1017        match self {
1018            Self::Finite(value) => Some(value),
1019            Self::NegInfinity | Self::PosInfinity => None,
1020        }
1021    }
1022    pub fn eval_bits(
1023        self,
1024        ty: Ty<'tcx>,
1025        tcx: TyCtxt<'tcx>,
1026        typing_env: ty::TypingEnv<'tcx>,
1027    ) -> u128 {
1028        match self {
1029            Self::Finite(value) => value.eval_bits(tcx, typing_env),
1030            Self::NegInfinity => {
1031                // Unwrap is ok because the type is known to be numeric.
1032                ty.numeric_min_and_max_as_bits(tcx).unwrap().0
1033            }
1034            Self::PosInfinity => {
1035                // Unwrap is ok because the type is known to be numeric.
1036                ty.numeric_min_and_max_as_bits(tcx).unwrap().1
1037            }
1038        }
1039    }
1040
1041    #[instrument(skip(tcx, typing_env), level = "debug", ret)]
1042    pub fn compare_with(
1043        self,
1044        other: Self,
1045        ty: Ty<'tcx>,
1046        tcx: TyCtxt<'tcx>,
1047        typing_env: ty::TypingEnv<'tcx>,
1048    ) -> Option<Ordering> {
1049        use PatRangeBoundary::*;
1050        match (self, other) {
1051            // When comparing with infinities, we must remember that `0u8..` and `0u8..=255`
1052            // describe the same range. These two shortcuts are ok, but for the rest we must check
1053            // bit values.
1054            (PosInfinity, PosInfinity) => return Some(Ordering::Equal),
1055            (NegInfinity, NegInfinity) => return Some(Ordering::Equal),
1056
1057            // This code is hot when compiling matches with many ranges. So we
1058            // special-case extraction of evaluated scalars for speed, for types where
1059            // we can do scalar comparisons. E.g. `unicode-normalization` has
1060            // many ranges such as '\u{037A}'..='\u{037F}', and chars can be compared
1061            // in this way.
1062            (Finite(a), Finite(b)) if matches!(ty.kind(), ty::Int(_) | ty::Uint(_) | ty::Char) => {
1063                if let (Some(a), Some(b)) = (a.try_to_scalar_int(), b.try_to_scalar_int()) {
1064                    let sz = ty.primitive_size(tcx);
1065                    let cmp = match ty.kind() {
1066                        ty::Uint(_) | ty::Char => a.to_uint(sz).cmp(&b.to_uint(sz)),
1067                        ty::Int(_) => a.to_int(sz).cmp(&b.to_int(sz)),
1068                        _ => unreachable!(),
1069                    };
1070                    return Some(cmp);
1071                }
1072            }
1073            _ => {}
1074        }
1075
1076        let a = self.eval_bits(ty, tcx, typing_env);
1077        let b = other.eval_bits(ty, tcx, typing_env);
1078
1079        match ty.kind() {
1080            ty::Float(ty::FloatTy::F16) => {
1081                use rustc_apfloat::Float;
1082                let a = rustc_apfloat::ieee::Half::from_bits(a);
1083                let b = rustc_apfloat::ieee::Half::from_bits(b);
1084                a.partial_cmp(&b)
1085            }
1086            ty::Float(ty::FloatTy::F32) => {
1087                use rustc_apfloat::Float;
1088                let a = rustc_apfloat::ieee::Single::from_bits(a);
1089                let b = rustc_apfloat::ieee::Single::from_bits(b);
1090                a.partial_cmp(&b)
1091            }
1092            ty::Float(ty::FloatTy::F64) => {
1093                use rustc_apfloat::Float;
1094                let a = rustc_apfloat::ieee::Double::from_bits(a);
1095                let b = rustc_apfloat::ieee::Double::from_bits(b);
1096                a.partial_cmp(&b)
1097            }
1098            ty::Float(ty::FloatTy::F128) => {
1099                use rustc_apfloat::Float;
1100                let a = rustc_apfloat::ieee::Quad::from_bits(a);
1101                let b = rustc_apfloat::ieee::Quad::from_bits(b);
1102                a.partial_cmp(&b)
1103            }
1104            ty::Int(ity) => {
1105                let size = rustc_abi::Integer::from_int_ty(&tcx, *ity).size();
1106                let a = size.sign_extend(a) as i128;
1107                let b = size.sign_extend(b) as i128;
1108                Some(a.cmp(&b))
1109            }
1110            ty::Uint(_) | ty::Char => Some(a.cmp(&b)),
1111            _ => bug!(),
1112        }
1113    }
1114}
1115
1116// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
1117#[cfg(target_pointer_width = "64")]
1118mod size_asserts {
1119    use rustc_data_structures::static_assert_size;
1120
1121    use super::*;
1122    // tidy-alphabetical-start
1123    static_assert_size!(Block, 48);
1124    static_assert_size!(Expr<'_>, 72);
1125    static_assert_size!(ExprKind<'_>, 40);
1126    static_assert_size!(Pat<'_>, 64);
1127    static_assert_size!(PatKind<'_>, 48);
1128    static_assert_size!(Stmt<'_>, 48);
1129    static_assert_size!(StmtKind<'_>, 48);
1130    // tidy-alphabetical-end
1131}