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