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