Skip to main content

rustc_mir_build/thir/pattern/
mod.rs

1//! Validation of patterns/matches.
2
3mod check_match;
4mod const_to_pat;
5mod migration;
6
7use std::assert_matches;
8use std::cmp::Ordering;
9use std::sync::Arc;
10
11use rustc_abi::{FieldIdx, Integer};
12use rustc_ast::LitKind;
13use rustc_errors::codes::*;
14use rustc_hir::def::{CtorOf, DefKind, Res};
15use rustc_hir::pat_util::EnumerateAndAdjustIterator;
16use rustc_hir::{self as hir, RangeEnd};
17use rustc_index::Idx;
18use rustc_middle::thir::{
19    Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
20};
21use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
22use rustc_middle::ty::layout::IntegerExt;
23use rustc_middle::ty::{
24    self, CanonicalUserTypeAnnotation, LitToConstInput, Ty, TyCtxt, const_lit_matches_ty,
25};
26use rustc_span::{ErrorGuaranteed, bug, span_bug};
27use tracing::{debug, instrument};
28
29pub(crate) use self::check_match::check_match;
30use self::migration::PatMigration;
31use crate::diagnostics::*;
32use crate::thir::cx::ThirBuildCx;
33
34/// Context for lowering HIR patterns to THIR patterns.
35struct PatCtxt<'tcx, 'ptcx> {
36    upper: &'ptcx mut ThirBuildCx<'tcx>,
37    tcx: TyCtxt<'tcx>,
38    typing_env: ty::TypingEnv<'tcx>,
39    typeck_results: &'tcx ty::TypeckResults<'tcx>,
40
41    /// Used by the Rust 2024 migration lint.
42    rust_2024_migration: Option<PatMigration<'tcx>>,
43}
44
45{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::DEBUG <=
                ::tracing::level_filters::LevelFilter::current() || { false }
    {
    __tracing_attr_span =
        {
            use ::tracing::__macro_support::Callsite as _;
            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                {
                    static META: ::tracing::Metadata<'static> =
                        {
                            ::tracing_core::metadata::Metadata::new("pat_from_hir",
                                "rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                                ::tracing_core::__macro_support::Option::Some(45u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("pat")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("pat");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("let_stmt_type")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("let_stmt_type");
                                                    NAME.as_str()
                                                }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                ::tracing::metadata::Kind::SPAN)
                        };
                    ::tracing::callsite::DefaultCallsite::new(&META)
                };
            let mut interest = ::tracing::subscriber::Interest::never();
            if ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        { interest = __CALLSITE.interest(); !interest.is_never() }
                    &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest) {
                let meta = __CALLSITE.metadata();
                ::tracing::Span::new(meta,
                    &{
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pat)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&let_stmt_type)
                                                        as &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[allow(unknown_lints, unreachable_code, clippy ::
                    diverging_sub_expression, clippy :: empty_loop, clippy ::
                    let_unit_value, clippy :: let_with_type_underscore, clippy
                    :: needless_return, clippy :: unreachable)]
                    if false {
                        let __tracing_attr_fake_return: Box<Pat<'tcx>> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        let mut pcx =
                            PatCtxt {
                                upper,
                                tcx,
                                typing_env,
                                typeck_results,
                                rust_2024_migration: typeck_results.rust_2024_migration_desugared_pats().get(pat.hir_id).map(PatMigration::new),
                            };
                        let mut thir_pat = pcx.lower_pattern(pat);
                        if let Some(let_stmt_type) = let_stmt_type &&
                                let Some(&user_ty) =
                                    typeck_results.user_provided_types().get(let_stmt_type.hir_id)
                            {
                            {
                                use ::tracing::__macro_support::Callsite as _;
                                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                    {
                                        static META: ::tracing::Metadata<'static> =
                                            {
                                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs:73",
                                                    "rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
                                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                                                    ::tracing_core::__macro_support::Option::Some(73u32),
                                                    ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
                                                    ::tracing_core::field::FieldSet::new(&[{
                                                                        const NAME:
                                                                            ::tracing::__macro_support::FieldName<{
                                                                                ::tracing::__macro_support::FieldName::len("user_ty")
                                                                            }> =
                                                                            ::tracing::__macro_support::FieldName::new("user_ty");
                                                                        NAME.as_str()
                                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                    ::tracing::metadata::Kind::EVENT)
                                            };
                                        ::tracing::callsite::DefaultCallsite::new(&META)
                                    };
                                let enabled =
                                    ::tracing::Level::DEBUG <=
                                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                            ::tracing::Level::DEBUG <=
                                                ::tracing::level_filters::LevelFilter::current() &&
                                        {
                                            let interest = __CALLSITE.interest();
                                            !interest.is_never() &&
                                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                    interest)
                                        };
                                if enabled {
                                    (|value_set: ::tracing::field::ValueSet|
                                                {
                                                    let meta = __CALLSITE.metadata();
                                                    ::tracing::Event::dispatch(meta, &value_set);
                                                    ;
                                                })({
                                            #[allow(unused_imports)]
                                            use ::tracing::field::{debug, display, Value};
                                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&user_ty)
                                                                        as &dyn ::tracing::field::Value))])
                                        });
                                } else { ; }
                            };
                            let annotation =
                                CanonicalUserTypeAnnotation {
                                    user_ty: Box::new(user_ty),
                                    span: let_stmt_type.span,
                                    inferred_ty: typeck_results.node_type(let_stmt_type.hir_id),
                                };
                            thir_pat.extra.get_or_insert_default().ascriptions.push(Ascription {
                                    annotation,
                                    variance: ty::Covariant,
                                });
                        }
                        if let Some(m) = pcx.rust_2024_migration {
                            m.emit(tcx, pat.hir_id);
                        }
                        thir_pat
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs:45",
                        "rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(45u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(level = "debug", skip(upper, tcx, typing_env, typeck_results), ret)]
