1mod check_match;
4mod const_to_pat;
5
6use std::cmp::Ordering;
7use std::sync::Arc;
8
9use rustc_abi::{FieldIdx, Integer};
10use rustc_errors::MultiSpan;
11use rustc_errors::codes::*;
12use rustc_hir::def::{CtorOf, DefKind, Res};
13use rustc_hir::pat_util::EnumerateAndAdjustIterator;
14use rustc_hir::{self as hir, ByRef, Mutability, RangeEnd};
15use rustc_index::Idx;
16use rustc_lint as lint;
17use rustc_middle::mir::interpret::LitToConstInput;
18use rustc_middle::thir::{
19 Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
20};
21use rustc_middle::ty::layout::IntegerExt;
22use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt};
23use rustc_middle::{bug, span_bug};
24use rustc_span::def_id::LocalDefId;
25use rustc_span::{ErrorGuaranteed, Span};
26use tracing::{debug, instrument};
27
28pub(crate) use self::check_match::check_match;
29use crate::errors::*;
30use crate::fluent_generated as fluent;
31
32struct PatCtxt<'a, 'tcx> {
33 tcx: TyCtxt<'tcx>,
34 typing_env: ty::TypingEnv<'tcx>,
35 typeck_results: &'a ty::TypeckResults<'tcx>,
36
37 rust_2024_migration_suggestion: Option<Rust2024IncompatiblePatSugg>,
39}
40
41pub(super) fn pat_from_hir<'a, 'tcx>(
42 tcx: TyCtxt<'tcx>,
43 typing_env: ty::TypingEnv<'tcx>,
44 typeck_results: &'a ty::TypeckResults<'tcx>,
45 pat: &'tcx hir::Pat<'tcx>,
46) -> Box<Pat<'tcx>> {
47 let migration_info = typeck_results.rust_2024_migration_desugared_pats().get(pat.hir_id);
48 let mut pcx = PatCtxt {
49 tcx,
50 typing_env,
51 typeck_results,
52 rust_2024_migration_suggestion: migration_info.and_then(|info| {
53 Some(Rust2024IncompatiblePatSugg {
54 suggest_eliding_modes: info.suggest_eliding_modes,
55 suggestion: Vec::new(),
56 ref_pattern_count: 0,
57 binding_mode_count: 0,
58 default_mode_span: None,
59 default_mode_labels: Default::default(),
60 })
61 }),
62 };
63 let result = pcx.lower_pattern(pat);
64 debug!("pat_from_hir({:?}) = {:?}", pat, result);
65 if let Some(info) = migration_info
66 && let Some(sugg) = pcx.rust_2024_migration_suggestion
67 {
68 let mut spans =
69 MultiSpan::from_spans(info.primary_labels.iter().map(|(span, _)| *span).collect());
70 for (span, label) in &info.primary_labels {
71 spans.push_span_label(*span, label.clone());
72 }
73 let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024());
75 if is_hard_error {
76 let mut err =
77 tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat);
78 if let Some(lint_info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible {
79 err.note(format!("for more information, see {}", lint_info.reference));
81 }
82 err.arg("bad_modifiers", info.bad_modifiers);
83 err.arg("bad_ref_pats", info.bad_ref_pats);
84 err.arg("is_hard_error", true);
85 err.subdiagnostic(sugg);
86 err.emit();
87 } else {
88 tcx.emit_node_span_lint(
89 lint::builtin::RUST_2024_INCOMPATIBLE_PAT,
90 pat.hir_id,
91 spans,
92 Rust2024IncompatiblePat {
93 sugg,
94 bad_modifiers: info.bad_modifiers,
95 bad_ref_pats: info.bad_ref_pats,
96 is_hard_error,
97 },
98 );
99 }
100 }
101 result
102}
103
104impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
105 fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
106 let adjustments: &[Ty<'tcx>] =
107 self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
108
109 let mut opt_old_mode_span = None;
110 if let Some(s) = &mut self.rust_2024_migration_suggestion
111 && !adjustments.is_empty()
112 {
113 let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| {
114 let &ty::Ref(_, _, mutbl) = ref_ty.kind() else {
115 span_bug!(pat.span, "pattern implicitly dereferences a non-ref type");
116 };
117 mutbl
118 });
119
120 if !s.suggest_eliding_modes {
121 let suggestion_str: String =
122 implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect();
123 s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str));
124 s.ref_pattern_count += adjustments.len();
125 }
126
127 let min_mutbl = implicit_deref_mutbls.min().unwrap();
129 if s.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) {
130 opt_old_mode_span = Some(s.default_mode_span);
131 s.default_mode_span = Some((pat.span, min_mutbl));
132 }
133 };
134
135 let unadjusted_pat = match pat.kind {
155 hir::PatKind::Ref(inner, _)
156 if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) =>
157 {
158 self.lower_pattern(inner)
159 }
160 _ => self.lower_pattern_unadjusted(pat),
161 };
162
163 let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, ref_ty| {
164 debug!("{:?}: wrapping pattern with type {:?}", thir_pat, ref_ty);
165 Box::new(Pat {
166 span: thir_pat.span,
167 ty: *ref_ty,
168 kind: PatKind::Deref { subpattern: thir_pat },
169 })
170 });
171
172 if let Some(s) = &mut self.rust_2024_migration_suggestion
173 && let Some(old_mode_span) = opt_old_mode_span
174 {
175 s.default_mode_span = old_mode_span;
176 }
177
178 adjusted_pat
179 }
180
181 fn lower_pattern_range_endpoint(
182 &mut self,
183 expr: Option<&'tcx hir::PatExpr<'tcx>>,
184 ascriptions: &mut Vec<Ascription<'tcx>>,
186 inline_consts: &mut Vec<LocalDefId>,
187 ) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
188 let Some(expr) = expr else { return Ok(None) };
189
190 let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr);
193
194 loop {
196 match kind {
197 PatKind::AscribeUserType { ascription, subpattern } => {
198 ascriptions.push(ascription);
199 kind = subpattern.kind;
200 }
201 PatKind::ExpandedConstant { is_inline, def_id, subpattern } => {
202 if is_inline {
203 inline_consts.extend(def_id.as_local());
204 }
205 kind = subpattern.kind;
206 }
207 _ => break,
208 }
209 }
210
211 let PatKind::Constant { value } = kind else {
213 let msg =
214 format!("found bad range pattern endpoint `{expr:?}` outside of error recovery");
215 return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
216 };
217
218 Ok(Some(PatRangeBoundary::Finite(value)))
219 }
220
221 fn error_on_literal_overflow(
227 &self,
228 expr: Option<&'tcx hir::PatExpr<'tcx>>,
229 ty: Ty<'tcx>,
230 ) -> Result<(), ErrorGuaranteed> {
231 use rustc_ast::ast::LitKind;
232
233 let Some(expr) = expr else {
234 return Ok(());
235 };
236 let span = expr.span;
237
238 let hir::PatExprKind::Lit { lit, negated } = expr.kind else {
242 return Ok(());
243 };
244 let LitKind::Int(lit_val, _) = lit.node else {
245 return Ok(());
246 };
247 let (min, max): (i128, u128) = match ty.kind() {
248 ty::Int(ity) => {
249 let size = Integer::from_int_ty(&self.tcx, *ity).size();
250 (size.signed_int_min(), size.signed_int_max() as u128)
251 }
252 ty::Uint(uty) => {
253 let size = Integer::from_uint_ty(&self.tcx, *uty).size();
254 (0, size.unsigned_int_max())
255 }
256 _ => {
257 return Ok(());
258 }
259 };
260 if (negated && lit_val > max + 1) || (!negated && lit_val > max) {
263 return Err(self.tcx.dcx().emit_err(LiteralOutOfRange { span, ty, min, max }));
264 }
265 Ok(())
266 }
267
268 fn lower_pattern_range(
269 &mut self,
270 lo_expr: Option<&'tcx hir::PatExpr<'tcx>>,
271 hi_expr: Option<&'tcx hir::PatExpr<'tcx>>,
272 end: RangeEnd,
273 ty: Ty<'tcx>,
274 span: Span,
275 ) -> Result<PatKind<'tcx>, ErrorGuaranteed> {
276 if lo_expr.is_none() && hi_expr.is_none() {
277 let msg = "found twice-open range pattern (`..`) outside of error recovery";
278 self.tcx.dcx().span_bug(span, msg);
279 }
280
281 let mut ascriptions = vec![];
283 let mut inline_consts = vec![];
284
285 let mut lower_endpoint =
286 |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts);
287
288 let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
289 let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
290
291 let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
292 let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty }));
293 match (end, cmp) {
294 (RangeEnd::Excluded, Some(Ordering::Less)) => {}
296 (RangeEnd::Included, Some(Ordering::Less)) => {}
298 (RangeEnd::Included, Some(Ordering::Equal)) if lo.is_finite() && hi.is_finite() => {
300 kind = PatKind::Constant { value: lo.as_finite().unwrap() };
301 }
302 (RangeEnd::Included, Some(Ordering::Equal)) if !lo.is_finite() => {}
304 (RangeEnd::Included, Some(Ordering::Equal)) if !hi.is_finite() => {}
307 _ => {
309 self.error_on_literal_overflow(lo_expr, ty)?;
311 self.error_on_literal_overflow(hi_expr, ty)?;
312 let e = match end {
313 RangeEnd::Included => {
314 self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
315 span,
316 teach: self.tcx.sess.teach(E0030),
317 })
318 }
319 RangeEnd::Excluded => {
320 self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanUpper { span })
321 }
322 };
323 return Err(e);
324 }
325 }
326
327 for ascription in ascriptions {
331 kind = PatKind::AscribeUserType {
332 ascription,
333 subpattern: Box::new(Pat { span, ty, kind }),
334 };
335 }
336 for def in inline_consts {
337 kind = PatKind::ExpandedConstant {
338 def_id: def.to_def_id(),
339 is_inline: true,
340 subpattern: Box::new(Pat { span, ty, kind }),
341 };
342 }
343 Ok(kind)
344 }
345
346 #[instrument(skip(self), level = "debug")]
347 fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
348 let mut ty = self.typeck_results.node_type(pat.hir_id);
349 let mut span = pat.span;
350
351 let kind = match pat.kind {
352 hir::PatKind::Wild => PatKind::Wild,
353
354 hir::PatKind::Never => PatKind::Never,
355
356 hir::PatKind::Expr(value) => self.lower_pat_expr(value),
357
358 hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
359 let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
360 self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
361 .unwrap_or_else(PatKind::Error)
362 }
363
364 hir::PatKind::Deref(subpattern) => {
365 let mutable = self.typeck_results.pat_has_ref_mut_binding(subpattern);
366 let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
367 PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), mutability }
368 }
369 hir::PatKind::Ref(subpattern, _) => {
370 let old_mode_span = self.rust_2024_migration_suggestion.as_mut().and_then(|s| {
372 if let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span {
373 s.default_mode_labels.insert(default_mode_span, default_ref_mutbl);
375 }
376 s.default_mode_span.take()
377 });
378 let subpattern = self.lower_pattern(subpattern);
379 if let Some(s) = &mut self.rust_2024_migration_suggestion {
380 s.default_mode_span = old_mode_span;
381 }
382 PatKind::Deref { subpattern }
383 }
384 hir::PatKind::Box(subpattern) => {
385 PatKind::Deref { subpattern: self.lower_pattern(subpattern) }
386 }
387
388 hir::PatKind::Slice(prefix, slice, suffix) => {
389 self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
390 }
391
392 hir::PatKind::Tuple(pats, ddpos) => {
393 let ty::Tuple(tys) = ty.kind() else {
394 span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty);
395 };
396 let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos);
397 PatKind::Leaf { subpatterns }
398 }
399
400 hir::PatKind::Binding(explicit_ba, id, ident, sub) => {
401 if let Some(ident_span) = ident.span.find_ancestor_inside(span) {
402 span = span.with_hi(ident_span.hi());
403 }
404
405 let mode = *self
406 .typeck_results
407 .pat_binding_modes()
408 .get(pat.hir_id)
409 .expect("missing binding mode");
410
411 if let Some(s) = &mut self.rust_2024_migration_suggestion {
412 if explicit_ba != hir::BindingMode::NONE
413 && let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span
414 {
415 s.default_mode_labels.insert(default_mode_span, default_ref_mutbl);
417 if s.suggest_eliding_modes {
419 s.suggestion.push((pat.span.with_hi(ident.span.lo()), String::new()));
420 s.binding_mode_count += 1;
421 }
422 }
423 if !s.suggest_eliding_modes
424 && explicit_ba.0 == ByRef::No
425 && let ByRef::Yes(mutbl) = mode.0
426 {
427 let sugg_str = match mutbl {
428 Mutability::Not => "ref ",
429 Mutability::Mut => "ref mut ",
430 };
431 s.suggestion.push((
432 pat.span.with_lo(ident.span.lo()).shrink_to_lo(),
433 sugg_str.to_owned(),
434 ));
435 s.binding_mode_count += 1;
436 }
437 }
438
439 let var_ty = ty;
442 if let hir::ByRef::Yes(_) = mode.0 {
443 if let ty::Ref(_, rty, _) = ty.kind() {
444 ty = *rty;
445 } else {
446 bug!("`ref {}` has wrong type {}", ident, ty);
447 }
448 };
449
450 PatKind::Binding {
451 mode,
452 name: ident.name,
453 var: LocalVarId(id),
454 ty: var_ty,
455 subpattern: self.lower_opt_pattern(sub),
456 is_primary: id == pat.hir_id,
457 }
458 }
459
460 hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
461 let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
462 let ty::Adt(adt_def, _) = ty.kind() else {
463 span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty);
464 };
465 let variant_def = adt_def.variant_of_res(res);
466 let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
467 self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns)
468 }
469
470 hir::PatKind::Struct(ref qpath, fields, _) => {
471 let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
472 let subpatterns = fields
473 .iter()
474 .map(|field| FieldPat {
475 field: self.typeck_results.field_index(field.hir_id),
476 pattern: *self.lower_pattern(field.pat),
477 })
478 .collect();
479
480 self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns)
481 }
482
483 hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
484
485 hir::PatKind::Guard(pat, _) => self.lower_pattern(pat).kind,
487
488 hir::PatKind::Err(guar) => PatKind::Error(guar),
489 };
490
491 Box::new(Pat { span, ty, kind })
492 }
493
494 fn lower_tuple_subpats(
495 &mut self,
496 pats: &'tcx [hir::Pat<'tcx>],
497 expected_len: usize,
498 gap_pos: hir::DotDotPos,
499 ) -> Vec<FieldPat<'tcx>> {
500 pats.iter()
501 .enumerate_and_adjust(expected_len, gap_pos)
502 .map(|(i, subpattern)| FieldPat {
503 field: FieldIdx::new(i),
504 pattern: *self.lower_pattern(subpattern),
505 })
506 .collect()
507 }
508
509 fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Pat<'tcx>]> {
510 pats.iter().map(|p| *self.lower_pattern(p)).collect()
511 }
512
513 fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {
514 pat.map(|p| self.lower_pattern(p))
515 }
516
517 fn slice_or_array_pattern(
518 &mut self,
519 span: Span,
520 ty: Ty<'tcx>,
521 prefix: &'tcx [hir::Pat<'tcx>],
522 slice: Option<&'tcx hir::Pat<'tcx>>,
523 suffix: &'tcx [hir::Pat<'tcx>],
524 ) -> PatKind<'tcx> {
525 let prefix = self.lower_patterns(prefix);
526 let slice = self.lower_opt_pattern(slice);
527 let suffix = self.lower_patterns(suffix);
528 match ty.kind() {
529 ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
531 ty::Array(_, len) => {
533 let len = len
534 .try_to_target_usize(self.tcx)
535 .expect("expected len of array pat to be definite");
536 assert!(len >= prefix.len() as u64 + suffix.len() as u64);
537 PatKind::Array { prefix, slice, suffix }
538 }
539 _ => span_bug!(span, "bad slice pattern type {:?}", ty),
540 }
541 }
542
543 fn lower_variant_or_leaf(
544 &mut self,
545 res: Res,
546 hir_id: hir::HirId,
547 span: Span,
548 ty: Ty<'tcx>,
549 subpatterns: Vec<FieldPat<'tcx>>,
550 ) -> PatKind<'tcx> {
551 let res = match res {
552 Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
553 let variant_id = self.tcx.parent(variant_ctor_id);
554 Res::Def(DefKind::Variant, variant_id)
555 }
556 res => res,
557 };
558
559 let mut kind = match res {
560 Res::Def(DefKind::Variant, variant_id) => {
561 let enum_id = self.tcx.parent(variant_id);
562 let adt_def = self.tcx.adt_def(enum_id);
563 if adt_def.is_enum() {
564 let args = match ty.kind() {
565 ty::Adt(_, args) | ty::FnDef(_, args) => args,
566 ty::Error(e) => {
567 return PatKind::Error(*e);
569 }
570 _ => bug!("inappropriate type for def: {:?}", ty),
571 };
572 PatKind::Variant {
573 adt_def,
574 args,
575 variant_index: adt_def.variant_index_with_id(variant_id),
576 subpatterns,
577 }
578 } else {
579 PatKind::Leaf { subpatterns }
580 }
581 }
582
583 Res::Def(
584 DefKind::Struct
585 | DefKind::Ctor(CtorOf::Struct, ..)
586 | DefKind::Union
587 | DefKind::TyAlias
588 | DefKind::AssocTy,
589 _,
590 )
591 | Res::SelfTyParam { .. }
592 | Res::SelfTyAlias { .. }
593 | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
594 _ => {
595 let e = match res {
596 Res::Def(DefKind::ConstParam, def_id) => {
597 let const_span = self.tcx.def_span(def_id);
598 self.tcx.dcx().emit_err(ConstParamInPattern { span, const_span })
599 }
600 Res::Def(DefKind::Static { .. }, def_id) => {
601 let static_span = self.tcx.def_span(def_id);
602 self.tcx.dcx().emit_err(StaticInPattern { span, static_span })
603 }
604 _ => self.tcx.dcx().emit_err(NonConstPath { span }),
605 };
606 PatKind::Error(e)
607 }
608 };
609
610 if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) {
611 debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
612 let annotation = CanonicalUserTypeAnnotation {
613 user_ty: Box::new(user_ty),
614 span,
615 inferred_ty: self.typeck_results.node_type(hir_id),
616 };
617 kind = PatKind::AscribeUserType {
618 subpattern: Box::new(Pat { span, ty, kind }),
619 ascription: Ascription { annotation, variance: ty::Covariant },
620 };
621 }
622
623 kind
624 }
625
626 fn user_args_applied_to_ty_of_hir_id(
627 &self,
628 hir_id: hir::HirId,
629 ) -> Option<ty::CanonicalUserType<'tcx>> {
630 crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id)
631 }
632
633 #[instrument(skip(self), level = "debug")]
637 fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Box<Pat<'tcx>> {
638 let ty = self.typeck_results.node_type(id);
639 let res = self.typeck_results.qpath_res(qpath, id);
640
641 let (def_id, user_ty) = match res {
642 Res::Def(DefKind::Const, def_id) => (def_id, None),
643 Res::Def(DefKind::AssocConst, def_id) => {
644 (def_id, self.typeck_results.user_provided_types().get(id))
645 }
646
647 _ => {
648 let kind = self.lower_variant_or_leaf(res, id, span, ty, vec![]);
651 return Box::new(Pat { span, ty, kind });
652 }
653 };
654
655 let args = self.typeck_results.node_args(id);
657 let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
658 let subpattern = self.const_to_pat(c, ty, id, span);
659
660 let mut pattern = {
664 let kind = PatKind::ExpandedConstant { subpattern, def_id, is_inline: false };
665 Box::new(Pat { span, ty, kind })
666 };
667
668 if let Some(&user_ty) = user_ty {
671 let annotation = CanonicalUserTypeAnnotation {
672 user_ty: Box::new(user_ty),
673 span,
674 inferred_ty: self.typeck_results.node_type(id),
675 };
676 let kind = PatKind::AscribeUserType {
677 subpattern: pattern,
678 ascription: Ascription {
679 annotation,
680 variance: ty::Contravariant,
683 },
684 };
685 pattern = Box::new(Pat { span, kind, ty });
686 }
687
688 pattern
689 }
690
691 fn lower_inline_const(
693 &mut self,
694 block: &'tcx hir::ConstBlock,
695 id: hir::HirId,
696 span: Span,
697 ) -> PatKind<'tcx> {
698 let tcx = self.tcx;
699 let def_id = block.def_id;
700 let ty = tcx.typeck(def_id).node_type(block.hir_id);
701
702 let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
703 let parent_args =
704 tcx.erase_regions(ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id));
705 let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args;
706
707 debug_assert!(!args.has_free_regions());
708
709 let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
710 let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span);
711
712 PatKind::ExpandedConstant { subpattern, def_id: def_id.to_def_id(), is_inline: true }
715 }
716
717 fn lower_pat_expr(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> {
722 let (lit, neg) = match &expr.kind {
723 hir::PatExprKind::Path(qpath) => {
724 return self.lower_path(qpath, expr.hir_id, expr.span).kind;
725 }
726 hir::PatExprKind::ConstBlock(anon_const) => {
727 return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
728 }
729 hir::PatExprKind::Lit { lit, negated } => (lit, *negated),
730 };
731
732 let ct_ty = self.typeck_results.node_type(expr.hir_id);
733 let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
734 let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
735 self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind
736 }
737}