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, 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 id of the HIR expression whose [temporary scope] should be used for this expression.
260    ///
261    /// [temporary scope]: https://doc.rust-lang.org/reference/destructors.html#temporary-scopes
262    pub temp_scope_id: hir::ItemLocalId,
263
264    /// span of the expression in the source
265    pub span: Span,
266}
267
268#[derive(Clone, Debug, HashStable)]
269pub enum ExprKind<'tcx> {
270    /// `Scope`s are used to explicitly mark destruction scopes,
271    /// and to track the `HirId` of the expressions within the scope.
272    Scope {
273        region_scope: region::Scope,
274        lint_level: LintLevel,
275        value: ExprId,
276    },
277    /// A `box <value>` expression.
278    Box {
279        value: ExprId,
280    },
281    /// An `if` expression.
282    If {
283        if_then_scope: region::Scope,
284        cond: ExprId,
285        /// `then` is always `ExprKind::Block`.
286        then: ExprId,
287        /// If present, the `else_opt` expr is always `ExprKind::Block` (for
288        /// `else`) or `ExprKind::If` (for `else if`).
289        else_opt: Option<ExprId>,
290    },
291    /// A function call. Method calls and overloaded operators are converted to plain function calls.
292    Call {
293        /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
294        ///
295        /// [`FnDef`]: ty::TyKind::FnDef
296        /// [`FnPtr`]: ty::TyKind::FnPtr
297        ty: Ty<'tcx>,
298        /// The function itself.
299        fun: ExprId,
300        /// The arguments passed to the function.
301        ///
302        /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
303        /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
304        args: Box<[ExprId]>,
305        /// Whether this is from an overloaded operator rather than a
306        /// function call from HIR. `true` for overloaded function call.
307        from_hir_call: bool,
308        /// The span of the function, without the dot and receiver
309        /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
310        fn_span: Span,
311    },
312    /// A use expression `x.use`.
313    ByUse {
314        /// The expression on which use is applied.
315        expr: ExprId,
316        /// The span of use, without the dot and receiver
317        /// (e.g. `use` in `x.use`).
318        span: Span,
319    },
320    /// A *non-overloaded* dereference.
321    Deref {
322        arg: ExprId,
323    },
324    /// A *non-overloaded* binary operation.
325    Binary {
326        op: BinOp,
327        lhs: ExprId,
328        rhs: ExprId,
329    },
330    /// A logical operation. This is distinct from `BinaryOp` because
331    /// the operands need to be lazily evaluated.
332    LogicalOp {
333        op: LogicalOp,
334        lhs: ExprId,
335        rhs: ExprId,
336    },
337    /// A *non-overloaded* unary operation. Note that here the deref (`*`)
338    /// operator is represented by `ExprKind::Deref`.
339    Unary {
340        op: UnOp,
341        arg: ExprId,
342    },
343    /// A cast: `<source> as <type>`. The type we cast to is the type of
344    /// the parent expression.
345    Cast {
346        source: ExprId,
347    },
348    /// Forces its contents to be treated as a value expression, not a place
349    /// expression. This is inserted in some places where an operation would
350    /// otherwise be erased completely (e.g. some no-op casts), but we still
351    /// need to ensure that its operand is treated as a value and not a place.
352    Use {
353        source: ExprId,
354    },
355    /// A coercion from `!` to any type.
356    NeverToAny {
357        source: ExprId,
358    },
359    /// A pointer coercion. More information can be found in [`PointerCoercion`].
360    /// Pointer casts that cannot be done by coercions are represented by [`ExprKind::Cast`].
361    PointerCoercion {
362        cast: PointerCoercion,
363        source: ExprId,
364        /// Whether this coercion is written with an `as` cast in the source code.
365        is_from_as_cast: bool,
366    },
367    /// A `loop` expression.
368    Loop {
369        body: ExprId,
370    },
371    /// A `#[loop_match] loop { state = 'blk: { match state { ... } } }` expression.
372    LoopMatch {
373        /// The state variable that is updated.
374        /// The `match_data.scrutinee` is the same variable, but with a different span.
375        state: ExprId,
376        region_scope: region::Scope,
377        match_data: Box<LoopMatchMatchData>,
378    },
379    /// Special expression representing the `let` part of an `if let` or similar construct
380    /// (including `if let` guards in match arms, and let-chains formed by `&&`).
381    ///
382    /// This isn't considered a real expression in surface Rust syntax, so it can
383    /// only appear in specific situations, such as within the condition of an `if`.
384    ///
385    /// (Not to be confused with [`StmtKind::Let`], which is a normal `let` statement.)
386    Let {
387        expr: ExprId,
388        pat: Box<Pat<'tcx>>,
389    },
390    /// A `match` expression.
391    Match {
392        scrutinee: ExprId,
393        arms: Box<[ArmId]>,
394        match_source: MatchSource,
395    },
396    /// A block.
397    Block {
398        block: BlockId,
399    },
400    /// An assignment: `lhs = rhs`.
401    Assign {
402        lhs: ExprId,
403        rhs: ExprId,
404    },
405    /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
406    AssignOp {
407        op: AssignOp,
408        lhs: ExprId,
409        rhs: ExprId,
410    },
411    /// Access to a field of a struct, a tuple, an union, or an enum.
412    Field {
413        lhs: ExprId,
414        /// Variant containing the field.
415        variant_index: VariantIdx,
416        /// This can be a named (`.foo`) or unnamed (`.0`) field.
417        name: FieldIdx,
418    },
419    /// A *non-overloaded* indexing operation.
420    Index {
421        lhs: ExprId,
422        index: ExprId,
423    },
424    /// A local variable.
425    VarRef {
426        id: LocalVarId,
427    },
428    /// Used to represent upvars mentioned in a closure/coroutine
429    UpvarRef {
430        /// DefId of the closure/coroutine
431        closure_def_id: DefId,
432
433        /// HirId of the root variable
434        var_hir_id: LocalVarId,
435    },
436    /// A borrow, e.g. `&arg`.
437    Borrow {
438        borrow_kind: BorrowKind,
439        arg: ExprId,
440    },
441    /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
442    RawBorrow {
443        mutability: hir::Mutability,
444        arg: ExprId,
445    },
446    /// A `break` expression.
447    Break {
448        label: region::Scope,
449        value: Option<ExprId>,
450    },
451    /// A `continue` expression.
452    Continue {
453        label: region::Scope,
454    },
455    /// A `#[const_continue] break` expression.
456    ConstContinue {
457        label: region::Scope,
458        value: ExprId,
459    },
460    /// A `return` expression.
461    Return {
462        value: Option<ExprId>,
463    },
464    /// A `become` expression.
465    Become {
466        value: ExprId,
467    },
468    /// An inline `const` block, e.g. `const {}`.
469    ConstBlock {
470        did: DefId,
471        args: GenericArgsRef<'tcx>,
472    },
473    /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
474    Repeat {
475        value: ExprId,
476        count: ty::Const<'tcx>,
477    },
478    /// An array, e.g. `[a, b, c, d]`.
479    Array {
480        fields: Box<[ExprId]>,
481    },
482    /// A tuple, e.g. `(a, b, c, d)`.
483    Tuple {
484        fields: Box<[ExprId]>,
485    },
486    /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
487    Adt(Box<AdtExpr<'tcx>>),
488    /// A type ascription on a place.
489    PlaceTypeAscription {
490        source: ExprId,
491        /// Type that the user gave to this expression
492        user_ty: UserTy<'tcx>,
493        user_ty_span: Span,
494    },
495    /// A type ascription on a value, e.g. `type_ascribe!(42, i32)` or `42 as i32`.
496    ValueTypeAscription {
497        source: ExprId,
498        /// Type that the user gave to this expression
499        user_ty: UserTy<'tcx>,
500        user_ty_span: Span,
501    },
502    /// An unsafe binder cast on a place, e.g. `unwrap_binder!(*ptr)`.
503    PlaceUnwrapUnsafeBinder {
504        source: ExprId,
505    },
506    /// An unsafe binder cast on a value, e.g. `unwrap_binder!(rvalue())`,
507    /// which makes a temporary.
508    ValueUnwrapUnsafeBinder {
509        source: ExprId,
510    },
511    /// Construct an unsafe binder, e.g. `wrap_binder(&ref)`.
512    WrapUnsafeBinder {
513        source: ExprId,
514    },
515    /// A closure definition.
516    Closure(Box<ClosureExpr<'tcx>>),
517    /// A literal.
518    Literal {
519        lit: hir::Lit,
520        neg: bool,
521    },
522    /// For literals that don't correspond to anything in the HIR
523    NonHirLiteral {
524        lit: ty::ScalarInt,
525        user_ty: UserTy<'tcx>,
526    },
527    /// A literal of a ZST type.
528    ZstLiteral {
529        user_ty: UserTy<'tcx>,
530    },
531    /// Associated constants and named constants
532    NamedConst {
533        def_id: DefId,
534        args: GenericArgsRef<'tcx>,
535        user_ty: UserTy<'tcx>,
536    },
537    ConstParam {
538        param: ty::ParamConst,
539        def_id: DefId,
540    },
541    // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
542    /// A literal containing the address of a `static`.
543    ///
544    /// This is only distinguished from `Literal` so that we can register some
545    /// info for diagnostics.
546    StaticRef {
547        alloc_id: AllocId,
548        ty: Ty<'tcx>,
549        def_id: DefId,
550    },
551    /// Inline assembly, i.e. `asm!()`.
552    InlineAsm(Box<InlineAsmExpr<'tcx>>),
553    /// An expression taking a reference to a thread local.
554    ThreadLocalRef(DefId),
555    /// A `yield` expression.
556    Yield {
557        value: ExprId,
558    },
559}
560
561/// Represents the association of a field identifier and an expression.
562///
563/// This is used in struct constructors.
564#[derive(Clone, Debug, HashStable)]
565pub struct FieldExpr {
566    pub name: FieldIdx,
567    pub expr: ExprId,
568}
569
570#[derive(Clone, Debug, HashStable)]
571pub struct FruInfo<'tcx> {
572    pub base: ExprId,
573    pub field_types: Box<[Ty<'tcx>]>,
574}
575
576/// A `match` arm.
577#[derive(Clone, Debug, HashStable)]
578pub struct Arm<'tcx> {
579    pub pattern: Box<Pat<'tcx>>,
580    pub guard: Option<ExprId>,
581    pub body: ExprId,
582    pub lint_level: LintLevel,
583    pub scope: region::Scope,
584    pub span: Span,
585}
586
587/// The `match` part of a `#[loop_match]`
588#[derive(Clone, Debug, HashStable)]
589pub struct LoopMatchMatchData {
590    pub scrutinee: ExprId,
591    pub arms: Box<[ArmId]>,
592    pub span: Span,
593}
594
595#[derive(Copy, Clone, Debug, HashStable)]
596pub enum LogicalOp {
597    /// The `&&` operator.
598    And,
599    /// The `||` operator.
600    Or,
601}
602
603#[derive(Clone, Debug, HashStable)]
604pub enum InlineAsmOperand<'tcx> {
605    In {
606        reg: InlineAsmRegOrRegClass,
607        expr: ExprId,
608    },
609    Out {
610        reg: InlineAsmRegOrRegClass,
611        late: bool,
612        expr: Option<ExprId>,
613    },
614    InOut {
615        reg: InlineAsmRegOrRegClass,
616        late: bool,
617        expr: ExprId,
618    },
619    SplitInOut {
620        reg: InlineAsmRegOrRegClass,
621        late: bool,
622        in_expr: ExprId,
623        out_expr: Option<ExprId>,
624    },
625    Const {
626        value: mir::Const<'tcx>,
627        span: Span,
628    },
629    SymFn {
630        value: ExprId,
631    },
632    SymStatic {
633        def_id: DefId,
634    },
635    Label {
636        block: BlockId,
637    },
638}
639
640#[derive(Clone, Debug, HashStable, TypeVisitable)]
641pub struct FieldPat<'tcx> {
642    pub field: FieldIdx,
643    pub pattern: Pat<'tcx>,
644}
645
646#[derive(Clone, Debug, HashStable, TypeVisitable)]
647pub struct Pat<'tcx> {
648    pub ty: Ty<'tcx>,
649    pub span: Span,
650    pub kind: PatKind<'tcx>,
651}
652
653impl<'tcx> Pat<'tcx> {
654    pub fn simple_ident(&self) -> Option<Symbol> {
655        match self.kind {
656            PatKind::Binding {
657                name, mode: BindingMode(ByRef::No, _), subpattern: None, ..
658            } => Some(name),
659            _ => None,
660        }
661    }
662
663    /// Call `f` on every "binding" in a pattern, e.g., on `a` in
664    /// `match foo() { Some(a) => (), None => () }`
665    pub fn each_binding(&self, mut f: impl FnMut(Symbol, ByRef, Ty<'tcx>, Span)) {
666        self.walk_always(|p| {
667            if let PatKind::Binding { name, mode, ty, .. } = p.kind {
668                f(name, mode.0, ty, p.span);
669            }
670        });
671    }
672
673    /// Walk the pattern in left-to-right order.
674    ///
675    /// If `it(pat)` returns `false`, the children are not visited.
676    pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
677        self.walk_(&mut it)
678    }
679
680    fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
681        if !it(self) {
682            return;
683        }
684
685        for_each_immediate_subpat(self, |p| p.walk_(it));
686    }
687
688    /// Whether the pattern has a `PatKind::Error` nested within.
689    pub fn pat_error_reported(&self) -> Result<(), ErrorGuaranteed> {
690        let mut error = None;
691        self.walk(|pat| {
692            if let PatKind::Error(e) = pat.kind
693                && error.is_none()
694            {
695                error = Some(e);
696            }
697            error.is_none()
698        });
699        match error {
700            None => Ok(()),
701            Some(e) => Err(e),
702        }
703    }
704
705    /// Walk the pattern in left-to-right order.
706    ///
707    /// If you always want to recurse, prefer this method over `walk`.
708    pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
709        self.walk(|p| {
710            it(p);
711            true
712        })
713    }
714
715    /// Whether this a never pattern.
716    pub fn is_never_pattern(&self) -> bool {
717        let mut is_never_pattern = false;
718        self.walk(|pat| match &pat.kind {
719            PatKind::Never => {
720                is_never_pattern = true;
721                false
722            }
723            PatKind::Or { pats } => {
724                is_never_pattern = pats.iter().all(|p| p.is_never_pattern());
725                false
726            }
727            _ => true,
728        });
729        is_never_pattern
730    }
731}
732
733#[derive(Clone, Debug, HashStable, TypeVisitable)]
734pub struct Ascription<'tcx> {
735    pub annotation: CanonicalUserTypeAnnotation<'tcx>,
736    /// Variance to use when relating the `user_ty` to the **type of the value being
737    /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
738    /// have a type that is some subtype of the ascribed type.
739    ///
740    /// Note that this variance does not apply for any bindings within subpatterns. The type
741    /// assigned to those bindings must be exactly equal to the `user_ty` given here.
742    ///
743    /// The only place where this field is not `Covariant` is when matching constants, where
744    /// we currently use `Contravariant` -- this is because the constant type just needs to
745    /// be "comparable" to the type of the input value. So, for example:
746    ///
747    /// ```text
748    /// match x { "foo" => .. }
749    /// ```
750    ///
751    /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
752    /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
753    /// of the old type-check for now. See #57280 for details.
754    pub variance: ty::Variance,
755}
756
757#[derive(Clone, Debug, HashStable, TypeVisitable)]
758pub enum PatKind<'tcx> {
759    /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.
760    Missing,
761
762    /// A wildcard pattern: `_`.
763    Wild,
764
765    AscribeUserType {
766        ascription: Ascription<'tcx>,
767        subpattern: Box<Pat<'tcx>>,
768    },
769
770    /// `x`, `ref x`, `x @ P`, etc.
771    Binding {
772        name: Symbol,
773        #[type_visitable(ignore)]
774        mode: BindingMode,
775        #[type_visitable(ignore)]
776        var: LocalVarId,
777        ty: Ty<'tcx>,
778        subpattern: Option<Box<Pat<'tcx>>>,
779
780        /// Is this the leftmost occurrence of the binding, i.e., is `var` the
781        /// `HirId` of this pattern?
782        ///
783        /// (The same binding can occur multiple times in different branches of
784        /// an or-pattern, but only one of them will be primary.)
785        is_primary: bool,
786        /// Is this binding a shorthand struct pattern, i.e. `Foo { a }`?
787        is_shorthand: bool,
788    },
789
790    /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
791    /// multiple variants.
792    Variant {
793        adt_def: AdtDef<'tcx>,
794        args: GenericArgsRef<'tcx>,
795        variant_index: VariantIdx,
796        subpatterns: Vec<FieldPat<'tcx>>,
797    },
798
799    /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
800    /// a single variant.
801    Leaf {
802        subpatterns: Vec<FieldPat<'tcx>>,
803    },
804
805    /// `box P`, `&P`, `&mut P`, etc.
806    Deref {
807        subpattern: Box<Pat<'tcx>>,
808    },
809
810    /// Deref pattern, written `box P` for now.
811    DerefPattern {
812        subpattern: Box<Pat<'tcx>>,
813        /// Whether the pattern scrutinee needs to be borrowed in order to call `Deref::deref` or
814        /// `DerefMut::deref_mut`, and if so, which. This is `ByRef::No` for deref patterns on
815        /// boxes; they are lowered using a built-in deref rather than a method call, thus they
816        /// don't borrow the scrutinee.
817        #[type_visitable(ignore)]
818        borrow: ByRef,
819    },
820
821    /// One of the following:
822    /// * `&str`, which will be handled as a string pattern and thus
823    ///   exhaustiveness checking will detect if you use the same string twice in different
824    ///   patterns.
825    /// * integer, bool, char or float, which will be handled by
826    ///   exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
827    ///   much simpler.
828    /// * raw pointers derived from integers, other raw pointers will have already resulted in an
829    ///   error.
830    /// * `String`, if `string_deref_patterns` is enabled.
831    Constant {
832        value: ty::Value<'tcx>,
833    },
834
835    /// Pattern obtained by converting a constant (inline or named) to its pattern
836    /// representation using `const_to_pat`. This is used for unsafety checking.
837    ExpandedConstant {
838        /// [DefId] of the constant item.
839        def_id: DefId,
840        /// The pattern that the constant lowered to.
841        ///
842        /// HACK: we need to keep the `DefId` of inline constants around for unsafety checking;
843        /// therefore when a range pattern contains inline constants, we re-wrap the range pattern
844        /// with the `ExpandedConstant` nodes that correspond to the range endpoints. Hence
845        /// `subpattern` may actually be a range pattern, and `def_id` be the constant for one of
846        /// its endpoints.
847        subpattern: Box<Pat<'tcx>>,
848    },
849
850    Range(Arc<PatRange<'tcx>>),
851
852    /// Matches against a slice, checking the length and extracting elements.
853    /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
854    /// e.g., `&[ref xs @ ..]`.
855    Slice {
856        prefix: Box<[Pat<'tcx>]>,
857        slice: Option<Box<Pat<'tcx>>>,
858        suffix: Box<[Pat<'tcx>]>,
859    },
860
861    /// Fixed match against an array; irrefutable.
862    Array {
863        prefix: Box<[Pat<'tcx>]>,
864        slice: Option<Box<Pat<'tcx>>>,
865        suffix: Box<[Pat<'tcx>]>,
866    },
867
868    /// An or-pattern, e.g. `p | q`.
869    /// Invariant: `pats.len() >= 2`.
870    Or {
871        pats: Box<[Pat<'tcx>]>,
872    },
873
874    /// A never pattern `!`.
875    Never,
876
877    /// An error has been encountered during lowering. We probably shouldn't report more lints
878    /// related to this pattern.
879    Error(ErrorGuaranteed),
880}
881
882/// A range pattern.
883/// The boundaries must be of the same type and that type must be numeric.
884#[derive(Clone, Debug, PartialEq, HashStable, TypeVisitable)]
885pub struct PatRange<'tcx> {
886    /// Must not be `PosInfinity`.
887    pub lo: PatRangeBoundary<'tcx>,
888    /// Must not be `NegInfinity`.
889    pub hi: PatRangeBoundary<'tcx>,
890    #[type_visitable(ignore)]
891    pub end: RangeEnd,
892    pub ty: Ty<'tcx>,
893}
894
895impl<'tcx> PatRange<'tcx> {
896    /// Whether this range covers the full extent of possible values (best-effort, we ignore floats).
897    #[inline]
898    pub fn is_full_range(&self, tcx: TyCtxt<'tcx>) -> Option<bool> {
899        let (min, max, size, bias) = match *self.ty.kind() {
900            ty::Char => (0, std::char::MAX as u128, Size::from_bits(32), 0),
901            ty::Int(ity) => {
902                let size = Integer::from_int_ty(&tcx, ity).size();
903                let max = size.truncate(u128::MAX);
904                let bias = 1u128 << (size.bits() - 1);
905                (0, max, size, bias)
906            }
907            ty::Uint(uty) => {
908                let size = Integer::from_uint_ty(&tcx, uty).size();
909                let max = size.unsigned_int_max();
910                (0, max, size, 0)
911            }
912            _ => return None,
913        };
914
915        // We want to compare ranges numerically, but the order of the bitwise representation of
916        // signed integers does not match their numeric order. Thus, to correct the ordering, we
917        // need to shift the range of signed integers to correct the comparison. This is achieved by
918        // XORing with a bias (see pattern/deconstruct_pat.rs for another pertinent example of this
919        // pattern).
920        //
921        // Also, for performance, it's important to only do the second `try_to_bits` if necessary.
922        let lo_is_min = match self.lo {
923            PatRangeBoundary::NegInfinity => true,
924            PatRangeBoundary::Finite(value) => {
925                let lo = value.try_to_scalar_int().unwrap().to_bits(size) ^ bias;
926                lo <= min
927            }
928            PatRangeBoundary::PosInfinity => false,
929        };
930        if lo_is_min {
931            let hi_is_max = match self.hi {
932                PatRangeBoundary::NegInfinity => false,
933                PatRangeBoundary::Finite(value) => {
934                    let hi = value.try_to_scalar_int().unwrap().to_bits(size) ^ bias;
935                    hi > max || hi == max && self.end == RangeEnd::Included
936                }
937                PatRangeBoundary::PosInfinity => true,
938            };
939            if hi_is_max {
940                return Some(true);
941            }
942        }
943        Some(false)
944    }
945
946    #[inline]
947    pub fn contains(&self, value: ty::Value<'tcx>, tcx: TyCtxt<'tcx>) -> Option<bool> {
948        use Ordering::*;
949        debug_assert_eq!(value.ty, self.ty);
950        let ty = self.ty;
951        let value = PatRangeBoundary::Finite(value.valtree);
952        // For performance, it's important to only do the second comparison if necessary.
953        Some(
954            match self.lo.compare_with(value, ty, tcx)? {
955                Less | Equal => true,
956                Greater => false,
957            } && match value.compare_with(self.hi, ty, tcx)? {
958                Less => true,
959                Equal => self.end == RangeEnd::Included,
960                Greater => false,
961            },
962        )
963    }
964
965    #[inline]
966    pub fn overlaps(&self, other: &Self, tcx: TyCtxt<'tcx>) -> 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)? {
972                Less => true,
973                Equal => self.end == RangeEnd::Included,
974                Greater => false,
975            } && match self.lo.compare_with(other.hi, self.ty, tcx)? {
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(valtree) = &self.lo {
987            let value = ty::Value { ty: self.ty, valtree };
988            write!(f, "{value}")?;
989        }
990        if let &PatRangeBoundary::Finite(valtree) = &self.hi {
991            write!(f, "{}", self.end)?;
992            let value = ty::Value { ty: self.ty, valtree };
993            write!(f, "{value}")?;
994        } else {
995            // `0..` is parsed as an inclusive range, we must display it correctly.
996            write!(f, "..")?;
997        }
998        Ok(())
999    }
1000}
1001
1002/// A (possibly open) boundary of a range pattern.
1003/// If present, the const must be of a numeric type.
1004#[derive(Copy, Clone, Debug, PartialEq, HashStable, TypeVisitable)]
1005pub enum PatRangeBoundary<'tcx> {
1006    /// The type of this valtree is stored in the surrounding `PatRange`.
1007    Finite(ty::ValTree<'tcx>),
1008    NegInfinity,
1009    PosInfinity,
1010}
1011
1012impl<'tcx> PatRangeBoundary<'tcx> {
1013    #[inline]
1014    pub fn is_finite(self) -> bool {
1015        matches!(self, Self::Finite(..))
1016    }
1017    #[inline]
1018    pub fn as_finite(self) -> Option<ty::ValTree<'tcx>> {
1019        match self {
1020            Self::Finite(value) => Some(value),
1021            Self::NegInfinity | Self::PosInfinity => None,
1022        }
1023    }
1024    pub fn to_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> u128 {
1025        match self {
1026            Self::Finite(value) => value.try_to_scalar_int().unwrap().to_bits_unchecked(),
1027            Self::NegInfinity => {
1028                // Unwrap is ok because the type is known to be numeric.
1029                ty.numeric_min_and_max_as_bits(tcx).unwrap().0
1030            }
1031            Self::PosInfinity => {
1032                // Unwrap is ok because the type is known to be numeric.
1033                ty.numeric_min_and_max_as_bits(tcx).unwrap().1
1034            }
1035        }
1036    }
1037
1038    #[instrument(skip(tcx), level = "debug", ret)]
1039    pub fn compare_with(self, other: Self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<Ordering> {
1040        use PatRangeBoundary::*;
1041        match (self, other) {
1042            // When comparing with infinities, we must remember that `0u8..` and `0u8..=255`
1043            // describe the same range. These two shortcuts are ok, but for the rest we must check
1044            // bit values.
1045            (PosInfinity, PosInfinity) => return Some(Ordering::Equal),
1046            (NegInfinity, NegInfinity) => return Some(Ordering::Equal),
1047
1048            // This code is hot when compiling matches with many ranges. So we
1049            // special-case extraction of evaluated scalars for speed, for types where
1050            // we can do scalar comparisons. E.g. `unicode-normalization` has
1051            // many ranges such as '\u{037A}'..='\u{037F}', and chars can be compared
1052            // in this way.
1053            (Finite(a), Finite(b)) if matches!(ty.kind(), ty::Int(_) | ty::Uint(_) | ty::Char) => {
1054                if let (Some(a), Some(b)) = (a.try_to_scalar_int(), b.try_to_scalar_int()) {
1055                    let sz = ty.primitive_size(tcx);
1056                    let cmp = match ty.kind() {
1057                        ty::Uint(_) | ty::Char => a.to_uint(sz).cmp(&b.to_uint(sz)),
1058                        ty::Int(_) => a.to_int(sz).cmp(&b.to_int(sz)),
1059                        _ => unreachable!(),
1060                    };
1061                    return Some(cmp);
1062                }
1063            }
1064            _ => {}
1065        }
1066
1067        let a = self.to_bits(ty, tcx);
1068        let b = other.to_bits(ty, tcx);
1069
1070        match ty.kind() {
1071            ty::Float(ty::FloatTy::F16) => {
1072                use rustc_apfloat::Float;
1073                let a = rustc_apfloat::ieee::Half::from_bits(a);
1074                let b = rustc_apfloat::ieee::Half::from_bits(b);
1075                a.partial_cmp(&b)
1076            }
1077            ty::Float(ty::FloatTy::F32) => {
1078                use rustc_apfloat::Float;
1079                let a = rustc_apfloat::ieee::Single::from_bits(a);
1080                let b = rustc_apfloat::ieee::Single::from_bits(b);
1081                a.partial_cmp(&b)
1082            }
1083            ty::Float(ty::FloatTy::F64) => {
1084                use rustc_apfloat::Float;
1085                let a = rustc_apfloat::ieee::Double::from_bits(a);
1086                let b = rustc_apfloat::ieee::Double::from_bits(b);
1087                a.partial_cmp(&b)
1088            }
1089            ty::Float(ty::FloatTy::F128) => {
1090                use rustc_apfloat::Float;
1091                let a = rustc_apfloat::ieee::Quad::from_bits(a);
1092                let b = rustc_apfloat::ieee::Quad::from_bits(b);
1093                a.partial_cmp(&b)
1094            }
1095            ty::Int(ity) => {
1096                let size = rustc_abi::Integer::from_int_ty(&tcx, *ity).size();
1097                let a = size.sign_extend(a) as i128;
1098                let b = size.sign_extend(b) as i128;
1099                Some(a.cmp(&b))
1100            }
1101            ty::Uint(_) | ty::Char => Some(a.cmp(&b)),
1102            _ => bug!(),
1103        }
1104    }
1105}
1106
1107// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
1108#[cfg(target_pointer_width = "64")]
1109mod size_asserts {
1110    use rustc_data_structures::static_assert_size;
1111
1112    use super::*;
1113    // tidy-alphabetical-start
1114    static_assert_size!(Block, 48);
1115    static_assert_size!(Expr<'_>, 64);
1116    static_assert_size!(ExprKind<'_>, 40);
1117    static_assert_size!(Pat<'_>, 64);
1118    static_assert_size!(PatKind<'_>, 48);
1119    static_assert_size!(Stmt<'_>, 48);
1120    static_assert_size!(StmtKind<'_>, 48);
1121    // tidy-alphabetical-end
1122}