46pub(super) fn pat_from_hir<'tcx, 'ptcx>(
47    upper: &'ptcx mut ThirBuildCx<'tcx>,
48    tcx: TyCtxt<'tcx>,
49    typing_env: ty::TypingEnv<'tcx>,
50    typeck_results: &'tcx ty::TypeckResults<'tcx>,
51    pat: &'tcx hir::Pat<'tcx>,
52    // Present if `pat` came from a let statement with an explicit type annotation
53    let_stmt_type: Option<&hir::Ty<'tcx>>,
54) -> Box<Pat<'tcx>> {
55    let mut pcx = PatCtxt {
56        upper,
57        tcx,
58        typing_env,
59        typeck_results,
60        rust_2024_migration: typeck_results
61            .rust_2024_migration_desugared_pats()
62            .get(pat.hir_id)
63            .map(PatMigration::new),
64    };
65
66    let mut thir_pat = pcx.lower_pattern(pat);
67
68    // If this pattern came from a let statement with an explicit type annotation
69    // (e.g. `let x: Foo = ...`), retain that user type information in the THIR pattern.
70    if let Some(let_stmt_type) = let_stmt_type
71        && let Some(&user_ty) = typeck_results.user_provided_types().get(let_stmt_type.hir_id)
72    {
73        debug!(?user_ty);
74        let annotation = CanonicalUserTypeAnnotation {
75            user_ty: Box::new(user_ty),
76            span: let_stmt_type.span,
77            inferred_ty: typeck_results.node_type(let_stmt_type.hir_id),
78        };
79        thir_pat
80            .extra
81            .get_or_insert_default()
82            .ascriptions
83            .push(Ascription { annotation, variance: ty::Covariant });
84    }
85
86    if let Some(m) = pcx.rust_2024_migration {
87        m.emit(tcx, pat.hir_id);
88    }
89
90    thir_pat
91}
92
93impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> {
94    fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
95        let adjustments: &[PatAdjustment<'tcx>] =
96            self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
97
98        // Track the default binding mode for the Rust 2024 migration suggestion.
99        // Implicitly dereferencing references changes the default binding mode, but implicit deref
100        // patterns do not. Only track binding mode changes if a ref type is in the adjustments.
101        let mut opt_old_mode_span = None;
102        if let Some(s) = &mut self.rust_2024_migration
103            && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
104        {
105            opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments);
106        }
107
108        // When implicit dereferences have been inserted in this pattern, the unadjusted lowered
109        // pattern has the type that results *after* dereferencing. For example, in this code:
110        //
111        // ```
112        // match &&Some(0i32) {
113        //     Some(n) => { ... },
114        //     _ => { ... },
115        // }
116        // ```
117        //
118        // the type assigned to `Some(n)` in `unadjusted_pat` would be `Option<i32>` (this is
119        // determined in rustc_hir_analysis::check::match). The adjustments would be
120        //
121        // `vec![&&Option<i32>, &Option<i32>]`.
122        //
123        // Applying the adjustments, we want to instead output `&&Some(n)` (as a THIR pattern). So
124        // we wrap the unadjusted pattern in `PatKind::Deref` repeatedly, consuming the
125        // adjustments in *reverse order* (last-in-first-out, so that the last `Deref` inserted
126        // gets the least-dereferenced type).
127        let unadjusted_pat = match pat.kind {
128            hir::PatKind::Ref(inner, _, _)
129                if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) =>
130            {
131                self.lower_pattern(inner)
132            }
133            _ => self.lower_pattern_unadjusted(pat),
134        };
135
136        let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| {
137            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs:137",
                        "rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(137u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("{0:?}: wrapping pattern with adjustment {1:?}",
                                                    thir_pat, adjust) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust);
