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