1mod 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, ByRef, LangItem, Mutability, Pinnedness, RangeEnd};
15use rustc_index::Idx;
16use rustc_infer::infer::TyCtxtInferExt;
17use rustc_middle::mir::interpret::LitToConstInput;
18use rustc_middle::thir::{
19 Ascription, 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
33struct PatCtxt<'a, 'tcx> {
34 tcx: TyCtxt<'tcx>,
35 typing_env: ty::TypingEnv<'tcx>,
36 typeck_results: &'a ty::TypeckResults<'tcx>,
37
38 rust_2024_migration: Option<PatMigration<'a>>,
40}
41
42pub(super) fn pat_from_hir<'a, 'tcx>(
43 tcx: TyCtxt<'tcx>,
44 typing_env: ty::TypingEnv<'tcx>,
45 typeck_results: &'a ty::TypeckResults<'tcx>,
46 pat: &'tcx hir::Pat<'tcx>,
47) -> Box<Pat<'tcx>> {
48 let mut pcx = PatCtxt {
49 tcx,
50 typing_env,
51 typeck_results,
52 rust_2024_migration: typeck_results
53 .rust_2024_migration_desugared_pats()
54 .get(pat.hir_id)
55 .map(PatMigration::new),
56 };
57 let result = pcx.lower_pattern(pat);
58 debug!("pat_from_hir({:?}) = {:?}", pat, result);
59 if let Some(m) = pcx.rust_2024_migration {
60 m.emit(tcx, pat.hir_id);
61 }
62 result
63}
64
65impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
66 fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
67 let adjustments: &[PatAdjustment<'tcx>] =
68 self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
69
70 let mut opt_old_mode_span = None;
74 if let Some(s) = &mut self.rust_2024_migration
75 && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
76 {
77 opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments);
78 }
79
80 let unadjusted_pat = match pat.kind {
100 hir::PatKind::Ref(inner, _, _)
101 if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) =>
102 {
103 self.lower_pattern(inner)
104 }
105 _ => self.lower_pattern_unadjusted(pat),
106 };
107
108 let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| {
109 debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust);
110 let span = thir_pat.span;
111 let kind = match adjust.kind {
112 PatAdjust::BuiltinDeref => PatKind::Deref { subpattern: thir_pat },
113 PatAdjust::OverloadedDeref => {
114 let borrow = self.typeck_results.deref_pat_borrow_mode(adjust.source, pat);
115 PatKind::DerefPattern { subpattern: thir_pat, borrow }
116 }
117 PatAdjust::PinDeref => {
118 let mutable = self.typeck_results.pat_has_ref_mut_binding(pat);
119 PatKind::DerefPattern {
120 subpattern: thir_pat,
121 borrow: ByRef::Yes(
122 Pinnedness::Pinned,
123 if mutable { Mutability::Mut } else { Mutability::Not },
124 ),
125 }
126 }
127 };
128 Box::new(Pat { span, ty: adjust.source, kind })
129 });
130
131 if let Some(s) = &mut self.rust_2024_migration
132 && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
133 {
134 s.leave_ref(opt_old_mode_span);
135 }
136
137 adjusted_pat
138 }
139
140 fn lower_pattern_range_endpoint(
141 &mut self,
142 expr: Option<&'tcx hir::PatExpr<'tcx>>,
143 ascriptions: &mut Vec<Ascription<'tcx>>,
145 expanded_consts: &mut Vec<DefId>,
146 ) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
147 let Some(expr) = expr else { return Ok(None) };
148
149 let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr, None);
152
153 loop {
155 match kind {
156 PatKind::AscribeUserType { ascription, subpattern } => {
157 ascriptions.push(ascription);
158 kind = subpattern.kind;
159 }
160 PatKind::ExpandedConstant { def_id, subpattern } => {
161 expanded_consts.push(def_id);
162 kind = subpattern.kind;
163 }
164 _ => break,
165 }
166 }
167
168 let PatKind::Constant { value } = kind else {
170 let msg =
171 format!("found bad range pattern endpoint `{expr:?}` outside of error recovery");
172 return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
173 };
174 Ok(Some(PatRangeBoundary::Finite(value.valtree)))
175 }
176
177 fn error_on_literal_overflow(
183 &self,
184 expr: Option<&'tcx hir::PatExpr<'tcx>>,
185 ty: Ty<'tcx>,
186 ) -> Result<(), ErrorGuaranteed> {
187 use rustc_ast::ast::LitKind;
188
189 let Some(expr) = expr else {
190 return Ok(());
191 };
192 let span = expr.span;
193
194 let hir::PatExprKind::Lit { lit, negated } = expr.kind else {
198 return Ok(());
199 };
200 let LitKind::Int(lit_val, _) = lit.node else {
201 return Ok(());
202 };
203 let (min, max): (i128, u128) = match ty.kind() {
204 ty::Int(ity) => {
205 let size = Integer::from_int_ty(&self.tcx, *ity).size();
206 (size.signed_int_min(), size.signed_int_max() as u128)
207 }
208 ty::Uint(uty) => {
209 let size = Integer::from_uint_ty(&self.tcx, *uty).size();
210 (0, size.unsigned_int_max())
211 }
212 _ => {
213 return Ok(());
214 }
215 };
216 if (negated && lit_val > max + 1) || (!negated && lit_val > max) {
219 return Err(self.tcx.dcx().emit_err(LiteralOutOfRange { span, ty, min, max }));
220 }
221 Ok(())
222 }
223
224 fn lower_pattern_range(
225 &mut self,
226 lo_expr: Option<&'tcx hir::PatExpr<'tcx>>,
227 hi_expr: Option<&'tcx hir::PatExpr<'tcx>>,
228 end: RangeEnd,
229 ty: Ty<'tcx>,
230 span: Span,
231 ) -> Result<PatKind<'tcx>, ErrorGuaranteed> {
232 if lo_expr.is_none() && hi_expr.is_none() {
233 let msg = "found twice-open range pattern (`..`) outside of error recovery";
234 self.tcx.dcx().span_bug(span, msg);
235 }
236
237 let mut ascriptions = vec![];
239 let mut expanded_consts = vec![];
240
241 let mut lower_endpoint =
242 |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut expanded_consts);
243
244 let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
245 let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
246
247 let cmp = lo.compare_with(hi, ty, self.tcx);
248 let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty }));
249 match (end, cmp) {
250 (RangeEnd::Excluded, Some(Ordering::Less)) => {}
252 (RangeEnd::Included, Some(Ordering::Less)) => {}
254 (RangeEnd::Included, Some(Ordering::Equal)) if lo.is_finite() && hi.is_finite() => {
256 let value = ty::Value { ty, valtree: lo.as_finite().unwrap() };
257 kind = PatKind::Constant { value };
258 }
259 (RangeEnd::Included, Some(Ordering::Equal)) if !lo.is_finite() => {}
261 (RangeEnd::Included, Some(Ordering::Equal)) if !hi.is_finite() => {}
264 _ => {
266 self.error_on_literal_overflow(lo_expr, ty)?;
268 self.error_on_literal_overflow(hi_expr, ty)?;
269 let e = match end {
270 RangeEnd::Included => {
271 self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
272 span,
273 teach: self.tcx.sess.teach(E0030),
274 })
275 }
276 RangeEnd::Excluded if lo_expr.is_none() => {
277 self.tcx.dcx().emit_err(UpperRangeBoundCannotBeMin { span })
278 }
279 RangeEnd::Excluded => {
280 self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanUpper { span })
281 }
282 };
283 return Err(e);
284 }
285 }
286
287 for ascription in ascriptions {
291 let subpattern = Box::new(Pat { span, ty, kind });
292 kind = PatKind::AscribeUserType { ascription, subpattern };
293 }
294 for def_id in expanded_consts {
295 let subpattern = Box::new(Pat { span, ty, kind });
296 kind = PatKind::ExpandedConstant { def_id, subpattern };
297 }
298 Ok(kind)
299 }
300
301 #[instrument(skip(self), level = "debug")]
302 fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
303 let mut ty = self.typeck_results.node_type(pat.hir_id);
304 let mut span = pat.span;
305
306 let kind = match pat.kind {
307 hir::PatKind::Missing => PatKind::Missing,
308
309 hir::PatKind::Wild => PatKind::Wild,
310
311 hir::PatKind::Never => PatKind::Never,
312
313 hir::PatKind::Expr(value) => self.lower_pat_expr(value, Some(ty)),
314
315 hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
316 let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
317 self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
318 .unwrap_or_else(PatKind::Error)
319 }
320
321 hir::PatKind::Deref(subpattern) => {
322 let borrow = self.typeck_results.deref_pat_borrow_mode(ty, subpattern);
323 PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), borrow }
324 }
325 hir::PatKind::Ref(subpattern, _, _) => {
326 let opt_old_mode_span =
328 self.rust_2024_migration.as_mut().and_then(|s| s.visit_explicit_deref());
329 let subpattern = self.lower_pattern(subpattern);
330 if let Some(s) = &mut self.rust_2024_migration {
331 s.leave_ref(opt_old_mode_span);
332 }
333 PatKind::Deref { subpattern }
334 }
335 hir::PatKind::Box(subpattern) => PatKind::DerefPattern {
336 subpattern: self.lower_pattern(subpattern),
337 borrow: hir::ByRef::No,
338 },
339
340 hir::PatKind::Slice(prefix, slice, suffix) => {
341 self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
342 }
343
344 hir::PatKind::Tuple(pats, ddpos) => {
345 let ty::Tuple(tys) = ty.kind() else {
346 span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty);
347 };
348 let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos);
349 PatKind::Leaf { subpatterns }
350 }
351
352 hir::PatKind::Binding(explicit_ba, id, ident, sub) => {
353 if let Some(ident_span) = ident.span.find_ancestor_inside(span) {
354 span = span.with_hi(ident_span.hi());
355 }
356
357 let mode = *self
358 .typeck_results
359 .pat_binding_modes()
360 .get(pat.hir_id)
361 .expect("missing binding mode");
362
363 if let Some(s) = &mut self.rust_2024_migration {
364 s.visit_binding(pat.span, mode, explicit_ba, ident);
365 }
366
367 let var_ty = ty;
370 if let hir::ByRef::Yes(pinnedness, _) = mode.0 {
371 match pinnedness {
372 hir::Pinnedness::Pinned
373 if let Some(pty) = ty.pinned_ty()
374 && let &ty::Ref(_, rty, _) = pty.kind() =>
375 {
376 ty = rty;
377 }
378 hir::Pinnedness::Not if let &ty::Ref(_, rty, _) = ty.kind() => {
379 ty = rty;
380 }
381 _ => bug!("`ref {}` has wrong type {}", ident, ty),
382 }
383 };
384
385 PatKind::Binding {
386 mode,
387 name: ident.name,
388 var: LocalVarId(id),
389 ty: var_ty,
390 subpattern: self.lower_opt_pattern(sub),
391 is_primary: id == pat.hir_id,
392 is_shorthand: false,
393 }
394 }
395
396 hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
397 let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
398 let ty::Adt(adt_def, _) = ty.kind() else {
399 span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty);
400 };
401 let variant_def = adt_def.variant_of_res(res);
402 let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
403 self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns)
404 }
405
406 hir::PatKind::Struct(ref qpath, fields, _) => {
407 let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
408 let subpatterns = fields
409 .iter()
410 .map(|field| {
411 let mut pattern = *self.lower_pattern(field.pat);
412 if let PatKind::Binding { ref mut is_shorthand, .. } = pattern.kind {
413 *is_shorthand = field.is_shorthand;
414 }
415 let field = self.typeck_results.field_index(field.hir_id);
416 FieldPat { field, pattern }
417 })
418 .collect();
419
420 self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns)
421 }
422
423 hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
424
425 hir::PatKind::Guard(pat, _) => self.lower_pattern(pat).kind,
427
428 hir::PatKind::Err(guar) => PatKind::Error(guar),
429 };
430
431 Box::new(Pat { span, ty, kind })
432 }
433
434 fn lower_tuple_subpats(
435 &mut self,
436 pats: &'tcx [hir::Pat<'tcx>],
437 expected_len: usize,
438 gap_pos: hir::DotDotPos,
439 ) -> Vec<FieldPat<'tcx>> {
440 pats.iter()
441 .enumerate_and_adjust(expected_len, gap_pos)
442 .map(|(i, subpattern)| FieldPat {
443 field: FieldIdx::new(i),
444 pattern: *self.lower_pattern(subpattern),
445 })
446 .collect()
447 }
448
449 fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Pat<'tcx>]> {
450 pats.iter().map(|p| *self.lower_pattern(p)).collect()
451 }
452
453 fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {
454 pat.map(|p| self.lower_pattern(p))
455 }
456
457 fn slice_or_array_pattern(
458 &mut self,
459 span: Span,
460 ty: Ty<'tcx>,
461 prefix: &'tcx [hir::Pat<'tcx>],
462 slice: Option<&'tcx hir::Pat<'tcx>>,
463 suffix: &'tcx [hir::Pat<'tcx>],
464 ) -> PatKind<'tcx> {
465 let prefix = self.lower_patterns(prefix);
466 let slice = self.lower_opt_pattern(slice);
467 let suffix = self.lower_patterns(suffix);
468 match ty.kind() {
469 ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
471 ty::Array(_, len) => {
473 let len = len
474 .try_to_target_usize(self.tcx)
475 .expect("expected len of array pat to be definite");
476 assert!(len >= prefix.len() as u64 + suffix.len() as u64);
477 PatKind::Array { prefix, slice, suffix }
478 }
479 _ => span_bug!(span, "bad slice pattern type {:?}", ty),
480 }
481 }
482
483 fn lower_variant_or_leaf(
484 &mut self,
485 res: Res,
486 hir_id: hir::HirId,
487 span: Span,
488 ty: Ty<'tcx>,
489 subpatterns: Vec<FieldPat<'tcx>>,
490 ) -> PatKind<'tcx> {
491 let res = match res {
492 Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
493 let variant_id = self.tcx.parent(variant_ctor_id);
494 Res::Def(DefKind::Variant, variant_id)
495 }
496 res => res,
497 };
498
499 let mut kind = match res {
500 Res::Def(DefKind::Variant, variant_id) => {
501 let enum_id = self.tcx.parent(variant_id);
502 let adt_def = self.tcx.adt_def(enum_id);
503 if adt_def.is_enum() {
504 let args = match ty.kind() {
505 ty::Adt(_, args) | ty::FnDef(_, args) => args,
506 ty::Error(e) => {
507 return PatKind::Error(*e);
509 }
510 _ => bug!("inappropriate type for def: {:?}", ty),
511 };
512 PatKind::Variant {
513 adt_def,
514 args,
515 variant_index: adt_def.variant_index_with_id(variant_id),
516 subpatterns,
517 }
518 } else {
519 PatKind::Leaf { subpatterns }
520 }
521 }
522
523 Res::Def(
524 DefKind::Struct
525 | DefKind::Ctor(CtorOf::Struct, ..)
526 | DefKind::Union
527 | DefKind::TyAlias
528 | DefKind::AssocTy,
529 _,
530 )
531 | Res::SelfTyParam { .. }
532 | Res::SelfTyAlias { .. }
533 | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
534 _ => {
535 let e = match res {
536 Res::Def(DefKind::ConstParam, def_id) => {
537 let const_span = self.tcx.def_span(def_id);
538 self.tcx.dcx().emit_err(ConstParamInPattern { span, const_span })
539 }
540 Res::Def(DefKind::Static { .. }, def_id) => {
541 let static_span = self.tcx.def_span(def_id);
542 self.tcx.dcx().emit_err(StaticInPattern { span, static_span })
543 }
544 _ => self.tcx.dcx().emit_err(NonConstPath { span }),
545 };
546 PatKind::Error(e)
547 }
548 };
549
550 if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) {
551 debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
552 let annotation = CanonicalUserTypeAnnotation {
553 user_ty: Box::new(user_ty),
554 span,
555 inferred_ty: self.typeck_results.node_type(hir_id),
556 };
557 kind = PatKind::AscribeUserType {
558 subpattern: Box::new(Pat { span, ty, kind }),
559 ascription: Ascription { annotation, variance: ty::Covariant },
560 };
561 }
562
563 kind
564 }
565
566 fn user_args_applied_to_ty_of_hir_id(
567 &self,
568 hir_id: hir::HirId,
569 ) -> Option<ty::CanonicalUserType<'tcx>> {
570 crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
571 }
572
573 #[instrument(skip(self), level = "debug")]
577 fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Box<Pat<'tcx>> {
578 let ty = self.typeck_results.node_type(id);
579 let res = self.typeck_results.qpath_res(qpath, id);
580
581 let (def_id, user_ty) = match res {
582 Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
583 (def_id, self.typeck_results.user_provided_types().get(id))
584 }
585
586 _ => {
587 let kind = self.lower_variant_or_leaf(res, id, span, ty, vec![]);
590 return Box::new(Pat { span, ty, kind });
591 }
592 };
593
594 let args = self.typeck_results.node_args(id);
596 let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
599 let mut pattern = self.const_to_pat(c, ty, id, span);
600
601 if let Some(&user_ty) = user_ty {
604 let annotation = CanonicalUserTypeAnnotation {
605 user_ty: Box::new(user_ty),
606 span,
607 inferred_ty: self.typeck_results.node_type(id),
608 };
609 let kind = PatKind::AscribeUserType {
610 subpattern: pattern,
611 ascription: Ascription {
612 annotation,
613 variance: ty::Contravariant,
616 },
617 };
618 pattern = Box::new(Pat { span, kind, ty });
619 }
620
621 pattern
622 }
623
624 fn lower_inline_const(
626 &mut self,
627 block: &'tcx hir::ConstBlock,
628 id: hir::HirId,
629 span: Span,
630 ) -> PatKind<'tcx> {
631 let tcx = self.tcx;
632 let def_id = block.def_id;
633 let ty = tcx.typeck(def_id).node_type(block.hir_id);
634
635 let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
636 let parent_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
637 let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args;
638
639 let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
640 let c = ty::Const::new_unevaluated(self.tcx, ct);
641 let pattern = self.const_to_pat(c, ty, id, span);
642
643 let annotation = {
645 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
646 let args = ty::InlineConstArgs::new(
647 tcx,
648 ty::InlineConstArgsParts { parent_args, ty: infcx.next_ty_var(span) },
649 )
650 .args;
651 infcx.canonicalize_user_type_annotation(ty::UserType::new(ty::UserTypeKind::TypeOf(
652 def_id.to_def_id(),
653 ty::UserArgs { args, user_self_ty: None },
654 )))
655 };
656 let annotation =
657 CanonicalUserTypeAnnotation { user_ty: Box::new(annotation), span, inferred_ty: ty };
658 PatKind::AscribeUserType {
659 subpattern: pattern,
660 ascription: Ascription {
661 annotation,
662 variance: ty::Contravariant,
665 },
666 }
667 }
668
669 fn lower_pat_expr(
674 &mut self,
675 expr: &'tcx hir::PatExpr<'tcx>,
676 pat_ty: Option<Ty<'tcx>>,
677 ) -> PatKind<'tcx> {
678 match &expr.kind {
679 hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind,
680 hir::PatExprKind::ConstBlock(anon_const) => {
681 self.lower_inline_const(anon_const, expr.hir_id, expr.span)
682 }
683 hir::PatExprKind::Lit { lit, negated } => {
684 let ct_ty = match pat_ty {
694 Some(pat_ty)
695 if let ty::Adt(def, _) = *pat_ty.kind()
696 && self.tcx.is_lang_item(def.did(), LangItem::String) =>
697 {
698 if !self.tcx.features().string_deref_patterns() {
699 span_bug!(
700 expr.span,
701 "matching on `String` went through without enabling string_deref_patterns"
702 );
703 }
704 self.typeck_results.node_type(expr.hir_id)
705 }
706 Some(pat_ty) => pat_ty,
707 None => self.typeck_results.node_type(expr.hir_id),
708 };
709 let lit_input = LitToConstInput { lit: lit.node, ty: ct_ty, neg: *negated };
710 let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
711 self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind
712 }
713 }
714 }
715}