138            let span = thir_pat.span;
139            let kind = match adjust.kind {
140                PatAdjust::BuiltinDeref => {
141                    PatKind::Deref { pin: hir::Pinnedness::Not, subpattern: thir_pat }
142                }
143                PatAdjust::OverloadedDeref => {
144                    let borrow = self.typeck_results.deref_pat_borrow_mode(adjust.source, pat);
145                    PatKind::DerefPattern { subpattern: thir_pat, borrow }
146                }
147                PatAdjust::PinDeref => {
148                    PatKind::Deref { pin: hir::Pinnedness::Pinned, subpattern: thir_pat }
149                }
150            };
151            Box::new(Pat { span, ty: adjust.source, kind, extra: None })
152        });
153
154        if let Some(s) = &mut self.rust_2024_migration
155            && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
156        {
157            s.leave_ref(opt_old_mode_span);
158        }
159
160        adjusted_pat
161    }
162
163    fn lower_pattern_range_endpoint(
164        &mut self,
165        pat: &'tcx hir::Pat<'tcx>, // Range pattern containing the endpoint
166        expr: Option<&'tcx hir::PatExpr<'tcx>>,
167        // Out-parameter collecting extra data to be reapplied by the caller
168        ascriptions: &mut Vec<Ascription<'tcx>>,
169    ) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
170        {
    match pat.kind {
        hir::PatKind::Range(..) => {}
        ref left_val => {
            ::core::panicking::assert_matches_failed(left_val,
                "hir::PatKind::Range(..)", ::core::option::Option::None);
        }
    }
};assert_matches!(pat.kind, hir::PatKind::Range(..));
171
172        // For partly-bounded ranges like `X..` or `..X`, an endpoint will be absent.
173        // Return None in that case; the caller will use NegInfinity or PosInfinity instead.
174        let Some(expr) = expr else { return Ok(None) };
175
176        // Lower the endpoint into a temporary `thir::Pat` that will then be
177        // deconstructed to obtain the constant value and other data.
178        let endpoint_pat: Box<Pat<'tcx>> = self.lower_pat_expr(pat, expr);
179        let Pat { ref kind, extra, .. } = endpoint_pat;
180
181        // Preserve any ascriptions from endpoint constants.
182        if let Some(extra) = extra {
183            ascriptions.extend(extra.ascriptions);
184        }
185
186        // The unpeeled kind should now be a constant, giving us the endpoint value.
187        let PatKind::Constant { value } = kind else {
188            let msg =
189                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("found bad range pattern endpoint `{0:?}` outside of error recovery",
                expr))
    })format!("found bad range pattern endpoint `{expr:?}` outside of error recovery");
