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, DerefPatBorrowMode, 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_middle::{bug, span_bug};
27use rustc_span::ErrorGuaranteed;
28use tracing::{debug, instrument};
29
30pub(crate) use self::check_match::check_match;
31use self::migration::PatMigration;
32use crate::errors::*;
33use crate::thir::cx::ThirBuildCx;
34
35/// Context for lowering HIR patterns to THIR patterns.
36struct PatCtxt<'tcx, 'ptcx> {
37    upper: &'ptcx mut ThirBuildCx<'tcx>,
38    tcx: TyCtxt<'tcx>,
39    typing_env: ty::TypingEnv<'tcx>,
40    typeck_results: &'tcx ty::TypeckResults<'tcx>,
41
42    /// Used by the Rust 2024 migration lint.
43    rust_2024_migration: Option<PatMigration<'tcx>>,
44}
45
46x;#[instrument(level = "debug", skip(upper, tcx, typing_env, typeck_results), ret)]
47pub(super) fn pat_from_hir<'tcx, 'ptcx>(
48    upper: &'ptcx mut ThirBuildCx<'tcx>,
49    tcx: TyCtxt<'tcx>,
50    typing_env: ty::TypingEnv<'tcx>,
51    typeck_results: &'tcx ty::TypeckResults<'tcx>,
52    pat: &'tcx hir::Pat<'tcx>,
53    // Present if `pat` came from a let statement with an explicit type annotation
54    let_stmt_type: Option<&hir::Ty<'tcx>>,
55) -> Box<Pat<'tcx>> {
56    let mut pcx = PatCtxt {
57        upper,
58        tcx,
59        typing_env,
60        typeck_results,
61        rust_2024_migration: typeck_results
62            .rust_2024_migration_desugared_pats()
63            .get(pat.hir_id)
64            .map(PatMigration::new),
65    };
66
67    let mut thir_pat = pcx.lower_pattern(pat);
68
69    // If this pattern came from a let statement with an explicit type annotation
70    // (e.g. `let x: Foo = ...`), retain that user type information in the THIR pattern.
71    if let Some(let_stmt_type) = let_stmt_type
72        && let Some(&user_ty) = typeck_results.user_provided_types().get(let_stmt_type.hir_id)
73    {
74        debug!(?user_ty);
75        let annotation = CanonicalUserTypeAnnotation {
76            user_ty: Box::new(user_ty),
77            span: let_stmt_type.span,
78            inferred_ty: typeck_results.node_type(let_stmt_type.hir_id),
79        };
80        thir_pat
81            .extra
82            .get_or_insert_default()
83            .ascriptions
84            .push(Ascription { annotation, variance: ty::Covariant });
85    }
86
87    if let Some(m) = pcx.rust_2024_migration {
88        m.emit(tcx, pat.hir_id);
89    }
90
91    thir_pat
92}
93
94impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> {
95    fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
96        let adjustments: &[PatAdjustment<'tcx>] =
97            self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
98
99        // Track the default binding mode for the Rust 2024 migration suggestion.
100        // Implicitly dereferencing references changes the default binding mode, but implicit deref
101        // patterns do not. Only track binding mode changes if a ref type is in the adjustments.
102        let mut opt_old_mode_span = None;
103        if let Some(s) = &mut self.rust_2024_migration
104            && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
105        {
106            opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments);
107        }
108
109        // When implicit dereferences have been inserted in this pattern, the unadjusted lowered
110        // pattern has the type that results *after* dereferencing. For example, in this code:
111        //
112        // ```
113        // match &&Some(0i32) {
114        //     Some(n) => { ... },
115        //     _ => { ... },
116        // }
117        // ```
118        //
119        // the type assigned to `Some(n)` in `unadjusted_pat` would be `Option<i32>` (this is
120        // determined in rustc_hir_analysis::check::match). The adjustments would be
121        //
122        // `vec![&&Option<i32>, &Option<i32>]`.
123        //
124        // Applying the adjustments, we want to instead output `&&Some(n)` (as a THIR pattern). So
125        // we wrap the unadjusted pattern in `PatKind::Deref` repeatedly, consuming the
126        // adjustments in *reverse order* (last-in-first-out, so that the last `Deref` inserted
127        // gets the least-dereferenced type).
128        let unadjusted_pat = match pat.kind {
129            hir::PatKind::Ref(inner, _, _)
130                if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) =>
131            {
132                self.lower_pattern(inner)
133            }
134            _ => self.lower_pattern_unadjusted(pat),
135        };
136
137        let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| {
138            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/pattern/mod.rs:138",
                        "rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(138u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("{0:?}: wrapping pattern with adjustment {1:?}",
                                                    thir_pat, adjust) as &dyn Value))])
            });
    } else { ; }
};debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust);
139            let span = thir_pat.span;
140            let kind = match adjust.kind {
141                PatAdjust::BuiltinDeref => {
142                    PatKind::Deref { pin: hir::Pinnedness::Not, subpattern: thir_pat }
143                }
144                PatAdjust::OverloadedDeref => {
145                    let borrow = self.typeck_results.deref_pat_borrow_mode(adjust.source, pat);
146                    PatKind::DerefPattern { subpattern: thir_pat, borrow }
147                }
148                PatAdjust::PinDeref => {
149                    PatKind::Deref { pin: hir::Pinnedness::Pinned, subpattern: thir_pat }
150                }
151            };
152            Box::new(Pat { span, ty: adjust.source, kind, extra: None })
153        });
154
155        if let Some(s) = &mut self.rust_2024_migration
156            && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
157        {
158            s.leave_ref(opt_old_mode_span);
159        }
160
161        adjusted_pat
162    }
163
164    fn lower_pattern_range_endpoint(
165        &mut self,
166        pat: &'tcx hir::Pat<'tcx>, // Range pattern containing the endpoint
167        expr: Option<&'tcx hir::PatExpr<'tcx>>,
168        // Out-parameter collecting extra data to be reapplied by the caller
169        ascriptions: &mut Vec<Ascription<'tcx>>,
170    ) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
171        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(..));
172
173        // For partly-bounded ranges like `X..` or `..X`, an endpoint will be absent.
174        // Return None in that case; the caller will use NegInfinity or PosInfinity instead.
175        let Some(expr) = expr else { return Ok(None) };
176
177        // Lower the endpoint into a temporary `thir::Pat` that will then be
178        // deconstructed to obtain the constant value and other data.
179        let endpoint_pat: Box<Pat<'tcx>> = self.lower_pat_expr(pat, expr);
180        let box Pat { ref kind, extra, .. } = endpoint_pat;
181
182        // Preserve any ascriptions from endpoint constants.
183        if let Some(extra) = extra {
184            ascriptions.extend(extra.ascriptions);
185        }
186
187        // The unpeeled kind should now be a constant, giving us the endpoint value.
188        let PatKind::Constant { value } = kind else {
189            let msg =
190                ::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");
191            return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
192        };
193        Ok(Some(PatRangeBoundary::Finite(value.valtree)))
194    }
195
196    /// Overflowing literals are linted against in a late pass. This is mostly fine, except when we
197    /// encounter a range pattern like `-130i8..2`: if we believe `eval_bits`, this looks like a
198    /// range where the endpoints are in the wrong order. To avoid a confusing error message, we
199    /// check for overflow then.
200    /// This is only called when the range is already known to be malformed.
201    fn error_on_literal_overflow(
202        &self,
203        expr: Option<&'tcx hir::PatExpr<'tcx>>,
204        ty: Ty<'tcx>,
205    ) -> Result<(), ErrorGuaranteed> {
206        let Some(expr) = expr else {
207            return Ok(());
208        };
209        let span = expr.span;
210
211        // We need to inspect the original expression, because if we only inspect the output of
212        // `eval_bits`, an overflowed value has already been wrapped around.
213        // We mostly copy the logic from the `rustc_lint::OVERFLOWING_LITERALS` lint.
214        let hir::PatExprKind::Lit { lit, negated } = expr.kind else {
215            return Ok(());
216        };
217        let LitKind::Int(lit_val, _) = lit.node else {
218            return Ok(());
219        };
220        let (min, max): (i128, u128) = match ty.kind() {
221            ty::Int(ity) => {
222                let size = Integer::from_int_ty(&self.tcx, *ity).size();
223                (size.signed_int_min(), size.signed_int_max() as u128)
224            }
225            ty::Uint(uty) => {
226                let size = Integer::from_uint_ty(&self.tcx, *uty).size();
227                (0, size.unsigned_int_max())
228            }
229            _ => {
230                return Ok(());
231            }
232        };
233        // Detect literal value out of range `[min, max]` inclusive, avoiding use of `-min` to
234        // prevent overflow/panic.
235        if (negated && lit_val > max + 1) || (!negated && lit_val > max) {
236            return Err(self.tcx.dcx().emit_err(LiteralOutOfRange { span, ty, min, max }));
237        }
238        Ok(())
239    }
240
241    fn lower_pattern_range(
242        &mut self,
243        pat: &'tcx hir::Pat<'tcx>,
244        lo_expr: Option<&'tcx hir::PatExpr<'tcx>>,
245        hi_expr: Option<&'tcx hir::PatExpr<'tcx>>,
246        end: RangeEnd,
247    ) -> Result<Box<Pat<'tcx>>, ErrorGuaranteed> {
248        let ty = self.typeck_results.node_type(pat.hir_id);
249        let span = pat.span;
250
251        if lo_expr.is_none() && hi_expr.is_none() {
252            let msg = "found twice-open range pattern (`..`) outside of error recovery";
253            self.tcx.dcx().span_bug(span, msg);
254        }
255
256        // Collect extra data while lowering the endpoints, to be reapplied later.
257        let mut ascriptions = ::alloc::vec::Vec::new()vec![];
258        let mut lower_endpoint =
259            |expr| self.lower_pattern_range_endpoint(pat, expr, &mut ascriptions);
260
261        let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
262        let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
263
264        let cmp = lo.compare_with(hi, ty, self.tcx);
265        let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty }));
266        match (end, cmp) {
267            // `x..y` where `x < y`.
268            (RangeEnd::Excluded, Some(Ordering::Less)) => {}
269            // `x..=y` where `x < y`.
270            (RangeEnd::Included, Some(Ordering::Less)) => {}
271            // `x..=y` where `x == y` and `x` and `y` are finite.
272            (RangeEnd::Included, Some(Ordering::Equal)) if lo.is_finite() && hi.is_finite() => {
273                let value = ty::Value { ty, valtree: lo.as_finite().unwrap() };
274                kind = PatKind::Constant { value };
275            }
276            // `..=x` where `x == ty::MIN`.
277            (RangeEnd::Included, Some(Ordering::Equal)) if !lo.is_finite() => {}
278            // `x..` where `x == ty::MAX` (yes, `x..` gives `RangeEnd::Included` since it is meant
279            // to include `ty::MAX`).
280            (RangeEnd::Included, Some(Ordering::Equal)) if !hi.is_finite() => {}
281            // `x..y` where `x >= y`, or `x..=y` where `x > y`. The range is empty => error.
282            _ => {
283                // Emit a more appropriate message if there was overflow.
284                self.error_on_literal_overflow(lo_expr, ty)?;
285                self.error_on_literal_overflow(hi_expr, ty)?;
286                let e = match end {
287                    RangeEnd::Included => {
288                        self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
289                            span,
290                            teach: self.tcx.sess.teach(E0030),
291                        })
292                    }
293                    RangeEnd::Excluded if lo_expr.is_none() => {
294                        self.tcx.dcx().emit_err(UpperRangeBoundCannotBeMin { span })
295                    }
296                    RangeEnd::Excluded => {
297                        self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanUpper { span })
298                    }
299                };
300                return Err(e);
301            }
302        }
303        let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
304
305        // If we are handling a range with associated constants (e.g.
306        // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
307        // constants somewhere. Have them on the range pattern.
308        thir_pat.extra.get_or_insert_default().ascriptions.extend(ascriptions);
309        // IDs of expanded constants from range endpoints used to
310        // also be preserved here, but that was only needed for unsafeck of
311        // inline `const { .. }` patterns, which were removed by
312        // <https://github.com/rust-lang/rust/pull/138492>.
313
314        Ok(thir_pat)
315    }
316
317    #[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("compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(317u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
                                    ::tracing_core::field::FieldSet::new(&["pat"],
                                        ::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};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pat)
                                                            as &dyn 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::Box(subpattern) =>
                        PatKind::DerefPattern {
                            subpattern: self.lower_pattern(subpattern),
                            borrow: DerefPatBorrowMode::Box,
                        },
                    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 {
                                ::rustc_middle::util::bug::span_bug_fmt(pat.span,
                                    format_args!("unexpected type for tuple pattern: {0:?}",
                                        ty));
                            };
                        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;
                                }
                                _ =>
                                    ::rustc_middle::util::bug::bug_fmt(format_args!("`ref {0}` has wrong type {1}",
                                            ident, ty)),
                            }
                        };
                        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 {
                                ::rustc_middle::util::bug::span_bug_fmt(pat.span,
                                    format_args!("tuple struct pattern not applied to an ADT {0:?}",
                                        ty));
                            };
                        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")]
