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