190            return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
191        };
192        Ok(Some(PatRangeBoundary::Finite(value.valtree)))
193    }
194
195    /// Overflowing literals are linted against in a late pass. This is mostly fine, except when we
196    /// encounter a range pattern like `-130i8..2`: if we believe `eval_bits`, this looks like a
197    /// range where the endpoints are in the wrong order. To avoid a confusing error message, we
198    /// check for overflow then.
199    /// This is only called when the range is already known to be malformed.
200    fn error_on_literal_overflow(
201        &self,
202        expr: Option<&'tcx hir::PatExpr<'tcx>>,
203        ty: Ty<'tcx>,
204    ) -> Result<(), ErrorGuaranteed> {
205        let Some(expr) = expr else {
206            return Ok(());
207        };
208        let span = expr.span;
209
210        // We need to inspect the original expression, because if we only inspect the output of
211        // `eval_bits`, an overflowed value has already been wrapped around.
212        // We mostly copy the logic from the `rustc_lint::OVERFLOWING_LITERALS` lint.
213        let hir::PatExprKind::Lit { lit, negated } = expr.kind else {
214            return Ok(());
215        };
216        let LitKind::Int(lit_val, _) = lit.node else {
217            return Ok(());
218        };
219        let (min, max): (i128, u128) = match ty.kind() {
220            ty::Int(ity) => {
221                let size = Integer::from_int_ty(&self.tcx, *ity).size();
222                (size.signed_int_min(), size.signed_int_max() as u128)
223            }
224            ty::Uint(uty) => {
225                let size = Integer::from_uint_ty(&self.tcx, *uty).size();
226                (0, size.unsigned_int_max())
227            }
228            _ => {
229                return Ok(());
230            }
231        };
232        // Detect literal value out of range `[min, max]` inclusive, avoiding use of `-min` to
233        // prevent overflow/panic.
234        if (negated && lit_val > max + 1) || (!negated && lit_val > max) {
235            return Err(self.tcx.dcx().emit_err(LiteralOutOfRange { span, ty, min, max }));
236        }
237        Ok(())
238    }
239
240    fn lower_pattern_range(
241        &mut self,
242        pat: &'tcx hir::Pat<'tcx>,
243        lo_expr: Option<&'tcx hir::PatExpr<'tcx>>,
244        hi_expr: Option<&'tcx hir::PatExpr<'tcx>>,
245        end: RangeEnd,
246    ) -> Result<Box<Pat<'tcx>>, ErrorGuaranteed> {
247        let ty = self.typeck_results.node_type(pat.hir_id);
248        let span = pat.span;
249
250        if lo_expr.is_none() && hi_expr.is_none() {
251            let msg = "found twice-open range pattern (`..`) outside of error recovery";
252            self.tcx.dcx().span_bug(span, msg);
253        }
254
255        // Collect extra data while lowering the endpoints, to be reapplied later.
256        let mut ascriptions = ::alloc::vec::Vec::new()vec![];
257        let mut lower_endpoint =
258            |expr| self.lower_pattern_range_endpoint(pat, expr, &mut ascriptions);
259
260        let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
261        let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
262
263        let cmp = lo.compare_with(hi, ty, self.tcx);
264        let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty }));
265        match (end, cmp) {
266            // `x..y` where `x < y`.
267            (RangeEnd::Excluded, Some(Ordering::Less)) => {}
268            // `x..=y` where `x < y`.
269            (RangeEnd::Included, Some(Ordering::Less)) => {}
270            // `x..=y` where `x == y` and `x` and `y` are finite.
271            (RangeEnd::Included, Some(Ordering::Equal)) if lo.is_finite() && hi.is_finite() => {
272                let value = ty::Value { ty, valtree: lo.as_finite().unwrap() };
273                kind = PatKind::Constant { value };
274            }
275            // `..=x` where `x == ty::MIN`.
276            (RangeEnd::Included, Some(Ordering::Equal)) if !lo.is_finite() => {}
277            // `x..` where `x == ty::MAX` (yes, `x..` gives `RangeEnd::Included` since it is meant
278            // to include `ty::MAX`).
279            (RangeEnd::Included, Some(Ordering::Equal)) if !hi.is_finite() => {}
280            // `x..y` where `x >= y`, or `x..=y` where `x > y`. The range is empty => error.
281            _ => {
282                // Emit a more appropriate message if there was overflow.
283                self.error_on_literal_overflow(lo_expr, ty)?;
284                self.error_on_literal_overflow(hi_expr, ty)?;
285                let e = match end {
286                    RangeEnd::Included => {
287                        self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
288                            span,
289                            teach: self.tcx.sess.teach(E0030),
290                        })
291                    }
292                    RangeEnd::Excluded if lo_expr.is_none() => {
293                        self.tcx.dcx().emit_err(UpperRangeBoundCannotBeMin { span })
294                    }
295                    RangeEnd::Excluded => {
296                        self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanUpper { span })
297                    }
298                };
299                return Err(e);
300            }
301        }
302        let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
303
304        // If we are handling a range with associated constants (e.g.
305        // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
306        // constants somewhere. Have them on the range pattern.
307        thir_pat.extra.get_or_insert_default().ascriptions.extend(ascriptions);
308        // IDs of expanded constants from range endpoints used to
309        // also be preserved here, but that was only needed for unsafeck of
310        // inline `const { .. }` patterns, which were removed by
311        // <https://github.com/rust-lang/rust/pull/138492>.
312
313        Ok(thir_pat)
314    }
315
316    {}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("lower_pattern_unadjusted",
                                    "rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(316u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("pat")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("pat");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pat)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Box<Pat<'tcx>> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let ty = self.typeck_results.node_type(pat.hir_id);
            let span = pat.span;
            let kind =
                match pat.kind {
                    hir::PatKind::Missing => PatKind::Missing,
                    hir::PatKind::Wild => PatKind::Wild,
                    hir::PatKind::Never => PatKind::Never,
                    hir::PatKind::Expr(value) =>
                        return self.lower_pat_expr(pat, value),
                    hir::PatKind::Range(lo_expr, hi_expr, end) => {
                        match self.lower_pattern_range(pat, lo_expr, hi_expr, end) {
                            Ok(thir_pat) => return thir_pat,
                            Err(e) => PatKind::Error(e),
                        }
                    }
                    hir::PatKind::Deref(subpattern) => {
                        let borrow =
                            self.typeck_results.deref_pat_borrow_mode(ty, subpattern);
                        PatKind::DerefPattern {
                            subpattern: self.lower_pattern(subpattern),
                            borrow,
                        }
                    }
                    hir::PatKind::Ref(subpattern, pin, _) => {
                        let opt_old_mode_span =
                            self.rust_2024_migration.as_mut().and_then(|s|
                                    s.visit_explicit_deref());
                        let subpattern = self.lower_pattern(subpattern);
                        if let Some(s) = &mut self.rust_2024_migration {
                            s.leave_ref(opt_old_mode_span);
                        }
                        PatKind::Deref { pin, subpattern }
                    }
                    hir::PatKind::Slice(prefix, slice, suffix) => {
                        return self.slice_or_array_pattern(pat, prefix, slice,
                                suffix);
                    }
                    hir::PatKind::Tuple(pats, ddpos) => {
                        let ty::Tuple(tys) =
                            ty.kind() else {
                                bug_impl(Some(pat.span),
                                    format_args!("unexpected type for tuple pattern: {0:?}",
                                        ty), Location::caller());
                            };
                        let subpatterns =
                            self.lower_tuple_subpats(pats, tys.len(), ddpos);
                        PatKind::Leaf { subpatterns }
                    }
                    hir::PatKind::Binding(explicit_ba, id, ident, sub) => {
                        let mut thir_pat_span = span;
                        if let Some(ident_span) =
                                ident.span.find_ancestor_inside(span) {
                            thir_pat_span = span.with_hi(ident_span.hi());
                        }
                        let mode =
                            *self.typeck_results.pat_binding_modes().get(pat.hir_id).expect("missing binding mode");
                        if let Some(s) = &mut self.rust_2024_migration {
                            s.visit_binding(pat.span, mode, explicit_ba, ident);
                        }
                        let var_ty = ty;
                        let mut thir_pat_ty = ty;
                        if let hir::ByRef::Yes(pinnedness, _) = mode.0 {
                            match pinnedness {
                                hir::Pinnedness::Pinned if
                                    let Some(pty) = ty.pinned_ty() &&
                                        let &ty::Ref(_, rty, _) = pty.kind() => {
                                    thir_pat_ty = rty;
                                }
                                hir::Pinnedness::Not if let &ty::Ref(_, rty, _) = ty.kind()
                                    => {
                                    thir_pat_ty = rty;
                                }
                                _ =>
                                    bug_impl(None,
                                        format_args!("`ref {0}` has wrong type {1}", ident, ty),
                                        Location::caller()),
                            }
                        };
                        let kind =
                            PatKind::Binding {
                                mode,
                                name: ident.name,
                                var: LocalVarId(id),
                                ty: var_ty,
                                subpattern: self.lower_opt_pattern(sub),
                                is_primary: id == pat.hir_id,
                                is_shorthand: false,
                            };
                        return Box::new(Pat {
                                    ty: thir_pat_ty,
                                    span: thir_pat_span,
                                    kind,
                                    extra: None,
                                });
                    }
                    hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
                        let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
                        let ty::Adt(adt_def, _) =
                            ty.kind() else {
                                bug_impl(Some(pat.span),
                                    format_args!("tuple struct pattern not applied to an ADT {0:?}",
                                        ty), Location::caller());
                            };
                        let variant_def = adt_def.variant_of_res(res);
                        let subpatterns =
                            self.lower_tuple_subpats(pats, variant_def.fields.len(),
                                ddpos);
                        return self.lower_variant_or_leaf(pat, None, res,
                                subpatterns);
                    }
                    hir::PatKind::Struct(ref qpath, fields, _) => {
                        let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
                        let subpatterns =
                            fields.iter().map(|field|
                                        {
                                            let mut pattern = *self.lower_pattern(field.pat);
                                            if let PatKind::Binding { ref mut is_shorthand, .. } =
                                                    pattern.kind {
                                                *is_shorthand = field.is_shorthand;
                                            }
                                            let field = self.typeck_results.field_index(field.hir_id);
                                            FieldPat { field, pattern }
                                        }).collect();
                        return self.lower_variant_or_leaf(pat, None, res,
                                subpatterns);
                    }
                    hir::PatKind::Or(pats) =>
                        PatKind::Or { pats: self.lower_patterns(pats) },
                    hir::PatKind::Guard(pat, condition) =>
                        PatKind::Guard {
                            subpattern: self.lower_pattern(pat),
                            condition: self.upper.mirror_expr(condition),
                        },
                    hir::PatKind::Err(guar) => PatKind::Error(guar),
                };
            Box::new(Pat { span, ty, kind, extra: None })
        }
    }
}#[instrument(skip(self), level = "debug")]
317    fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
318        let ty = self.typeck_results.node_type(pat.hir_id);
319        let span = pat.span;
320
321        // Some of these match arms return a `Box<Pat>` early, while others
322        // evaluate to a `PatKind` that will become a `Box<Pat>` at the end of
323        // this function.
324        let kind = match pat.kind {
325            hir::PatKind::Missing => PatKind::Missing,
326
327            hir::PatKind::Wild => PatKind::Wild,
328
329            hir::PatKind::Never => PatKind::Never,
330
331            hir::PatKind::Expr(value) => return self.lower_pat_expr(pat, value),
332
333            hir::PatKind::Range(lo_expr, hi_expr, end) => {
334                match self.lower_pattern_range(pat, lo_expr, hi_expr, end) {
335                    Ok(thir_pat) => return thir_pat,
336                    Err(e) => PatKind::Error(e),
337                }
338            }
339
340            hir::PatKind::Deref(subpattern) => {
341                let borrow = self.typeck_results.deref_pat_borrow_mode(ty, subpattern);
342                PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), borrow }
343            }
344            hir::PatKind::Ref(subpattern, pin, _) => {
345                // Track the default binding mode for the Rust 2024 migration suggestion.
346                let opt_old_mode_span =
347                    self.rust_2024_migration.as_mut().and_then(|s| s.visit_explicit_deref());
348                let subpattern = self.lower_pattern(subpattern);
349                if let Some(s) = &mut self.rust_2024_migration {
350                    s.leave_ref(opt_old_mode_span);
351                }
352                PatKind::Deref { pin, subpattern }
353            }
354            hir::PatKind::Slice(prefix, slice, suffix) => {
355                return self.slice_or_array_pattern(pat, prefix, slice, suffix);
356            }
357
358            hir::PatKind::Tuple(pats, ddpos) => {
359                let ty::Tuple(tys) = ty.kind() else {
360                    span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty);
361                };
362                let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos);
363                PatKind::Leaf { subpatterns }
364            }
365
366            hir::PatKind::Binding(explicit_ba, id, ident, sub) => {
367                let mut thir_pat_span = span;
368                if let Some(ident_span) = ident.span.find_ancestor_inside(span) {
369                    thir_pat_span = span.with_hi(ident_span.hi());
370                }
371
372                let mode = *self
373                    .typeck_results
374                    .pat_binding_modes()
375                    .get(pat.hir_id)
376                    .expect("missing binding mode");
377
378                if let Some(s) = &mut self.rust_2024_migration {
379                    s.visit_binding(pat.span, mode, explicit_ba, ident);
380                }
381
382                // A ref x pattern is the same node used for x, and as such it has
383                // x's type, which is &T, where we want T (the type being matched).
384                let var_ty = ty;
385                let mut thir_pat_ty = ty;
386                if let hir::ByRef::Yes(pinnedness, _) = mode.0 {
387                    match pinnedness {
388                        hir::Pinnedness::Pinned
389                            if let Some(pty) = ty.pinned_ty()
390                                && let &ty::Ref(_, rty, _) = pty.kind() =>
391                        {
392                            thir_pat_ty = rty;
393                        }
394                        hir::Pinnedness::Not if let &ty::Ref(_, rty, _) = ty.kind() => {
395                            thir_pat_ty = rty;
396                        }
397                        _ => bug!("`ref {}` has wrong type {}", ident, ty),
398                    }
399                };
400
401                let kind = PatKind::Binding {
402                    mode,
403                    name: ident.name,
404                    var: LocalVarId(id),
405                    ty: var_ty,
406                    subpattern: self.lower_opt_pattern(sub),
407                    is_primary: id == pat.hir_id,
408                    is_shorthand: false,
409                };
410                // We might have modified the type or span, so use the modified
411                // values in the THIR pattern node.
412                return Box::new(Pat { ty: thir_pat_ty, span: thir_pat_span, kind, extra: None });
413            }
414
415            hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
416                let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
417                let ty::Adt(adt_def, _) = ty.kind() else {
418                    span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty);
419                };
420                let variant_def = adt_def.variant_of_res(res);
421                let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
422                return self.lower_variant_or_leaf(pat, None, res, subpatterns);
423            }
424
425            hir::PatKind::Struct(ref qpath, fields, _) => {
426                let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
427                let subpatterns = fields
428                    .iter()
429                    .map(|field| {
430                        let mut pattern = *self.lower_pattern(field.pat);
431                        if let PatKind::Binding { ref mut is_shorthand, .. } = pattern.kind {
432                            *is_shorthand = field.is_shorthand;
433                        }
434                        let field = self.typeck_results.field_index(field.hir_id);
435                        FieldPat { field, pattern }
436                    })
437                    .collect();
438
439                return self.lower_variant_or_leaf(pat, None, res, subpatterns);
440            }
441
442            hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
443
444            hir::PatKind::Guard(pat, condition) => PatKind::Guard {
445                subpattern: self.lower_pattern(pat),
446                condition: self.upper.mirror_expr(condition),
447            },
448
449            hir::PatKind::Err(guar) => PatKind::Error(guar),
450        };
451
452        // For pattern kinds that haven't already returned, create a `thir::Pat`
453        // with the HIR pattern node's type and span.
454        Box::new(Pat { span, ty, kind, extra: None })
455    }
456
457    fn lower_tuple_subpats(
458        &mut self,
459        pats: &'tcx [hir::Pat<'tcx>],
460        expected_len: usize,
461        gap_pos: hir::DotDotPos,
462    ) -> Vec<FieldPat<'tcx>> {
463        pats.iter()
464            .enumerate_and_adjust(expected_len, gap_pos)
465            .map(|(i, subpattern)| FieldPat {
466                field: FieldIdx::new(i),
467                pattern: *self.lower_pattern(subpattern),
468            })
469            .collect()
470    }
471
472    fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Pat<'tcx>]> {
473        pats.iter().map(|p| *self.lower_pattern(p)).collect()
474    }
475
476    fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {
477        pat.map(|p| self.lower_pattern(p))
478    }
479
480    fn slice_or_array_pattern(
481        &mut self,
482        pat: &'tcx hir::Pat<'tcx>,
483        prefix: &'tcx [hir::Pat<'tcx>],
484        slice: Option<&'tcx hir::Pat<'tcx>>,
485        suffix: &'tcx [hir::Pat<'tcx>],
486    ) -> Box<Pat<'tcx>> {
487        let ty = self.typeck_results.node_type(pat.hir_id);
488        let span = pat.span;
489
490        let prefix = self.lower_patterns(prefix);
491        let slice = self.lower_opt_pattern(slice);
492        let suffix = self.lower_patterns(suffix);
493        let kind = match ty.kind() {
494            // Matching a slice, `[T]`.
495            ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
496            // Fixed-length array, `[T; len]`.
497            ty::Array(_, len) => {
498                let len = len
499                    .try_to_target_usize(self.tcx)
500                    .expect("expected len of array pat to be definite");
501                if !(len >= prefix.len() as u64 + suffix.len() as u64) {
    ::core::panicking::panic("assertion failed: len >= prefix.len() as u64 + suffix.len() as u64")
};assert!(len >= prefix.len() as u64 + suffix.len() as u64);
502                PatKind::Array { prefix, slice, suffix }
503            }
504            _ => bug_impl(Some(span), format_args!("bad slice pattern type {0:?}", ty),
    Location::caller())span_bug!(span, "bad slice pattern type {ty:?}"),
505        };
506        Box::new(Pat { ty, span, kind, extra: None })
507    }
508
509    fn lower_variant_or_leaf(
510        &mut self,
511        pat: &'tcx hir::Pat<'tcx>,
512        expr: Option<&'tcx hir::PatExpr<'tcx>>,
513        res: Res,
514        subpatterns: Vec<FieldPat<'tcx>>,
515    ) -> Box<Pat<'tcx>> {
516        // Check whether the caller should have provided an `expr` for this pattern kind.
517        {
    match (pat.kind, expr) {
        (hir::PatKind::Expr(..) | hir::PatKind::Range(..), Some(_)) |
            (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..), None)
            => {}
        ref left_val => {
            ::core::panicking::assert_matches_failed(left_val,
                "(hir::PatKind::Expr(..) | hir::PatKind::Range(..), Some(_)) |\n(hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..), None)",
                ::core::option::Option::None);
        }
    }
};assert_matches!(
518            (pat.kind, expr),
519            (hir::PatKind::Expr(..) | hir::PatKind::Range(..), Some(_))
520                | (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..), None)
521        );
522
523        // Use the id/span of the `hir::PatExpr`, if provided.
524        // Otherwise, use the id/span of the `hir::Pat`.
525        let (hir_id, span) = match expr {
526            Some(expr) => (expr.hir_id, expr.span),
527            None => (pat.hir_id, pat.span),
528        };
529        let ty = self.typeck_results.node_type(hir_id);
530
531        let res = match res {
532            Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
533                let variant_id = self.tcx.parent(variant_ctor_id);
534                Res::Def(DefKind::Variant, variant_id)
535            }
536            res => res,
537        };
538
539        let kind = match res {
540            Res::Def(DefKind::Variant, variant_id) => {
541                let enum_id = self.tcx.parent(variant_id);
542                let adt_def = self.tcx.adt_def(enum_id);
543                if adt_def.is_enum() {
544                    let args = match ty.kind() {
545                        ty::FnDef(_, args) => args.no_bound_vars().unwrap(),
546                        ty::Adt(_, args) => args,
547                        ty::Error(e) => {
548                            // Avoid ICE (#50585)
549                            return Box::new(Pat {
550                                ty,
551                                span,
552                                kind: PatKind::Error(*e),
553                                extra: None,
554                            });
555                        }
556                        _ => bug_impl(None, format_args!("inappropriate type for def: {0:?}", ty),
    Location::caller())bug!("inappropriate type for def: {:?}", ty),
557                    };
558                    PatKind::Variant {
559                        adt_def,
560                        args,
561                        variant_index: adt_def.variant_index_with_id(variant_id),
562                        subpatterns,
563                    }
564                } else {
565                    PatKind::Leaf { subpatterns }
566                }
567            }
568
569            Res::Def(
570                DefKind::Struct
571                | DefKind::Ctor(CtorOf::Struct, ..)
572                | DefKind::Union
573                | DefKind::TyAlias
574                | DefKind::AssocTy,
575                _,
576            )
577            | Res::SelfTyParam { .. }
578            | Res::SelfTyAlias { .. }
579            | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
580            _ => {
581                let e = match res {
582                    Res::Def(DefKind::ConstParam, def_id) => {
583                        let const_span = self.tcx.def_span(def_id);
584                        self.tcx.dcx().emit_err(ConstParamInPattern { span, const_span })
585                    }
586                    Res::Def(DefKind::Static { .. }, def_id) => {
587                        let static_span = self.tcx.def_span(def_id);
588                        self.tcx.dcx().emit_err(StaticInPattern { span, static_span })
589                    }
590                    _ => self.tcx.dcx().emit_err(NonConstPath { span }),
591                };
592                PatKind::Error(e)
593            }
594        };
595        let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
596
597        if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) {
598            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs:598",
                        "rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(598u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
                        ::tracing_core::field::FieldSet::new(&["message",
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("thir_pat")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("thir_pat");
                                            NAME.as_str()
                                        },
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("user_ty")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("user_ty");
                                            NAME.as_str()
                                        },
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("span")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("span");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("lower_variant_or_leaf: applying ascription")
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&thir_pat)
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&user_ty)
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?thir_pat, ?user_ty, ?span, "lower_variant_or_leaf: applying ascription");
599            let annotation = CanonicalUserTypeAnnotation {
600                user_ty: Box::new(user_ty),
601                span,
602                inferred_ty: self.typeck_results.node_type(hir_id),
603            };
604            thir_pat
605                .extra
606                .get_or_insert_default()
607                .ascriptions
608                .push(Ascription { annotation, variance: ty::Covariant });
609        }
610
611        thir_pat
612    }
613
614    fn user_args_applied_to_ty_of_hir_id(
615        &self,
616        hir_id: hir::HirId,
617    ) -> Option<ty::CanonicalUserType<'tcx>> {
618        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
619    }
620
621    /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
622    /// it to `const_to_pat`. Any other path (like enum variants without fields)
623    /// is converted to the corresponding pattern via `lower_variant_or_leaf`.
624    {}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("lower_path",
                                    "rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(624u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("pat")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("pat");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expr")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expr");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("qpath")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("qpath");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pat)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expr)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&qpath)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Box<Pat<'tcx>> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            {
                match pat.kind {
                    hir::PatKind::Expr(..) | hir::PatKind::Range(..) => {}
                    ref left_val => {
                        ::core::panicking::assert_matches_failed(left_val,
                            "hir::PatKind::Expr(..) | hir::PatKind::Range(..)",
                            ::core::option::Option::None);
                    }
                }
            };
            let id = expr.hir_id;
            let span = expr.span;
            let ty = self.typeck_results.node_type(id);
            let res = self.typeck_results.qpath_res(qpath, id);
            let (def_id, user_ty) =
                match res {
                    Res::Def(DefKind::Const, def_id) |
                        Res::Def(DefKind::AssocConst, def_id) => {
                        (def_id, self.typeck_results.user_provided_types().get(id))
                    }
                    _ => {
                        return self.lower_variant_or_leaf(pat, Some(expr), res,
                                ::alloc::vec::Vec::new());
                    }
                };
            let args = self.typeck_results.node_args(id);
            let c =
                ty::Const::new_alias(self.tcx, ty::IsRigid::No,
                    ty::AliasConst::new(self.tcx,
                        ty::AliasConstKind::new_from_def_id(self.tcx, def_id,
                            ty::AliasConstInherentArgsKind::Impl), args));
            let mut pattern = self.const_to_pat(c, ty, id, span);
            if let Some(&user_ty) = user_ty {
                let annotation =
                    CanonicalUserTypeAnnotation {
                        user_ty: Box::new(user_ty),
                        span,
                        inferred_ty: self.typeck_results.node_type(id),
                    };
                pattern.extra.get_or_insert_default().ascriptions.push(Ascription {
                        annotation,
                        variance: ty::Contravariant,
                    });
            }
            pattern
        }
    }
}#[instrument(skip(self), level = "debug")]
625    fn lower_path(
626        &mut self,
627        pat: &'tcx hir::Pat<'tcx>, // Pattern that directly contains `expr`
628        expr: &'tcx hir::PatExpr<'tcx>,
629        qpath: &hir::QPath<'_>,
630    ) -> Box<Pat<'tcx>> {
631        assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
632
633        let id = expr.hir_id;
634        let span = expr.span;
635        let ty = self.typeck_results.node_type(id);
636        let res = self.typeck_results.qpath_res(qpath, id);
637
638        let (def_id, user_ty) = match res {
639            Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
640                (def_id, self.typeck_results.user_provided_types().get(id))
641            }
642
643            _ => {
644                // The path isn't the name of a constant, so it must actually
645                // be a unit struct or unit variant (e.g. `Option::None`).
646                return self.lower_variant_or_leaf(pat, Some(expr), res, vec![]);
647            }
648        };
649
650        // Lower the named constant to a THIR pattern.
651        let args = self.typeck_results.node_args(id);
652        // FIXME(mgca): we will need to special case IACs here to have type system compatible
653        // generic args, instead of how we represent them in body expressions.
654        let c = ty::Const::new_alias(
655            self.tcx,
656            ty::IsRigid::No,
657            ty::AliasConst::new(
658                self.tcx,
659                ty::AliasConstKind::new_from_def_id(
660                    self.tcx,
661                    def_id,
662                    ty::AliasConstInherentArgsKind::Impl,
663                ),
664                args,
665            ),
666        );
667        let mut pattern = self.const_to_pat(c, ty, id, span);
668
669        // If this is an associated constant with an explicit user-written
670        // type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`).
671        if let Some(&user_ty) = user_ty {
672            let annotation = CanonicalUserTypeAnnotation {
673                user_ty: Box::new(user_ty),
674                span,
675                inferred_ty: self.typeck_results.node_type(id),
676            };
677            // Note that we use `Contravariant` here. See the
678            // `variance` field documentation for details.
679            pattern
680                .extra
681                .get_or_insert_default()
682                .ascriptions
683                .push(Ascription { annotation, variance: ty::Contravariant });
684        }
685
686        pattern
687    }
688
689    /// Lowers the kinds of "expression" that can appear in a HIR pattern:
690    /// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`)
691    /// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
692    fn lower_pat_expr(
693        &mut self,
694        pat: &'tcx hir::Pat<'tcx>, // Pattern that directly contains `expr`
695        expr: &'tcx hir::PatExpr<'tcx>,
696    ) -> Box<Pat<'tcx>> {
697        {
    match pat.kind {
        hir::PatKind::Expr(..) | hir::PatKind::Range(..) => {}
        ref left_val => {
            ::core::panicking::assert_matches_failed(left_val,
                "hir::PatKind::Expr(..) | hir::PatKind::Range(..)",
                ::core::option::Option::None);
        }
    }
};assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
698        match &expr.kind {
699            hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath),
700            hir::PatExprKind::Lit { lit, negated } => {
701                // We handle byte string literal patterns by using the pattern's type instead of the
702                // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
703                // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
704                // pattern's type means we'll properly translate it to a slice reference pattern. This works
705                // because slices and arrays have the same valtree representation.
706                //
707                // Under `feature(deref_patterns)`, this adjustment can also convert string literal
708                // patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
709
710                let pat_ty = self.typeck_results.node_type(pat.hir_id);
711                let lit_input = LitToConstInput { lit: lit.node, ty: Some(pat_ty), neg: *negated };
712                let constant = const_lit_matches_ty(self.tcx, &lit.node, pat_ty, *negated)
713                    .then(|| self.tcx.at(expr.span).lit_to_const(lit_input))
714                    .flatten()
715                    .map(|v| ty::Const::new_value(self.tcx, v.valtree, pat_ty))
716                    .unwrap_or_else(|| {
717                        ty::Const::new_error_with_message(
718                            self.tcx,
719                            expr.span,
720                            "literal does not match expected type",
721                        )
722                    });
723                self.const_to_pat(constant, pat_ty, expr.hir_id, lit.span)
724            }
725        }
726    }
727}