318    fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
319        let ty = self.typeck_results.node_type(pat.hir_id);
320        let span = pat.span;
321
322        // Some of these match arms return a `Box<Pat>` early, while others
323        // evaluate to a `PatKind` that will become a `Box<Pat>` at the end of
324        // this function.
325        let kind = match pat.kind {
326            hir::PatKind::Missing => PatKind::Missing,
327
328            hir::PatKind::Wild => PatKind::Wild,
329
330            hir::PatKind::Never => PatKind::Never,
331
332            hir::PatKind::Expr(value) => return self.lower_pat_expr(pat, value),
333
334            hir::PatKind::Range(lo_expr, hi_expr, end) => {
335                match self.lower_pattern_range(pat, lo_expr, hi_expr, end) {
336                    Ok(thir_pat) => return thir_pat,
337                    Err(e) => PatKind::Error(e),
338                }
339            }
340
341            hir::PatKind::Deref(subpattern) => {
342                let borrow = self.typeck_results.deref_pat_borrow_mode(ty, subpattern);
343                PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), borrow }
344            }
345            hir::PatKind::Ref(subpattern, pin, _) => {
346                // Track the default binding mode for the Rust 2024 migration suggestion.
347                let opt_old_mode_span =
348                    self.rust_2024_migration.as_mut().and_then(|s| s.visit_explicit_deref());
349                let subpattern = self.lower_pattern(subpattern);
350                if let Some(s) = &mut self.rust_2024_migration {
351                    s.leave_ref(opt_old_mode_span);
352                }
353                PatKind::Deref { pin, subpattern }
354            }
355            hir::PatKind::Box(subpattern) => PatKind::DerefPattern {
356                subpattern: self.lower_pattern(subpattern),
357                borrow: DerefPatBorrowMode::Box,
358            },
359
360            hir::PatKind::Slice(prefix, slice, suffix) => {
361                return self.slice_or_array_pattern(pat, prefix, slice, suffix);
362            }
363
364            hir::PatKind::Tuple(pats, ddpos) => {
365                let ty::Tuple(tys) = ty.kind() else {
366                    span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty);
367                };
368                let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos);
369                PatKind::Leaf { subpatterns }
370            }
371
372            hir::PatKind::Binding(explicit_ba, id, ident, sub) => {
373                let mut thir_pat_span = span;
374                if let Some(ident_span) = ident.span.find_ancestor_inside(span) {
375                    thir_pat_span = span.with_hi(ident_span.hi());
376                }
377
378                let mode = *self
379                    .typeck_results
380                    .pat_binding_modes()
381                    .get(pat.hir_id)
382                    .expect("missing binding mode");
383
384                if let Some(s) = &mut self.rust_2024_migration {
385                    s.visit_binding(pat.span, mode, explicit_ba, ident);
386                }
387
388                // A ref x pattern is the same node used for x, and as such it has
389                // x's type, which is &T, where we want T (the type being matched).
390                let var_ty = ty;
391                let mut thir_pat_ty = ty;
392                if let hir::ByRef::Yes(pinnedness, _) = mode.0 {
393                    match pinnedness {
394                        hir::Pinnedness::Pinned
395                            if let Some(pty) = ty.pinned_ty()
396                                && let &ty::Ref(_, rty, _) = pty.kind() =>
397                        {
398                            thir_pat_ty = rty;
399                        }
400                        hir::Pinnedness::Not if let &ty::Ref(_, rty, _) = ty.kind() => {
401                            thir_pat_ty = rty;
402                        }
403                        _ => bug!("`ref {}` has wrong type {}", ident, ty),
404                    }
405                };
406
407                let kind = PatKind::Binding {
408                    mode,
409                    name: ident.name,
410                    var: LocalVarId(id),
411                    ty: var_ty,
412                    subpattern: self.lower_opt_pattern(sub),
413                    is_primary: id == pat.hir_id,
414                    is_shorthand: false,
415                };
416                // We might have modified the type or span, so use the modified
417                // values in the THIR pattern node.
418                return Box::new(Pat { ty: thir_pat_ty, span: thir_pat_span, kind, extra: None });
419            }
420
421            hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
422                let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
423                let ty::Adt(adt_def, _) = ty.kind() else {
424                    span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty);
425                };
426                let variant_def = adt_def.variant_of_res(res);
427                let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
428                return self.lower_variant_or_leaf(pat, None, res, subpatterns);
429            }
430
431            hir::PatKind::Struct(ref qpath, fields, _) => {
432                let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
433                let subpatterns = fields
434                    .iter()
435                    .map(|field| {
436                        let mut pattern = *self.lower_pattern(field.pat);
437                        if let PatKind::Binding { ref mut is_shorthand, .. } = pattern.kind {
438                            *is_shorthand = field.is_shorthand;
439                        }
440                        let field = self.typeck_results.field_index(field.hir_id);
441                        FieldPat { field, pattern }
442                    })
443                    .collect();
444
445                return self.lower_variant_or_leaf(pat, None, res, subpatterns);
446            }
447
448            hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
449
450            hir::PatKind::Guard(pat, condition) => PatKind::Guard {
451                subpattern: self.lower_pattern(pat),
452                condition: self.upper.mirror_expr(condition),
453            },
454
455            hir::PatKind::Err(guar) => PatKind::Error(guar),
456        };
457
458        // For pattern kinds that haven't already returned, create a `thir::Pat`
459        // with the HIR pattern node's type and span.
460        Box::new(Pat { span, ty, kind, extra: None })
461    }
462
463    fn lower_tuple_subpats(
464        &mut self,
465        pats: &'tcx [hir::Pat<'tcx>],
466        expected_len: usize,
467        gap_pos: hir::DotDotPos,
468    ) -> Vec<FieldPat<'tcx>> {
469        pats.iter()
470            .enumerate_and_adjust(expected_len, gap_pos)
471            .map(|(i, subpattern)| FieldPat {
472                field: FieldIdx::new(i),
473                pattern: *self.lower_pattern(subpattern),
474            })
475            .collect()
476    }
477
478    fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Pat<'tcx>]> {
479        pats.iter().map(|p| *self.lower_pattern(p)).collect()
480    }
481
482    fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {
483        pat.map(|p| self.lower_pattern(p))
484    }
485
486    fn slice_or_array_pattern(
487        &mut self,
488        pat: &'tcx hir::Pat<'tcx>,
489        prefix: &'tcx [hir::Pat<'tcx>],
490        slice: Option<&'tcx hir::Pat<'tcx>>,
491        suffix: &'tcx [hir::Pat<'tcx>],
492    ) -> Box<Pat<'tcx>> {
493        let ty = self.typeck_results.node_type(pat.hir_id);
494        let span = pat.span;
495
496        let prefix = self.lower_patterns(prefix);
497        let slice = self.lower_opt_pattern(slice);
498        let suffix = self.lower_patterns(suffix);
499        let kind = match ty.kind() {
500            // Matching a slice, `[T]`.
501            ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
502            // Fixed-length array, `[T; len]`.
503            ty::Array(_, len) => {
504                let len = len
505                    .try_to_target_usize(self.tcx)
506                    .expect("expected len of array pat to be definite");
507                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);
508                PatKind::Array { prefix, slice, suffix }
509            }
510            _ => ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("bad slice pattern type {0:?}", ty))span_bug!(span, "bad slice pattern type {ty:?}"),
511        };
512        Box::new(Pat { ty, span, kind, extra: None })
513    }
514
515    fn lower_variant_or_leaf(
516        &mut self,
517        pat: &'tcx hir::Pat<'tcx>,
518        expr: Option<&'tcx hir::PatExpr<'tcx>>,
519        res: Res,
520        subpatterns: Vec<FieldPat<'tcx>>,
521    ) -> Box<Pat<'tcx>> {
522        // Check whether the caller should have provided an `expr` for this pattern kind.
523        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!(
524            (pat.kind, expr),
525            (hir::PatKind::Expr(..) | hir::PatKind::Range(..), Some(_))
526                | (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..), None)
527        );
528
529        // Use the id/span of the `hir::PatExpr`, if provided.
530        // Otherwise, use the id/span of the `hir::Pat`.
531        let (hir_id, span) = match expr {
532            Some(expr) => (expr.hir_id, expr.span),
533            None => (pat.hir_id, pat.span),
534        };
535        let ty = self.typeck_results.node_type(hir_id);
536
537        let res = match res {
538            Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
539                let variant_id = self.tcx.parent(variant_ctor_id);
540                Res::Def(DefKind::Variant, variant_id)
541            }
542            res => res,
543        };
544
545        let kind = match res {
546            Res::Def(DefKind::Variant, variant_id) => {
547                let enum_id = self.tcx.parent(variant_id);
548                let adt_def = self.tcx.adt_def(enum_id);
549                if adt_def.is_enum() {
550                    let args = match ty.kind() {
551                        ty::Adt(_, args) | ty::FnDef(_, args) => args,
552                        ty::Error(e) => {
553                            // Avoid ICE (#50585)
554                            return Box::new(Pat {
555                                ty,
556                                span,
557                                kind: PatKind::Error(*e),
558                                extra: None,
559                            });
560                        }
561                        _ => ::rustc_middle::util::bug::bug_fmt(format_args!("inappropriate type for def: {0:?}",
        ty))bug!("inappropriate type for def: {:?}", ty),
562                    };
563                    PatKind::Variant {
564                        adt_def,
565                        args,
566                        variant_index: adt_def.variant_index_with_id(variant_id),
567                        subpatterns,
568                    }
569                } else {
570                    PatKind::Leaf { subpatterns }
571                }
572            }
573
574            Res::Def(
575                DefKind::Struct
576                | DefKind::Ctor(CtorOf::Struct, ..)
577                | DefKind::Union
578                | DefKind::TyAlias
579                | DefKind::AssocTy,
580                _,
581            )
582            | Res::SelfTyParam { .. }
583            | Res::SelfTyAlias { .. }
584            | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
585            _ => {
586                let e = match res {
587                    Res::Def(DefKind::ConstParam, def_id) => {
588                        let const_span = self.tcx.def_span(def_id);
589                        self.tcx.dcx().emit_err(ConstParamInPattern { span, const_span })
590                    }
591                    Res::Def(DefKind::Static { .. }, def_id) => {
592                        let static_span = self.tcx.def_span(def_id);
593                        self.tcx.dcx().emit_err(StaticInPattern { span, static_span })
594                    }
595                    _ => self.tcx.dcx().emit_err(NonConstPath { span }),
596                };
597                PatKind::Error(e)
598            }
599        };
600        let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
601
602        if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) {
603            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/pattern/mod.rs:603",
                        "rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(603u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
                        ::tracing_core::field::FieldSet::new(&["message",
                                        "thir_pat", "user_ty", "span"],
                            ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("lower_variant_or_leaf: applying ascription")
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&thir_pat)
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&user_ty) as
                                            &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&span) as
                                            &dyn Value))])
            });
    } else { ; }
};debug!(?thir_pat, ?user_ty, ?span, "lower_variant_or_leaf: applying ascription");
604            let annotation = CanonicalUserTypeAnnotation {
605                user_ty: Box::new(user_ty),
606                span,
607                inferred_ty: self.typeck_results.node_type(hir_id),
608            };
609            thir_pat
610                .extra
611                .get_or_insert_default()
612                .ascriptions
613                .push(Ascription { annotation, variance: ty::Covariant });
614        }
615
616        thir_pat
617    }
618
619    fn user_args_applied_to_ty_of_hir_id(
620        &self,
621        hir_id: hir::HirId,
622    ) -> Option<ty::CanonicalUserType<'tcx>> {
623        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
624    }
625
626    /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
627    /// it to `const_to_pat`. Any other path (like enum variants without fields)
628    /// is converted to the corresponding pattern via `lower_variant_or_leaf`.
629    #[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("compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(629u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
                                    ::tracing_core::field::FieldSet::new(&["pat", "expr",
                                                    "qpath"],
                                        ::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};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pat)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expr)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&qpath)
                                                            as &dyn 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_unevaluated(self.tcx,
                    ty::UnevaluatedConst { def: def_id, 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")]
630    fn lower_path(
631        &mut self,
632        pat: &'tcx hir::Pat<'tcx>, // Pattern that directly contains `expr`
633        expr: &'tcx hir::PatExpr<'tcx>,
634        qpath: &hir::QPath<'_>,
635    ) -> Box<Pat<'tcx>> {
636        assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
637
638        let id = expr.hir_id;
639        let span = expr.span;
640        let ty = self.typeck_results.node_type(id);
641        let res = self.typeck_results.qpath_res(qpath, id);
642
643        let (def_id, user_ty) = match res {
644            Res::Def(DefKind::Const { .. }, def_id)
645            | Res::Def(DefKind::AssocConst { .. }, def_id) => {
646                (def_id, self.typeck_results.user_provided_types().get(id))
647            }
648
649            _ => {
650                // The path isn't the name of a constant, so it must actually
651                // be a unit struct or unit variant (e.g. `Option::None`).
652                return self.lower_variant_or_leaf(pat, Some(expr), res, vec![]);
653            }
654        };
655
656        // Lower the named constant to a THIR pattern.
657        let args = self.typeck_results.node_args(id);
658        // FIXME(mgca): we will need to special case IACs here to have type system compatible
659        // generic args, instead of how we represent them in body expressions.
660        let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
661        let mut pattern = self.const_to_pat(c, ty, id, span);
662
663        // If this is an associated constant with an explicit user-written
664        // type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`).
665        if let Some(&user_ty) = user_ty {
666            let annotation = CanonicalUserTypeAnnotation {
667                user_ty: Box::new(user_ty),
668                span,
669                inferred_ty: self.typeck_results.node_type(id),
670            };
671            // Note that we use `Contravariant` here. See the
672            // `variance` field documentation for details.
673            pattern
674                .extra
675                .get_or_insert_default()
676                .ascriptions
677                .push(Ascription { annotation, variance: ty::Contravariant });
678        }
679
680        pattern
681    }
682
683    /// Lowers the kinds of "expression" that can appear in a HIR pattern:
684    /// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`)
685    /// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
686    fn lower_pat_expr(
687        &mut self,
688        pat: &'tcx hir::Pat<'tcx>, // Pattern that directly contains `expr`
689        expr: &'tcx hir::PatExpr<'tcx>,
690    ) -> Box<Pat<'tcx>> {
691        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(..));
692        match &expr.kind {
693            hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath),
694            hir::PatExprKind::Lit { lit, negated } => {
695                // We handle byte string literal patterns by using the pattern's type instead of the
696                // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
697                // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
698                // pattern's type means we'll properly translate it to a slice reference pattern. This works
699                // because slices and arrays have the same valtree representation.
700                //
701                // Under `feature(deref_patterns)`, this adjustment can also convert string literal
702                // patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.
703
704                let pat_ty = self.typeck_results.node_type(pat.hir_id);
705                let lit_input = LitToConstInput { lit: lit.node, ty: Some(pat_ty), neg: *negated };
706                let constant = const_lit_matches_ty(self.tcx, &lit.node, pat_ty, *negated)
707                    .then(|| self.tcx.at(expr.span).lit_to_const(lit_input))
708                    .flatten()
709                    .map(|v| ty::Const::new_value(self.tcx, v.valtree, pat_ty))
710                    .unwrap_or_else(|| {
711                        ty::Const::new_error_with_message(
712                            self.tcx,
713                            expr.span,
714                            "literal does not match expected type",
715                        )
716                    });
717                self.const_to_pat(constant, pat_ty, expr.hir_id, lit.span)
718            }
719        }
720    }
721}