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, 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
33struct PatCtxt<'tcx> {
35 tcx: TyCtxt<'tcx>,
36 typing_env: ty::TypingEnv<'tcx>,
37 typeck_results: &'tcx ty::TypeckResults<'tcx>,
38
39 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 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 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 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 let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr, None);
144
145 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 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 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 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 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 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 (RangeEnd::Excluded, Some(Ordering::Less)) => {}
244 (RangeEnd::Included, Some(Ordering::Less)) => {}
246 (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 (RangeEnd::Included, Some(Ordering::Equal)) if !lo.is_finite() => {}
253 (RangeEnd::Included, Some(Ordering::Equal)) if !hi.is_finite() => {}
256 _ => {
258 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 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 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 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 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 ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
463 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 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 #[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 let kind = self.lower_variant_or_leaf(res, id, span, ty, vec![]);
582 return Box::new(Pat { span, ty, kind });
583 }
584 };
585
586 let args = self.typeck_results.node_args(id);
588 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 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 variance: ty::Contravariant,
608 },
609 };
610 pattern = Box::new(Pat { span, kind, ty });
611 }
612
613 pattern
614 }
615
616 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 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 variance: ty::Contravariant,
657 },
658 }
659 }
660
661 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 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}