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