1use std::cmp;
2use std::collections::hash_map::Entry::{Occupied, Vacant};
3
4use rustc_abi::FieldIdx;
5use rustc_ast as ast;
6use rustc_data_structures::fx::FxHashMap;
7use rustc_errors::codes::*;
8use rustc_errors::{
9 Applicability, Diag, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err,
10};
11use rustc_hir::def::{CtorKind, DefKind, Res};
12use rustc_hir::pat_util::EnumerateAndAdjustIterator;
13use rustc_hir::{
14 self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatExpr,
15 PatExprKind, PatKind, expr_needs_parens,
16};
17use rustc_infer::infer;
18use rustc_middle::traits::PatternOriginExpr;
19use rustc_middle::ty::{self, Ty, TypeVisitableExt};
20use rustc_middle::{bug, span_bug};
21use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
22use rustc_session::parse::feature_err;
23use rustc_span::edit_distance::find_best_match_for_name;
24use rustc_span::edition::Edition;
25use rustc_span::hygiene::DesugaringKind;
26use rustc_span::source_map::Spanned;
27use rustc_span::{BytePos, DUMMY_SP, Ident, Span, kw, sym};
28use rustc_trait_selection::infer::InferCtxtExt;
29use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
30use tracing::{debug, instrument, trace};
31use ty::VariantDef;
32
33use super::report_unexpected_variant_res;
34use crate::expectation::Expectation;
35use crate::gather_locals::DeclOrigin;
36use crate::{FnCtxt, LoweredTy, errors};
37
38const CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ: &str = "\
39This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
40pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
41this type has no compile-time size. Therefore, all accesses to trait types must be through \
42pointers. If you encounter this error you should try to avoid dereferencing the pointer.
43
44You can read more about trait objects in the Trait Objects section of the Reference: \
45https://doc.rust-lang.org/reference/types.html#trait-objects";
46
47fn is_number(text: &str) -> bool {
48 text.chars().all(|c: char| c.is_digit(10))
49}
50
51#[derive(Copy, Clone)]
55struct TopInfo<'tcx> {
56 expected: Ty<'tcx>,
58 origin_expr: Option<&'tcx hir::Expr<'tcx>>,
62 span: Option<Span>,
85 hir_id: HirId,
87}
88
89#[derive(Copy, Clone)]
90struct PatInfo<'tcx> {
91 binding_mode: ByRef,
92 max_ref_mutbl: MutblCap,
93 top_info: TopInfo<'tcx>,
94 decl_origin: Option<DeclOrigin<'tcx>>,
95
96 current_depth: u32,
98}
99
100impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
101 fn pattern_cause(&self, ti: &TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
102 let origin_expr_info = ti.origin_expr.map(|mut cur_expr| {
107 let mut count = 0;
108
109 while let ExprKind::AddrOf(.., inner) = &cur_expr.kind {
113 cur_expr = inner;
114 count += 1;
115 }
116
117 PatternOriginExpr {
118 peeled_span: cur_expr.span,
119 peeled_count: count,
120 peeled_prefix_suggestion_parentheses: expr_needs_parens(cur_expr),
121 }
122 });
123
124 let code = ObligationCauseCode::Pattern {
125 span: ti.span,
126 root_ty: ti.expected,
127 origin_expr: origin_expr_info,
128 };
129 self.cause(cause_span, code)
130 }
131
132 fn demand_eqtype_pat_diag(
133 &'a self,
134 cause_span: Span,
135 expected: Ty<'tcx>,
136 actual: Ty<'tcx>,
137 ti: &TopInfo<'tcx>,
138 ) -> Result<(), Diag<'a>> {
139 self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
140 .map_err(|mut diag| {
141 if let Some(expr) = ti.origin_expr {
142 self.suggest_fn_call(&mut diag, expr, expected, |output| {
143 self.can_eq(self.param_env, output, actual)
144 });
145 }
146 diag
147 })
148 }
149
150 fn demand_eqtype_pat(
151 &self,
152 cause_span: Span,
153 expected: Ty<'tcx>,
154 actual: Ty<'tcx>,
155 ti: &TopInfo<'tcx>,
156 ) -> Result<(), ErrorGuaranteed> {
157 self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map_err(|err| err.emit())
158 }
159}
160
161#[derive(Clone, Copy, Debug, PartialEq, Eq)]
163enum AdjustMode {
164 Peel,
166 Reset,
169 Pass,
171}
172
173#[derive(Clone, Copy, Debug, PartialEq, Eq)]
184enum MutblCap {
185 Not,
187
188 WeaklyNot(Option<Span>),
195
196 Mut,
198}
199
200impl MutblCap {
201 #[must_use]
202 fn cap_to_weakly_not(self, span: Option<Span>) -> Self {
203 match self {
204 MutblCap::Not => MutblCap::Not,
205 _ => MutblCap::WeaklyNot(span),
206 }
207 }
208
209 #[must_use]
210 fn as_mutbl(self) -> Mutability {
211 match self {
212 MutblCap::Not | MutblCap::WeaklyNot(_) => Mutability::Not,
213 MutblCap::Mut => Mutability::Mut,
214 }
215 }
216}
217
218#[derive(Clone, Copy, Debug, PartialEq, Eq)]
224enum InheritedRefMatchRule {
225 EatOuter,
229 EatInner,
232 EatBoth {
235 consider_inherited_ref: bool,
245 },
246}
247
248impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
249 fn downgrade_mut_inside_shared(&self) -> bool {
253 self.tcx.features().ref_pat_eat_one_layer_2024_structural()
256 }
257
258 fn ref_pat_matches_inherited_ref(&self, edition: Edition) -> InheritedRefMatchRule {
261 if edition.at_least_rust_2024() {
264 if self.tcx.features().ref_pat_eat_one_layer_2024() {
265 InheritedRefMatchRule::EatOuter
266 } else if self.tcx.features().ref_pat_eat_one_layer_2024_structural() {
267 InheritedRefMatchRule::EatInner
268 } else {
269 InheritedRefMatchRule::EatBoth { consider_inherited_ref: false }
272 }
273 } else {
274 InheritedRefMatchRule::EatBoth {
275 consider_inherited_ref: self.tcx.features().ref_pat_eat_one_layer_2024()
276 || self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
277 }
278 }
279 }
280
281 fn ref_pat_matches_mut_ref(&self) -> bool {
284 self.tcx.features().ref_pat_eat_one_layer_2024()
287 || self.tcx.features().ref_pat_eat_one_layer_2024_structural()
288 }
289
290 pub(crate) fn check_pat_top(
299 &self,
300 pat: &'tcx Pat<'tcx>,
301 expected: Ty<'tcx>,
302 span: Option<Span>,
303 origin_expr: Option<&'tcx hir::Expr<'tcx>>,
304 decl_origin: Option<DeclOrigin<'tcx>>,
305 ) {
306 let top_info = TopInfo { expected, origin_expr, span, hir_id: pat.hir_id };
307 let pat_info = PatInfo {
308 binding_mode: ByRef::No,
309 max_ref_mutbl: MutblCap::Mut,
310 top_info,
311 decl_origin,
312 current_depth: 0,
313 };
314 self.check_pat(pat, expected, pat_info);
315 }
316
317 #[instrument(level = "debug", skip(self, pat_info))]
323 fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) {
324 let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info;
325
326 let path_res = match pat.kind {
327 PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
328 Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span))
329 }
330 _ => None,
331 };
332 let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
333 let (expected, binding_mode, max_ref_mutbl) =
334 self.calc_default_binding_mode(pat, expected, binding_mode, adjust_mode, max_ref_mutbl);
335 let pat_info = PatInfo {
336 binding_mode,
337 max_ref_mutbl,
338 top_info: ti,
339 decl_origin: pat_info.decl_origin,
340 current_depth: current_depth + 1,
341 };
342
343 let ty = match pat.kind {
344 PatKind::Wild | PatKind::Err(_) => expected,
345 PatKind::Never => expected,
347 PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
348 let ty = self.check_pat_path(
349 *hir_id,
350 pat.hir_id,
351 *span,
352 qpath,
353 path_res.unwrap(),
354 expected,
355 &pat_info.top_info,
356 );
357 self.write_ty(*hir_id, ty);
358 ty
359 }
360 PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info),
361 PatKind::Range(lhs, rhs, _) => {
362 self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info)
363 }
364 PatKind::Binding(ba, var_id, ident, sub) => {
365 self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
366 }
367 PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
368 self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
369 }
370 PatKind::Struct(ref qpath, fields, has_rest_pat) => {
371 self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
372 }
373 PatKind::Guard(pat, cond) => {
374 self.check_pat(pat, expected, pat_info);
375 self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {});
376 expected
377 }
378 PatKind::Or(pats) => {
379 for pat in pats {
380 self.check_pat(pat, expected, pat_info);
381 }
382 expected
383 }
384 PatKind::Tuple(elements, ddpos) => {
385 self.check_pat_tuple(pat.span, elements, ddpos, expected, pat_info)
386 }
387 PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info),
388 PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info),
389 PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info),
390 PatKind::Slice(before, slice, after) => {
391 self.check_pat_slice(pat.span, before, slice, after, expected, pat_info)
392 }
393 };
394
395 self.write_ty(pat.hir_id, ty);
396
397 }
439
440 fn calc_default_binding_mode(
443 &self,
444 pat: &'tcx Pat<'tcx>,
445 expected: Ty<'tcx>,
446 def_br: ByRef,
447 adjust_mode: AdjustMode,
448 max_ref_mutbl: MutblCap,
449 ) -> (Ty<'tcx>, ByRef, MutblCap) {
450 #[cfg(debug_assertions)]
451 if def_br == ByRef::Yes(Mutability::Mut)
452 && max_ref_mutbl != MutblCap::Mut
453 && self.downgrade_mut_inside_shared()
454 {
455 span_bug!(pat.span, "Pattern mutability cap violated!");
456 }
457 match adjust_mode {
458 AdjustMode::Pass => (expected, def_br, max_ref_mutbl),
459 AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut),
460 AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl),
461 }
462 }
463
464 fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> AdjustMode {
468 if !pat.default_binding_modes {
471 return AdjustMode::Reset;
472 }
473 match &pat.kind {
474 PatKind::Struct(..)
477 | PatKind::TupleStruct(..)
478 | PatKind::Tuple(..)
479 | PatKind::Box(_)
480 | PatKind::Deref(_)
481 | PatKind::Range(..)
482 | PatKind::Slice(..) => AdjustMode::Peel,
483 PatKind::Never => AdjustMode::Peel,
485 PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => match opt_path_res.unwrap() {
486 Res::Def(DefKind::Const | DefKind::AssocConst, _) => AdjustMode::Pass,
490 _ => AdjustMode::Peel,
495 },
496
497 PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() {
503 ty::Ref(..) => AdjustMode::Pass,
504 _ => AdjustMode::Peel,
505 },
506
507 PatKind::Ref(..) => AdjustMode::Pass,
509 PatKind::Wild
511 | PatKind::Err(_)
513 | PatKind::Binding(..)
518 | PatKind::Or(_)
522 | PatKind::Guard(..) => AdjustMode::Pass,
524 }
525 }
526
527 fn peel_off_references(
531 &self,
532 pat: &'tcx Pat<'tcx>,
533 expected: Ty<'tcx>,
534 mut def_br: ByRef,
535 mut max_ref_mutbl: MutblCap,
536 ) -> (Ty<'tcx>, ByRef, MutblCap) {
537 let mut expected = self.try_structurally_resolve_type(pat.span, expected);
538 let mut pat_adjustments = vec![];
547 while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
548 debug!("inspecting {:?}", expected);
549
550 debug!("current discriminant is Ref, inserting implicit deref");
551 pat_adjustments.push(expected);
553
554 expected = self.try_structurally_resolve_type(pat.span, inner_ty);
555 def_br = ByRef::Yes(match def_br {
556 ByRef::No |
559 ByRef::Yes(Mutability::Mut) => inner_mutability,
561 ByRef::Yes(Mutability::Not) => Mutability::Not,
564 });
565 }
566
567 if self.downgrade_mut_inside_shared() {
568 def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl());
569 }
570 if def_br == ByRef::Yes(Mutability::Not) {
571 max_ref_mutbl = MutblCap::Not;
572 }
573
574 if !pat_adjustments.is_empty() {
575 debug!("default binding mode is now {:?}", def_br);
576 self.typeck_results
577 .borrow_mut()
578 .pat_adjustments_mut()
579 .insert(pat.hir_id, pat_adjustments);
580 }
581
582 (expected, def_br, max_ref_mutbl)
583 }
584
585 fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
586 let ty = match <.kind {
587 rustc_hir::PatExprKind::Lit { lit, negated } => {
588 let ty = self.check_expr_lit(lit, Expectation::NoExpectation);
589 if *negated {
590 self.register_bound(
591 ty,
592 self.tcx.require_lang_item(LangItem::Neg, Some(lt.span)),
593 ObligationCause::dummy_with_span(lt.span),
594 );
595 }
596 ty
597 }
598 rustc_hir::PatExprKind::ConstBlock(c) => {
599 self.check_expr_const_block(c, Expectation::NoExpectation)
600 }
601 rustc_hir::PatExprKind::Path(qpath) => {
602 let (res, opt_ty, segments) =
603 self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span);
604 self.instantiate_value_path(segments, opt_ty, res, lt.span, lt.span, lt.hir_id).0
605 }
606 };
607 self.write_ty(lt.hir_id, ty);
608 ty
609 }
610
611 fn check_pat_lit(
612 &self,
613 span: Span,
614 lt: &hir::PatExpr<'tcx>,
615 expected: Ty<'tcx>,
616 ti: &TopInfo<'tcx>,
617 ) -> Ty<'tcx> {
618 let ty = self.node_ty(lt.hir_id);
621
622 let mut pat_ty = ty;
625 if let hir::PatExprKind::Lit {
626 lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, ..
627 } = lt.kind
628 {
629 let expected = self.structurally_resolve_type(span, expected);
630 if let ty::Ref(_, inner_ty, _) = *expected.kind()
631 && self.try_structurally_resolve_type(span, inner_ty).is_slice()
632 {
633 let tcx = self.tcx;
634 trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
635 self.typeck_results
636 .borrow_mut()
637 .treat_byte_string_as_slice
638 .insert(lt.hir_id.local_id);
639 pat_ty =
640 Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8));
641 }
642 }
643
644 if self.tcx.features().string_deref_patterns()
645 && let hir::PatExprKind::Lit {
646 lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
647 } = lt.kind
648 {
649 let tcx = self.tcx;
650 let expected = self.resolve_vars_if_possible(expected);
651 pat_ty = match expected.kind() {
652 ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => expected,
653 ty::Str => Ty::new_static_str(tcx),
654 _ => pat_ty,
655 };
656 }
657
658 let cause = self.pattern_cause(ti, span);
669 if let Err(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
670 err.emit_unless(
671 ti.span
672 .filter(|&s| {
673 s.is_desugaring(DesugaringKind::CondTemporary)
677 })
678 .is_some(),
679 );
680 }
681
682 pat_ty
683 }
684
685 fn check_pat_range(
686 &self,
687 span: Span,
688 lhs: Option<&'tcx hir::PatExpr<'tcx>>,
689 rhs: Option<&'tcx hir::PatExpr<'tcx>>,
690 expected: Ty<'tcx>,
691 ti: &TopInfo<'tcx>,
692 ) -> Ty<'tcx> {
693 let calc_side = |opt_expr: Option<&'tcx hir::PatExpr<'tcx>>| match opt_expr {
694 None => None,
695 Some(expr) => {
696 let ty = self.check_pat_expr_unadjusted(expr);
697 let fail =
704 !(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error());
705 Some((fail, ty, expr.span))
706 }
707 };
708 let mut lhs = calc_side(lhs);
709 let mut rhs = calc_side(rhs);
710
711 if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
712 let guar = self.emit_err_pat_range(span, lhs, rhs);
715 return Ty::new_error(self.tcx, guar);
716 }
717
718 let demand_eqtype = |x: &mut _, y| {
721 if let Some((ref mut fail, x_ty, x_span)) = *x
722 && let Err(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
723 {
724 if let Some((_, y_ty, y_span)) = y {
725 self.endpoint_has_type(&mut err, y_span, y_ty);
726 }
727 err.emit();
728 *fail = true;
729 }
730 };
731 demand_eqtype(&mut lhs, rhs);
732 demand_eqtype(&mut rhs, lhs);
733
734 if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
735 return Ty::new_misc_error(self.tcx);
736 }
737
738 let ty = self.structurally_resolve_type(span, expected);
743 if !(ty.is_numeric() || ty.is_char() || ty.references_error()) {
744 if let Some((ref mut fail, _, _)) = lhs {
745 *fail = true;
746 }
747 if let Some((ref mut fail, _, _)) = rhs {
748 *fail = true;
749 }
750 let guar = self.emit_err_pat_range(span, lhs, rhs);
751 return Ty::new_error(self.tcx, guar);
752 }
753 ty
754 }
755
756 fn endpoint_has_type(&self, err: &mut Diag<'_>, span: Span, ty: Ty<'_>) {
757 if !ty.references_error() {
758 err.span_label(span, format!("this is of type `{ty}`"));
759 }
760 }
761
762 fn emit_err_pat_range(
763 &self,
764 span: Span,
765 lhs: Option<(bool, Ty<'tcx>, Span)>,
766 rhs: Option<(bool, Ty<'tcx>, Span)>,
767 ) -> ErrorGuaranteed {
768 let span = match (lhs, rhs) {
769 (Some((true, ..)), Some((true, ..))) => span,
770 (Some((true, _, sp)), _) => sp,
771 (_, Some((true, _, sp))) => sp,
772 _ => span_bug!(span, "emit_err_pat_range: no side failed or exists but still error?"),
773 };
774 let mut err = struct_span_code_err!(
775 self.dcx(),
776 span,
777 E0029,
778 "only `char` and numeric types are allowed in range patterns"
779 );
780 let msg = |ty| {
781 let ty = self.resolve_vars_if_possible(ty);
782 format!("this is of type `{ty}` but it should be `char` or numeric")
783 };
784 let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| {
785 err.span_label(first_span, msg(first_ty));
786 if let Some((_, ty, sp)) = second {
787 let ty = self.resolve_vars_if_possible(ty);
788 self.endpoint_has_type(&mut err, sp, ty);
789 }
790 };
791 match (lhs, rhs) {
792 (Some((true, lhs_ty, lhs_sp)), Some((true, rhs_ty, rhs_sp))) => {
793 err.span_label(lhs_sp, msg(lhs_ty));
794 err.span_label(rhs_sp, msg(rhs_ty));
795 }
796 (Some((true, lhs_ty, lhs_sp)), rhs) => one_side_err(lhs_sp, lhs_ty, rhs),
797 (lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs),
798 _ => span_bug!(span, "Impossible, verified above."),
799 }
800 if (lhs, rhs).references_error() {
801 err.downgrade_to_delayed_bug();
802 }
803 if self.tcx.sess.teach(err.code.unwrap()) {
804 err.note(
805 "In a match expression, only numbers and characters can be matched \
806 against a range. This is because the compiler checks that the range \
807 is non-empty at compile-time, and is unable to evaluate arbitrary \
808 comparison functions. If you want to capture values of an orderable \
809 type between two end-points, you can use a guard.",
810 );
811 }
812 err.emit()
813 }
814
815 fn check_pat_ident(
816 &self,
817 pat: &'tcx Pat<'tcx>,
818 user_bind_annot: BindingMode,
819 var_id: HirId,
820 ident: Ident,
821 sub: Option<&'tcx Pat<'tcx>>,
822 expected: Ty<'tcx>,
823 pat_info: PatInfo<'tcx>,
824 ) -> Ty<'tcx> {
825 let PatInfo { binding_mode: def_br, top_info: ti, .. } = pat_info;
826
827 let bm = match user_bind_annot {
829 BindingMode(ByRef::No, Mutability::Mut) if let ByRef::Yes(def_br_mutbl) = def_br => {
830 if pat.span.at_least_rust_2024()
833 && (self.tcx.features().ref_pat_eat_one_layer_2024()
834 || self.tcx.features().ref_pat_eat_one_layer_2024_structural())
835 {
836 if !self.tcx.features().mut_ref() {
837 feature_err(
838 &self.tcx.sess,
839 sym::mut_ref,
840 pat.span.until(ident.span),
841 "binding cannot be both mutable and by-reference",
842 )
843 .emit();
844 }
845
846 BindingMode(def_br, Mutability::Mut)
847 } else {
848 self.add_rust_2024_migration_desugared_pat(
850 pat_info.top_info.hir_id,
851 pat,
852 't', def_br_mutbl,
854 );
855 BindingMode(ByRef::No, Mutability::Mut)
856 }
857 }
858 BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
859 BindingMode(ByRef::Yes(user_br_mutbl), _) => {
860 if let ByRef::Yes(def_br_mutbl) = def_br {
861 self.add_rust_2024_migration_desugared_pat(
863 pat_info.top_info.hir_id,
864 pat,
865 match user_br_mutbl {
866 Mutability::Not => 'f', Mutability::Mut => 't', },
869 def_br_mutbl,
870 );
871 }
872 user_bind_annot
873 }
874 };
875
876 if bm.0 == ByRef::Yes(Mutability::Mut)
877 && let MutblCap::WeaklyNot(and_pat_span) = pat_info.max_ref_mutbl
878 {
879 let mut err = struct_span_code_err!(
880 self.dcx(),
881 ident.span,
882 E0596,
883 "cannot borrow as mutable inside an `&` pattern"
884 );
885
886 if let Some(span) = and_pat_span {
887 err.span_suggestion(
888 span,
889 "replace this `&` with `&mut`",
890 "&mut ",
891 Applicability::MachineApplicable,
892 );
893 }
894 err.emit();
895 }
896
897 self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
899
900 debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
901
902 let local_ty = self.local_ty(pat.span, pat.hir_id);
903 let eq_ty = match bm.0 {
904 ByRef::Yes(mutbl) => {
905 self.new_ref_ty(pat.span, mutbl, expected)
913 }
914 ByRef::No => expected, };
917
918 let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, &ti);
920
921 if var_id != pat.hir_id {
924 self.check_binding_alt_eq_ty(user_bind_annot, pat.span, var_id, local_ty, &ti);
925 }
926
927 if let Some(p) = sub {
928 self.check_pat(p, expected, pat_info);
929 }
930
931 local_ty
932 }
933
934 fn check_binding_alt_eq_ty(
938 &self,
939 ba: BindingMode,
940 span: Span,
941 var_id: HirId,
942 ty: Ty<'tcx>,
943 ti: &TopInfo<'tcx>,
944 ) {
945 let var_ty = self.local_ty(span, var_id);
946 if let Err(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
947 let hir = self.tcx.hir();
948 let var_ty = self.resolve_vars_if_possible(var_ty);
949 let msg = format!("first introduced with type `{var_ty}` here");
950 err.span_label(hir.span(var_id), msg);
951 let in_match = self.tcx.hir_parent_iter(var_id).any(|(_, n)| {
952 matches!(
953 n,
954 hir::Node::Expr(hir::Expr {
955 kind: hir::ExprKind::Match(.., hir::MatchSource::Normal),
956 ..
957 })
958 )
959 });
960 let pre = if in_match { "in the same arm, " } else { "" };
961 err.note(format!("{pre}a binding must have the same type in all alternatives"));
962 self.suggest_adding_missing_ref_or_removing_ref(
963 &mut err,
964 span,
965 var_ty,
966 self.resolve_vars_if_possible(ty),
967 ba,
968 );
969 err.emit();
970 }
971 }
972
973 fn suggest_adding_missing_ref_or_removing_ref(
974 &self,
975 err: &mut Diag<'_>,
976 span: Span,
977 expected: Ty<'tcx>,
978 actual: Ty<'tcx>,
979 ba: BindingMode,
980 ) {
981 match (expected.kind(), actual.kind(), ba) {
982 (ty::Ref(_, inner_ty, _), _, BindingMode::NONE)
983 if self.can_eq(self.param_env, *inner_ty, actual) =>
984 {
985 err.span_suggestion_verbose(
986 span.shrink_to_lo(),
987 "consider adding `ref`",
988 "ref ",
989 Applicability::MaybeIncorrect,
990 );
991 }
992 (_, ty::Ref(_, inner_ty, _), BindingMode::REF)
993 if self.can_eq(self.param_env, expected, *inner_ty) =>
994 {
995 err.span_suggestion_verbose(
996 span.with_hi(span.lo() + BytePos(4)),
997 "consider removing `ref`",
998 "",
999 Applicability::MaybeIncorrect,
1000 );
1001 }
1002 _ => (),
1003 }
1004 }
1005
1006 fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) {
1008 let tcx = self.tcx;
1009 if let PatKind::Ref(inner, mutbl) = pat.kind
1010 && let PatKind::Binding(_, _, binding, ..) = inner.kind
1011 {
1012 let binding_parent = tcx.parent_hir_node(pat.hir_id);
1013 debug!(?inner, ?pat, ?binding_parent);
1014
1015 let mutability = match mutbl {
1016 ast::Mutability::Mut => "mut",
1017 ast::Mutability::Not => "",
1018 };
1019
1020 let mut_var_suggestion = 'block: {
1021 if mutbl.is_not() {
1022 break 'block None;
1023 }
1024
1025 let ident_kind = match binding_parent {
1026 hir::Node::Param(_) => "parameter",
1027 hir::Node::LetStmt(_) => "variable",
1028 hir::Node::Arm(_) => "binding",
1029
1030 hir::Node::Pat(Pat { kind, .. }) => match kind {
1033 PatKind::Struct(..)
1034 | PatKind::TupleStruct(..)
1035 | PatKind::Or(..)
1036 | PatKind::Guard(..)
1037 | PatKind::Tuple(..)
1038 | PatKind::Slice(..) => "binding",
1039
1040 PatKind::Wild
1041 | PatKind::Never
1042 | PatKind::Binding(..)
1043 | PatKind::Box(..)
1044 | PatKind::Deref(_)
1045 | PatKind::Ref(..)
1046 | PatKind::Expr(..)
1047 | PatKind::Range(..)
1048 | PatKind::Err(_) => break 'block None,
1049 },
1050
1051 _ => break 'block None,
1053 };
1054
1055 Some((
1056 pat.span,
1057 format!("to declare a mutable {ident_kind} use"),
1058 format!("mut {binding}"),
1059 ))
1060 };
1061
1062 match binding_parent {
1063 hir::Node::Param(hir::Param { ty_span, pat, .. }) if pat.span != *ty_span => {
1066 err.multipart_suggestion_verbose(
1067 format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"),
1068 vec![
1069 (pat.span.until(inner.span), "".to_owned()),
1070 (ty_span.shrink_to_lo(), mutbl.ref_prefix_str().to_owned()),
1071 ],
1072 Applicability::MachineApplicable
1073 );
1074
1075 if let Some((sp, msg, sugg)) = mut_var_suggestion {
1076 err.span_note(sp, format!("{msg}: `{sugg}`"));
1077 }
1078 }
1079 hir::Node::Pat(pt) if let PatKind::TupleStruct(_, pat_arr, _) = pt.kind => {
1080 for i in pat_arr.iter() {
1081 if let PatKind::Ref(the_ref, _) = i.kind
1082 && let PatKind::Binding(mt, _, ident, _) = the_ref.kind
1083 {
1084 let BindingMode(_, mtblty) = mt;
1085 err.span_suggestion_verbose(
1086 i.span,
1087 format!("consider removing `&{mutability}` from the pattern"),
1088 mtblty.prefix_str().to_string() + &ident.name.to_string(),
1089 Applicability::MaybeIncorrect,
1090 );
1091 }
1092 }
1093 if let Some((sp, msg, sugg)) = mut_var_suggestion {
1094 err.span_note(sp, format!("{msg}: `{sugg}`"));
1095 }
1096 }
1097 hir::Node::Param(_) | hir::Node::Arm(_) | hir::Node::Pat(_) => {
1098 err.span_suggestion_verbose(
1100 pat.span.until(inner.span),
1101 format!("consider removing `&{mutability}` from the pattern"),
1102 "",
1103 Applicability::MaybeIncorrect,
1104 );
1105
1106 if let Some((sp, msg, sugg)) = mut_var_suggestion {
1107 err.span_note(sp, format!("{msg}: `{sugg}`"));
1108 }
1109 }
1110 _ if let Some((sp, msg, sugg)) = mut_var_suggestion => {
1111 err.span_suggestion(sp, msg, sugg, Applicability::MachineApplicable);
1112 }
1113 _ => {} }
1115 }
1116 }
1117
1118 fn check_dereferenceable(
1119 &self,
1120 span: Span,
1121 expected: Ty<'tcx>,
1122 inner: &Pat<'_>,
1123 ) -> Result<(), ErrorGuaranteed> {
1124 if let PatKind::Binding(..) = inner.kind
1125 && let Some(pointee_ty) = self.shallow_resolve(expected).builtin_deref(true)
1126 && let ty::Dynamic(..) = pointee_ty.kind()
1127 {
1128 let type_str = self.ty_to_string(expected);
1131 let mut err = struct_span_code_err!(
1132 self.dcx(),
1133 span,
1134 E0033,
1135 "type `{}` cannot be dereferenced",
1136 type_str
1137 );
1138 err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
1139 if self.tcx.sess.teach(err.code.unwrap()) {
1140 err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
1141 }
1142 return Err(err.emit());
1143 }
1144 Ok(())
1145 }
1146
1147 fn check_pat_struct(
1148 &self,
1149 pat: &'tcx Pat<'tcx>,
1150 qpath: &hir::QPath<'tcx>,
1151 fields: &'tcx [hir::PatField<'tcx>],
1152 has_rest_pat: bool,
1153 expected: Ty<'tcx>,
1154 pat_info: PatInfo<'tcx>,
1155 ) -> Ty<'tcx> {
1156 let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) {
1158 Ok(data) => data,
1159 Err(guar) => {
1160 let err = Ty::new_error(self.tcx, guar);
1161 for field in fields {
1162 self.check_pat(field.pat, err, pat_info);
1163 }
1164 return err;
1165 }
1166 };
1167
1168 let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
1170
1171 match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
1173 Ok(()) => pat_ty,
1174 Err(guar) => Ty::new_error(self.tcx, guar),
1175 }
1176 }
1177
1178 fn check_pat_path(
1179 &self,
1180 path_id: HirId,
1181 pat_id_for_diag: HirId,
1182 span: Span,
1183 qpath: &hir::QPath<'_>,
1184 path_resolution: (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
1185 expected: Ty<'tcx>,
1186 ti: &TopInfo<'tcx>,
1187 ) -> Ty<'tcx> {
1188 let tcx = self.tcx;
1189
1190 let (res, opt_ty, segments) = path_resolution;
1192 match res {
1193 Res::Err => {
1194 let e =
1195 self.dcx().span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted");
1196 self.set_tainted_by_errors(e);
1197 return Ty::new_error(tcx, e);
1198 }
1199 Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
1200 let expected = "unit struct, unit variant or constant";
1201 let e = report_unexpected_variant_res(tcx, res, None, qpath, span, E0533, expected);
1202 return Ty::new_error(tcx, e);
1203 }
1204 Res::SelfCtor(def_id) => {
1205 if let ty::Adt(adt_def, _) = *tcx.type_of(def_id).skip_binder().kind()
1206 && adt_def.is_struct()
1207 && let Some((CtorKind::Const, _)) = adt_def.non_enum_variant().ctor
1208 {
1209 } else {
1211 let e = report_unexpected_variant_res(
1212 tcx,
1213 res,
1214 None,
1215 qpath,
1216 span,
1217 E0533,
1218 "unit struct",
1219 );
1220 return Ty::new_error(tcx, e);
1221 }
1222 }
1223 Res::Def(
1224 DefKind::Ctor(_, CtorKind::Const)
1225 | DefKind::Const
1226 | DefKind::AssocConst
1227 | DefKind::ConstParam,
1228 _,
1229 ) => {} _ => bug!("unexpected pattern resolution: {:?}", res),
1231 }
1232
1233 let (pat_ty, pat_res) =
1235 self.instantiate_value_path(segments, opt_ty, res, span, span, path_id);
1236 if let Err(err) =
1237 self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, pat_ty)
1238 {
1239 self.emit_bad_pat_path(err, pat_id_for_diag, span, res, pat_res, pat_ty, segments);
1240 }
1241 pat_ty
1242 }
1243
1244 fn maybe_suggest_range_literal(
1245 &self,
1246 e: &mut Diag<'_>,
1247 opt_def_id: Option<hir::def_id::DefId>,
1248 ident: Ident,
1249 ) -> bool {
1250 match opt_def_id {
1251 Some(def_id) => match self.tcx.hir_get_if_local(def_id) {
1252 Some(hir::Node::Item(hir::Item {
1253 kind: hir::ItemKind::Const(_, _, _, body_id),
1254 ..
1255 })) => match self.tcx.hir_node(body_id.hir_id) {
1256 hir::Node::Expr(expr) => {
1257 if hir::is_range_literal(expr) {
1258 let span = self.tcx.hir().span(body_id.hir_id);
1259 if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) {
1260 e.span_suggestion_verbose(
1261 ident.span,
1262 "you may want to move the range into the match block",
1263 snip,
1264 Applicability::MachineApplicable,
1265 );
1266 return true;
1267 }
1268 }
1269 }
1270 _ => (),
1271 },
1272 _ => (),
1273 },
1274 _ => (),
1275 }
1276 false
1277 }
1278
1279 fn emit_bad_pat_path(
1280 &self,
1281 mut e: Diag<'_>,
1282 hir_id: HirId,
1283 pat_span: Span,
1284 res: Res,
1285 pat_res: Res,
1286 pat_ty: Ty<'tcx>,
1287 segments: &'tcx [hir::PathSegment<'tcx>],
1288 ) {
1289 if let Some(span) = self.tcx.hir().res_span(pat_res) {
1290 e.span_label(span, format!("{} defined here", res.descr()));
1291 if let [hir::PathSegment { ident, .. }] = &*segments {
1292 e.span_label(
1293 pat_span,
1294 format!(
1295 "`{}` is interpreted as {} {}, not a new binding",
1296 ident,
1297 res.article(),
1298 res.descr(),
1299 ),
1300 );
1301 match self.tcx.parent_hir_node(hir_id) {
1302 hir::Node::PatField(..) => {
1303 e.span_suggestion_verbose(
1304 ident.span.shrink_to_hi(),
1305 "bind the struct field to a different name instead",
1306 format!(": other_{}", ident.as_str().to_lowercase()),
1307 Applicability::HasPlaceholders,
1308 );
1309 }
1310 _ => {
1311 let (type_def_id, item_def_id) = match pat_ty.kind() {
1312 ty::Adt(def, _) => match res {
1313 Res::Def(DefKind::Const, def_id) => (Some(def.did()), Some(def_id)),
1314 _ => (None, None),
1315 },
1316 _ => (None, None),
1317 };
1318
1319 let ranges = &[
1320 self.tcx.lang_items().range_struct(),
1321 self.tcx.lang_items().range_from_struct(),
1322 self.tcx.lang_items().range_to_struct(),
1323 self.tcx.lang_items().range_full_struct(),
1324 self.tcx.lang_items().range_inclusive_struct(),
1325 self.tcx.lang_items().range_to_inclusive_struct(),
1326 ];
1327 if type_def_id != None && ranges.contains(&type_def_id) {
1328 if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
1329 let msg = "constants only support matching by type, \
1330 if you meant to match against a range of values, \
1331 consider using a range pattern like `min ..= max` in the match block";
1332 e.note(msg);
1333 }
1334 } else {
1335 let msg = "introduce a new binding instead";
1336 let sugg = format!("other_{}", ident.as_str().to_lowercase());
1337 e.span_suggestion(
1338 ident.span,
1339 msg,
1340 sugg,
1341 Applicability::HasPlaceholders,
1342 );
1343 }
1344 }
1345 };
1346 }
1347 }
1348 e.emit();
1349 }
1350
1351 fn check_pat_tuple_struct(
1352 &self,
1353 pat: &'tcx Pat<'tcx>,
1354 qpath: &'tcx hir::QPath<'tcx>,
1355 subpats: &'tcx [Pat<'tcx>],
1356 ddpos: hir::DotDotPos,
1357 expected: Ty<'tcx>,
1358 pat_info: PatInfo<'tcx>,
1359 ) -> Ty<'tcx> {
1360 let tcx = self.tcx;
1361 let on_error = |e| {
1362 for pat in subpats {
1363 self.check_pat(pat, Ty::new_error(tcx, e), pat_info);
1364 }
1365 };
1366 let report_unexpected_res = |res: Res| {
1367 let expected = "tuple struct or tuple variant";
1368 let e = report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected);
1369 on_error(e);
1370 e
1371 };
1372
1373 let (res, opt_ty, segments) =
1375 self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
1376 if res == Res::Err {
1377 let e = self.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
1378 self.set_tainted_by_errors(e);
1379 on_error(e);
1380 return Ty::new_error(tcx, e);
1381 }
1382
1383 let (pat_ty, res) =
1385 self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
1386 if !pat_ty.is_fn() {
1387 let e = report_unexpected_res(res);
1388 return Ty::new_error(tcx, e);
1389 }
1390
1391 let variant = match res {
1392 Res::Err => {
1393 self.dcx().span_bug(pat.span, "`Res::Err` but no error emitted");
1394 }
1395 Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
1396 let e = report_unexpected_res(res);
1397 return Ty::new_error(tcx, e);
1398 }
1399 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
1400 _ => bug!("unexpected pattern resolution: {:?}", res),
1401 };
1402
1403 let pat_ty = pat_ty.fn_sig(tcx).output();
1405 let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1406
1407 let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info);
1409 let had_err = diag.map_err(|diag| diag.emit());
1410
1411 if subpats.len() == variant.fields.len()
1413 || subpats.len() < variant.fields.len() && ddpos.as_opt_usize().is_some()
1414 {
1415 let ty::Adt(_, args) = pat_ty.kind() else {
1416 bug!("unexpected pattern type {:?}", pat_ty);
1417 };
1418 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
1419 let field = &variant.fields[FieldIdx::from_usize(i)];
1420 let field_ty = self.field_ty(subpat.span, field, args);
1421 self.check_pat(subpat, field_ty, pat_info);
1422
1423 self.tcx.check_stability(
1424 variant.fields[FieldIdx::from_usize(i)].did,
1425 Some(subpat.hir_id),
1426 subpat.span,
1427 None,
1428 );
1429 }
1430 if let Err(e) = had_err {
1431 on_error(e);
1432 return Ty::new_error(tcx, e);
1433 }
1434 } else {
1435 let e = self.emit_err_pat_wrong_number_of_fields(
1436 pat.span,
1437 res,
1438 qpath,
1439 subpats,
1440 &variant.fields.raw,
1441 expected,
1442 had_err,
1443 );
1444 on_error(e);
1445 return Ty::new_error(tcx, e);
1446 }
1447 pat_ty
1448 }
1449
1450 fn emit_err_pat_wrong_number_of_fields(
1451 &self,
1452 pat_span: Span,
1453 res: Res,
1454 qpath: &hir::QPath<'_>,
1455 subpats: &'tcx [Pat<'tcx>],
1456 fields: &'tcx [ty::FieldDef],
1457 expected: Ty<'tcx>,
1458 had_err: Result<(), ErrorGuaranteed>,
1459 ) -> ErrorGuaranteed {
1460 let subpats_ending = pluralize!(subpats.len());
1461 let fields_ending = pluralize!(fields.len());
1462
1463 let subpat_spans = if subpats.is_empty() {
1464 vec![pat_span]
1465 } else {
1466 subpats.iter().map(|p| p.span).collect()
1467 };
1468 let last_subpat_span = *subpat_spans.last().unwrap();
1469 let res_span = self.tcx.def_span(res.def_id());
1470 let def_ident_span = self.tcx.def_ident_span(res.def_id()).unwrap_or(res_span);
1471 let field_def_spans = if fields.is_empty() {
1472 vec![res_span]
1473 } else {
1474 fields.iter().map(|f| f.ident(self.tcx).span).collect()
1475 };
1476 let last_field_def_span = *field_def_spans.last().unwrap();
1477
1478 let mut err = struct_span_code_err!(
1479 self.dcx(),
1480 MultiSpan::from_spans(subpat_spans),
1481 E0023,
1482 "this pattern has {} field{}, but the corresponding {} has {} field{}",
1483 subpats.len(),
1484 subpats_ending,
1485 res.descr(),
1486 fields.len(),
1487 fields_ending,
1488 );
1489 err.span_label(
1490 last_subpat_span,
1491 format!("expected {} field{}, found {}", fields.len(), fields_ending, subpats.len()),
1492 );
1493 if self.tcx.sess.source_map().is_multiline(qpath.span().between(last_subpat_span)) {
1494 err.span_label(qpath.span(), "");
1495 }
1496 if self.tcx.sess.source_map().is_multiline(def_ident_span.between(last_field_def_span)) {
1497 err.span_label(def_ident_span, format!("{} defined here", res.descr()));
1498 }
1499 for span in &field_def_spans[..field_def_spans.len() - 1] {
1500 err.span_label(*span, "");
1501 }
1502 err.span_label(
1503 last_field_def_span,
1504 format!("{} has {} field{}", res.descr(), fields.len(), fields_ending),
1505 );
1506
1507 let missing_parentheses = match (expected.kind(), fields, had_err) {
1512 (ty::Adt(_, args), [field], Ok(())) => {
1516 let field_ty = self.field_ty(pat_span, field, args);
1517 match field_ty.kind() {
1518 ty::Tuple(fields) => fields.len() == subpats.len(),
1519 _ => false,
1520 }
1521 }
1522 _ => false,
1523 };
1524 if missing_parentheses {
1525 let (left, right) = match subpats {
1526 [] => (qpath.span().shrink_to_hi(), pat_span),
1535 [first, ..] => (first.span.shrink_to_lo(), subpats.last().unwrap().span),
1544 };
1545 err.multipart_suggestion(
1546 "missing parentheses",
1547 vec![(left, "(".to_string()), (right.shrink_to_hi(), ")".to_string())],
1548 Applicability::MachineApplicable,
1549 );
1550 } else if fields.len() > subpats.len() && pat_span != DUMMY_SP {
1551 let after_fields_span = pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi();
1552 let all_fields_span = match subpats {
1553 [] => after_fields_span,
1554 [field] => field.span,
1555 [first, .., last] => first.span.to(last.span),
1556 };
1557
1558 let all_wildcards = subpats.iter().all(|pat| matches!(pat.kind, PatKind::Wild));
1560 let first_tail_wildcard =
1561 subpats.iter().enumerate().fold(None, |acc, (pos, pat)| match (acc, &pat.kind) {
1562 (None, PatKind::Wild) => Some(pos),
1563 (Some(_), PatKind::Wild) => acc,
1564 _ => None,
1565 });
1566 let tail_span = match first_tail_wildcard {
1567 None => after_fields_span,
1568 Some(0) => subpats[0].span.to(after_fields_span),
1569 Some(pos) => subpats[pos - 1].span.shrink_to_hi().to(after_fields_span),
1570 };
1571
1572 let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", ");
1574 if !subpats.is_empty() {
1575 wildcard_sugg = String::from(", ") + &wildcard_sugg;
1576 }
1577
1578 err.span_suggestion_verbose(
1579 after_fields_span,
1580 "use `_` to explicitly ignore each field",
1581 wildcard_sugg,
1582 Applicability::MaybeIncorrect,
1583 );
1584
1585 if fields.len() - subpats.len() > 1 || all_wildcards {
1588 if subpats.is_empty() || all_wildcards {
1589 err.span_suggestion_verbose(
1590 all_fields_span,
1591 "use `..` to ignore all fields",
1592 "..",
1593 Applicability::MaybeIncorrect,
1594 );
1595 } else {
1596 err.span_suggestion_verbose(
1597 tail_span,
1598 "use `..` to ignore the rest of the fields",
1599 ", ..",
1600 Applicability::MaybeIncorrect,
1601 );
1602 }
1603 }
1604 }
1605
1606 err.emit()
1607 }
1608
1609 fn check_pat_tuple(
1610 &self,
1611 span: Span,
1612 elements: &'tcx [Pat<'tcx>],
1613 ddpos: hir::DotDotPos,
1614 expected: Ty<'tcx>,
1615 pat_info: PatInfo<'tcx>,
1616 ) -> Ty<'tcx> {
1617 let tcx = self.tcx;
1618 let mut expected_len = elements.len();
1619 if ddpos.as_opt_usize().is_some() {
1620 if let ty::Tuple(tys) = self.structurally_resolve_type(span, expected).kind() {
1622 expected_len = tys.len();
1623 }
1624 }
1625 let max_len = cmp::max(expected_len, elements.len());
1626
1627 let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(span));
1628 let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
1629 let pat_ty = Ty::new_tup(tcx, element_tys);
1630 if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, &pat_info.top_info) {
1631 let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
1634 for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
1635 self.check_pat(elem, Ty::new_error(tcx, reported), pat_info);
1636 }
1637 Ty::new_tup_from_iter(tcx, element_tys_iter)
1638 } else {
1639 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
1640 self.check_pat(elem, element_tys[i], pat_info);
1641 }
1642 pat_ty
1643 }
1644 }
1645
1646 fn check_struct_pat_fields(
1647 &self,
1648 adt_ty: Ty<'tcx>,
1649 pat: &'tcx Pat<'tcx>,
1650 variant: &'tcx ty::VariantDef,
1651 fields: &'tcx [hir::PatField<'tcx>],
1652 has_rest_pat: bool,
1653 pat_info: PatInfo<'tcx>,
1654 ) -> Result<(), ErrorGuaranteed> {
1655 let tcx = self.tcx;
1656
1657 let ty::Adt(adt, args) = adt_ty.kind() else {
1658 span_bug!(pat.span, "struct pattern is not an ADT");
1659 };
1660
1661 let field_map = variant
1663 .fields
1664 .iter_enumerated()
1665 .map(|(i, field)| (field.ident(self.tcx).normalize_to_macros_2_0(), (i, field)))
1666 .collect::<FxHashMap<_, _>>();
1667
1668 let mut used_fields = FxHashMap::default();
1670 let mut result = Ok(());
1671
1672 let mut inexistent_fields = vec![];
1673 for field in fields {
1675 let span = field.span;
1676 let ident = tcx.adjust_ident(field.ident, variant.def_id);
1677 let field_ty = match used_fields.entry(ident) {
1678 Occupied(occupied) => {
1679 let guar = self.error_field_already_bound(span, field.ident, *occupied.get());
1680 result = Err(guar);
1681 Ty::new_error(tcx, guar)
1682 }
1683 Vacant(vacant) => {
1684 vacant.insert(span);
1685 field_map
1686 .get(&ident)
1687 .map(|(i, f)| {
1688 self.write_field_index(field.hir_id, *i);
1689 self.tcx.check_stability(f.did, Some(field.hir_id), span, None);
1690 self.field_ty(span, f, args)
1691 })
1692 .unwrap_or_else(|| {
1693 inexistent_fields.push(field);
1694 Ty::new_misc_error(tcx)
1695 })
1696 }
1697 };
1698
1699 self.check_pat(field.pat, field_ty, pat_info);
1700 }
1701
1702 let mut unmentioned_fields = variant
1703 .fields
1704 .iter()
1705 .map(|field| (field, field.ident(self.tcx).normalize_to_macros_2_0()))
1706 .filter(|(_, ident)| !used_fields.contains_key(ident))
1707 .collect::<Vec<_>>();
1708
1709 let inexistent_fields_err = if !inexistent_fields.is_empty()
1710 && !inexistent_fields.iter().any(|field| field.ident.name == kw::Underscore)
1711 {
1712 variant.has_errors()?;
1714 Some(self.error_inexistent_fields(
1715 adt.variant_descr(),
1716 &inexistent_fields,
1717 &mut unmentioned_fields,
1718 pat,
1719 variant,
1720 args,
1721 ))
1722 } else {
1723 None
1724 };
1725
1726 let non_exhaustive = variant.field_list_has_applicable_non_exhaustive();
1728 if non_exhaustive && !has_rest_pat {
1729 self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty());
1730 }
1731
1732 let mut unmentioned_err = None;
1733 if adt.is_union() {
1735 if fields.len() != 1 {
1736 self.dcx().emit_err(errors::UnionPatMultipleFields { span: pat.span });
1737 }
1738 if has_rest_pat {
1739 self.dcx().emit_err(errors::UnionPatDotDot { span: pat.span });
1740 }
1741 } else if !unmentioned_fields.is_empty() {
1742 let accessible_unmentioned_fields: Vec<_> = unmentioned_fields
1743 .iter()
1744 .copied()
1745 .filter(|(field, _)| self.is_field_suggestable(field, pat.hir_id, pat.span))
1746 .collect();
1747
1748 if !has_rest_pat {
1749 if accessible_unmentioned_fields.is_empty() {
1750 unmentioned_err = Some(self.error_no_accessible_fields(pat, fields));
1751 } else {
1752 unmentioned_err = Some(self.error_unmentioned_fields(
1753 pat,
1754 &accessible_unmentioned_fields,
1755 accessible_unmentioned_fields.len() != unmentioned_fields.len(),
1756 fields,
1757 ));
1758 }
1759 } else if non_exhaustive && !accessible_unmentioned_fields.is_empty() {
1760 self.lint_non_exhaustive_omitted_patterns(
1761 pat,
1762 &accessible_unmentioned_fields,
1763 adt_ty,
1764 )
1765 }
1766 }
1767 match (inexistent_fields_err, unmentioned_err) {
1768 (Some(i), Some(u)) => {
1769 if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
1770 i.delay_as_bug();
1773 u.delay_as_bug();
1774 Err(e)
1775 } else {
1776 i.emit();
1777 Err(u.emit())
1778 }
1779 }
1780 (None, Some(u)) => {
1781 if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
1782 u.delay_as_bug();
1783 Err(e)
1784 } else {
1785 Err(u.emit())
1786 }
1787 }
1788 (Some(err), None) => Err(err.emit()),
1789 (None, None) => {
1790 self.error_tuple_variant_index_shorthand(variant, pat, fields)?;
1791 result
1792 }
1793 }
1794 }
1795
1796 fn error_tuple_variant_index_shorthand(
1797 &self,
1798 variant: &VariantDef,
1799 pat: &'_ Pat<'_>,
1800 fields: &[hir::PatField<'_>],
1801 ) -> Result<(), ErrorGuaranteed> {
1802 if let (Some(CtorKind::Fn), PatKind::Struct(qpath, field_patterns, ..)) =
1806 (variant.ctor_kind(), &pat.kind)
1807 {
1808 let has_shorthand_field_name = field_patterns.iter().any(|field| field.is_shorthand);
1809 if has_shorthand_field_name {
1810 let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
1811 let mut err = struct_span_code_err!(
1812 self.dcx(),
1813 pat.span,
1814 E0769,
1815 "tuple variant `{path}` written as struct variant",
1816 );
1817 err.span_suggestion_verbose(
1818 qpath.span().shrink_to_hi().to(pat.span.shrink_to_hi()),
1819 "use the tuple variant pattern syntax instead",
1820 format!("({})", self.get_suggested_tuple_struct_pattern(fields, variant)),
1821 Applicability::MaybeIncorrect,
1822 );
1823 return Err(err.emit());
1824 }
1825 }
1826 Ok(())
1827 }
1828
1829 fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) {
1830 let sess = self.tcx.sess;
1831 let sm = sess.source_map();
1832 let sp_brace = sm.end_point(pat.span);
1833 let sp_comma = sm.end_point(pat.span.with_hi(sp_brace.hi()));
1834 let sugg = if no_fields || sp_brace != sp_comma { ".. }" } else { ", .. }" };
1835
1836 struct_span_code_err!(
1837 self.dcx(),
1838 pat.span,
1839 E0638,
1840 "`..` required with {descr} marked as non-exhaustive",
1841 )
1842 .with_span_suggestion_verbose(
1843 sp_comma,
1844 "add `..` at the end of the field list to ignore all other fields",
1845 sugg,
1846 Applicability::MachineApplicable,
1847 )
1848 .emit();
1849 }
1850
1851 fn error_field_already_bound(
1852 &self,
1853 span: Span,
1854 ident: Ident,
1855 other_field: Span,
1856 ) -> ErrorGuaranteed {
1857 struct_span_code_err!(
1858 self.dcx(),
1859 span,
1860 E0025,
1861 "field `{}` bound multiple times in the pattern",
1862 ident
1863 )
1864 .with_span_label(span, format!("multiple uses of `{ident}` in pattern"))
1865 .with_span_label(other_field, format!("first use of `{ident}`"))
1866 .emit()
1867 }
1868
1869 fn error_inexistent_fields(
1870 &self,
1871 kind_name: &str,
1872 inexistent_fields: &[&hir::PatField<'tcx>],
1873 unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>,
1874 pat: &'tcx Pat<'tcx>,
1875 variant: &ty::VariantDef,
1876 args: ty::GenericArgsRef<'tcx>,
1877 ) -> Diag<'a> {
1878 let tcx = self.tcx;
1879 let (field_names, t, plural) = if let [field] = inexistent_fields {
1880 (format!("a field named `{}`", field.ident), "this", "")
1881 } else {
1882 (
1883 format!(
1884 "fields named {}",
1885 inexistent_fields
1886 .iter()
1887 .map(|field| format!("`{}`", field.ident))
1888 .collect::<Vec<String>>()
1889 .join(", ")
1890 ),
1891 "these",
1892 "s",
1893 )
1894 };
1895 let spans = inexistent_fields.iter().map(|field| field.ident.span).collect::<Vec<_>>();
1896 let mut err = struct_span_code_err!(
1897 self.dcx(),
1898 spans,
1899 E0026,
1900 "{} `{}` does not have {}",
1901 kind_name,
1902 tcx.def_path_str(variant.def_id),
1903 field_names
1904 );
1905 if let Some(pat_field) = inexistent_fields.last() {
1906 err.span_label(
1907 pat_field.ident.span,
1908 format!(
1909 "{} `{}` does not have {} field{}",
1910 kind_name,
1911 tcx.def_path_str(variant.def_id),
1912 t,
1913 plural
1914 ),
1915 );
1916
1917 if let [(field_def, field)] = unmentioned_fields.as_slice()
1918 && self.is_field_suggestable(field_def, pat.hir_id, pat.span)
1919 {
1920 let suggested_name =
1921 find_best_match_for_name(&[field.name], pat_field.ident.name, None);
1922 if let Some(suggested_name) = suggested_name {
1923 err.span_suggestion(
1924 pat_field.ident.span,
1925 "a field with a similar name exists",
1926 suggested_name,
1927 Applicability::MaybeIncorrect,
1928 );
1929
1930 if suggested_name.to_ident_string().parse::<usize>().is_err() {
1936 unmentioned_fields.retain(|&(_, x)| x.name != suggested_name);
1938 }
1939 } else if inexistent_fields.len() == 1 {
1940 match pat_field.pat.kind {
1941 PatKind::Expr(_)
1942 if !self.may_coerce(
1943 self.typeck_results.borrow().node_type(pat_field.pat.hir_id),
1944 self.field_ty(field.span, field_def, args),
1945 ) => {}
1946 _ => {
1947 err.span_suggestion_short(
1948 pat_field.ident.span,
1949 format!(
1950 "`{}` has a field named `{}`",
1951 tcx.def_path_str(variant.def_id),
1952 field.name,
1953 ),
1954 field.name,
1955 Applicability::MaybeIncorrect,
1956 );
1957 }
1958 }
1959 }
1960 }
1961 }
1962 if tcx.sess.teach(err.code.unwrap()) {
1963 err.note(
1964 "This error indicates that a struct pattern attempted to \
1965 extract a nonexistent field from a struct. Struct fields \
1966 are identified by the name used before the colon : so struct \
1967 patterns should resemble the declaration of the struct type \
1968 being matched.\n\n\
1969 If you are using shorthand field patterns but want to refer \
1970 to the struct field by a different name, you should rename \
1971 it explicitly.",
1972 );
1973 }
1974 err
1975 }
1976
1977 fn error_tuple_variant_as_struct_pat(
1978 &self,
1979 pat: &Pat<'_>,
1980 fields: &'tcx [hir::PatField<'tcx>],
1981 variant: &ty::VariantDef,
1982 ) -> Result<(), ErrorGuaranteed> {
1983 if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) =
1984 (variant.ctor_kind(), &pat.kind)
1985 {
1986 let is_tuple_struct_match = !pattern_fields.is_empty()
1987 && pattern_fields.iter().map(|field| field.ident.name.as_str()).all(is_number);
1988 if is_tuple_struct_match {
1989 return Ok(());
1990 }
1991
1992 variant.has_errors()?;
1994
1995 let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
1996 let mut err = struct_span_code_err!(
1997 self.dcx(),
1998 pat.span,
1999 E0769,
2000 "tuple variant `{}` written as struct variant",
2001 path
2002 );
2003 let (sugg, appl) = if fields.len() == variant.fields.len() {
2004 (
2005 self.get_suggested_tuple_struct_pattern(fields, variant),
2006 Applicability::MachineApplicable,
2007 )
2008 } else {
2009 (
2010 variant.fields.iter().map(|_| "_").collect::<Vec<&str>>().join(", "),
2011 Applicability::MaybeIncorrect,
2012 )
2013 };
2014 err.span_suggestion_verbose(
2015 qpath.span().shrink_to_hi().to(pat.span.shrink_to_hi()),
2016 "use the tuple variant pattern syntax instead",
2017 format!("({sugg})"),
2018 appl,
2019 );
2020 return Err(err.emit());
2021 }
2022 Ok(())
2023 }
2024
2025 fn get_suggested_tuple_struct_pattern(
2026 &self,
2027 fields: &[hir::PatField<'_>],
2028 variant: &VariantDef,
2029 ) -> String {
2030 let variant_field_idents =
2031 variant.fields.iter().map(|f| f.ident(self.tcx)).collect::<Vec<Ident>>();
2032 fields
2033 .iter()
2034 .map(|field| {
2035 match self.tcx.sess.source_map().span_to_snippet(field.pat.span) {
2036 Ok(f) => {
2037 if variant_field_idents.contains(&field.ident) {
2040 String::from("_")
2041 } else {
2042 f
2043 }
2044 }
2045 Err(_) => rustc_hir_pretty::pat_to_string(&self.tcx, field.pat),
2046 }
2047 })
2048 .collect::<Vec<String>>()
2049 .join(", ")
2050 }
2051
2052 fn error_no_accessible_fields(
2068 &self,
2069 pat: &Pat<'_>,
2070 fields: &'tcx [hir::PatField<'tcx>],
2071 ) -> Diag<'a> {
2072 let mut err = self
2073 .dcx()
2074 .struct_span_err(pat.span, "pattern requires `..` due to inaccessible fields");
2075
2076 if let Some(field) = fields.last() {
2077 err.span_suggestion_verbose(
2078 field.span.shrink_to_hi(),
2079 "ignore the inaccessible and unused fields",
2080 ", ..",
2081 Applicability::MachineApplicable,
2082 );
2083 } else {
2084 let qpath_span = if let PatKind::Struct(qpath, ..) = &pat.kind {
2085 qpath.span()
2086 } else {
2087 bug!("`error_no_accessible_fields` called on non-struct pattern");
2088 };
2089
2090 let span = pat.span.with_lo(qpath_span.shrink_to_hi().hi());
2092 err.span_suggestion_verbose(
2093 span,
2094 "ignore the inaccessible and unused fields",
2095 " { .. }",
2096 Applicability::MachineApplicable,
2097 );
2098 }
2099 err
2100 }
2101
2102 fn lint_non_exhaustive_omitted_patterns(
2107 &self,
2108 pat: &Pat<'_>,
2109 unmentioned_fields: &[(&ty::FieldDef, Ident)],
2110 ty: Ty<'tcx>,
2111 ) {
2112 fn joined_uncovered_patterns(witnesses: &[&Ident]) -> String {
2113 const LIMIT: usize = 3;
2114 match witnesses {
2115 [] => {
2116 unreachable!(
2117 "expected an uncovered pattern, otherwise why are we emitting an error?"
2118 )
2119 }
2120 [witness] => format!("`{witness}`"),
2121 [head @ .., tail] if head.len() < LIMIT => {
2122 let head: Vec<_> = head.iter().map(<_>::to_string).collect();
2123 format!("`{}` and `{}`", head.join("`, `"), tail)
2124 }
2125 _ => {
2126 let (head, tail) = witnesses.split_at(LIMIT);
2127 let head: Vec<_> = head.iter().map(<_>::to_string).collect();
2128 format!("`{}` and {} more", head.join("`, `"), tail.len())
2129 }
2130 }
2131 }
2132 let joined_patterns = joined_uncovered_patterns(
2133 &unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
2134 );
2135
2136 self.tcx.node_span_lint(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, |lint| {
2137 lint.primary_message("some fields are not explicitly listed");
2138 lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
2139 lint.help(
2140 "ensure that all fields are mentioned explicitly by adding the suggested fields",
2141 );
2142 lint.note(format!(
2143 "the pattern is of type `{ty}` and the `non_exhaustive_omitted_patterns` attribute was found",
2144 ));
2145 });
2146 }
2147
2148 fn error_unmentioned_fields(
2158 &self,
2159 pat: &Pat<'_>,
2160 unmentioned_fields: &[(&ty::FieldDef, Ident)],
2161 have_inaccessible_fields: bool,
2162 fields: &'tcx [hir::PatField<'tcx>],
2163 ) -> Diag<'a> {
2164 let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" };
2165 let field_names = if let [(_, field)] = unmentioned_fields {
2166 format!("field `{field}`{inaccessible}")
2167 } else {
2168 let fields = unmentioned_fields
2169 .iter()
2170 .map(|(_, name)| format!("`{name}`"))
2171 .collect::<Vec<String>>()
2172 .join(", ");
2173 format!("fields {fields}{inaccessible}")
2174 };
2175 let mut err = struct_span_code_err!(
2176 self.dcx(),
2177 pat.span,
2178 E0027,
2179 "pattern does not mention {}",
2180 field_names
2181 );
2182 err.span_label(pat.span, format!("missing {field_names}"));
2183 let len = unmentioned_fields.len();
2184 let (prefix, postfix, sp) = match fields {
2185 [] => match &pat.kind {
2186 PatKind::Struct(path, [], false) => {
2187 (" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi()))
2188 }
2189 _ => return err,
2190 },
2191 [.., field] => {
2192 let tail = field.span.shrink_to_hi().with_hi(pat.span.hi());
2195 match &pat.kind {
2196 PatKind::Struct(..) => (", ", " }", tail),
2197 _ => return err,
2198 }
2199 }
2200 };
2201 err.span_suggestion(
2202 sp,
2203 format!(
2204 "include the missing field{} in the pattern{}",
2205 pluralize!(len),
2206 if have_inaccessible_fields { " and ignore the inaccessible fields" } else { "" }
2207 ),
2208 format!(
2209 "{}{}{}{}",
2210 prefix,
2211 unmentioned_fields
2212 .iter()
2213 .map(|(_, name)| {
2214 let field_name = name.to_string();
2215 if is_number(&field_name) { format!("{field_name}: _") } else { field_name }
2216 })
2217 .collect::<Vec<_>>()
2218 .join(", "),
2219 if have_inaccessible_fields { ", .." } else { "" },
2220 postfix,
2221 ),
2222 Applicability::MachineApplicable,
2223 );
2224 err.span_suggestion(
2225 sp,
2226 format!(
2227 "if you don't care about {these} missing field{s}, you can explicitly ignore {them}",
2228 these = pluralize!("this", len),
2229 s = pluralize!(len),
2230 them = if len == 1 { "it" } else { "them" },
2231 ),
2232 format!(
2233 "{}{}{}{}",
2234 prefix,
2235 unmentioned_fields
2236 .iter()
2237 .map(|(_, name)| {
2238 let field_name = name.to_string();
2239 format!("{field_name}: _")
2240 })
2241 .collect::<Vec<_>>()
2242 .join(", "),
2243 if have_inaccessible_fields { ", .." } else { "" },
2244 postfix,
2245 ),
2246 Applicability::MachineApplicable,
2247 );
2248 err.span_suggestion(
2249 sp,
2250 "or always ignore missing fields here",
2251 format!("{prefix}..{postfix}"),
2252 Applicability::MachineApplicable,
2253 );
2254 err
2255 }
2256
2257 fn check_pat_box(
2258 &self,
2259 span: Span,
2260 inner: &'tcx Pat<'tcx>,
2261 expected: Ty<'tcx>,
2262 pat_info: PatInfo<'tcx>,
2263 ) -> Ty<'tcx> {
2264 let tcx = self.tcx;
2265 let (box_ty, inner_ty) = self
2266 .check_dereferenceable(span, expected, inner)
2267 .and_then(|()| {
2268 let inner_ty = self.next_ty_var(inner.span);
2271 let box_ty = Ty::new_box(tcx, inner_ty);
2272 self.demand_eqtype_pat(span, expected, box_ty, &pat_info.top_info)?;
2273 Ok((box_ty, inner_ty))
2274 })
2275 .unwrap_or_else(|guar| {
2276 let err = Ty::new_error(tcx, guar);
2277 (err, err)
2278 });
2279 self.check_pat(inner, inner_ty, pat_info);
2280 box_ty
2281 }
2282
2283 fn check_pat_deref(
2284 &self,
2285 span: Span,
2286 inner: &'tcx Pat<'tcx>,
2287 expected: Ty<'tcx>,
2288 pat_info: PatInfo<'tcx>,
2289 ) -> Ty<'tcx> {
2290 let tcx = self.tcx;
2291 self.register_bound(
2293 expected,
2294 tcx.require_lang_item(hir::LangItem::DerefPure, Some(span)),
2295 self.misc(span),
2296 );
2297 let ty = Ty::new_projection(
2299 tcx,
2300 tcx.require_lang_item(hir::LangItem::DerefTarget, Some(span)),
2301 [expected],
2302 );
2303 let ty = self.normalize(span, ty);
2304 let ty = self.try_structurally_resolve_type(span, ty);
2305 self.check_pat(inner, ty, pat_info);
2306
2307 if self.typeck_results.borrow().pat_has_ref_mut_binding(inner) {
2312 self.register_bound(
2313 expected,
2314 tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)),
2315 self.misc(span),
2316 );
2317 }
2318
2319 expected
2320 }
2321
2322 fn check_pat_ref(
2324 &self,
2325 pat: &'tcx Pat<'tcx>,
2326 inner: &'tcx Pat<'tcx>,
2327 pat_mutbl: Mutability,
2328 mut expected: Ty<'tcx>,
2329 mut pat_info: PatInfo<'tcx>,
2330 ) -> Ty<'tcx> {
2331 let tcx = self.tcx;
2332
2333 let pat_prefix_span =
2334 inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end));
2335
2336 let ref_pat_matches_mut_ref = self.ref_pat_matches_mut_ref();
2337 if ref_pat_matches_mut_ref && pat_mutbl == Mutability::Not {
2338 pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(pat_prefix_span);
2343 }
2344
2345 expected = self.try_structurally_resolve_type(pat.span, expected);
2346 if let ByRef::Yes(inh_mut) = pat_info.binding_mode {
2349 match self.ref_pat_matches_inherited_ref(pat.span.edition()) {
2350 InheritedRefMatchRule::EatOuter => {
2351 if pat_mutbl > inh_mut {
2353 debug_assert!(ref_pat_matches_mut_ref);
2358 self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
2359 }
2360
2361 pat_info.binding_mode = ByRef::No;
2362 self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2363 self.check_pat(inner, expected, pat_info);
2364 return expected;
2365 }
2366 InheritedRefMatchRule::EatInner => {
2367 if let ty::Ref(_, _, r_mutbl) = *expected.kind()
2368 && pat_mutbl <= r_mutbl
2369 {
2370 debug_assert!(ref_pat_matches_mut_ref);
2377 debug_assert!(self.downgrade_mut_inside_shared());
2381 let mutbl_cap = cmp::min(r_mutbl, pat_info.max_ref_mutbl.as_mutbl());
2382 pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(mutbl_cap);
2383 } else {
2384 if pat_mutbl > inh_mut {
2387 debug_assert!(ref_pat_matches_mut_ref);
2396 self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
2397 }
2398
2399 pat_info.binding_mode = ByRef::No;
2400 self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2401 self.check_pat(inner, expected, pat_info);
2402 return expected;
2403 }
2404 }
2405 InheritedRefMatchRule::EatBoth { consider_inherited_ref: true } => {
2406 pat_info.binding_mode = ByRef::No;
2408
2409 if let ty::Ref(_, inner_ty, _) = *expected.kind() {
2410 if pat_mutbl.is_mut() && inh_mut.is_mut() {
2412 self.check_pat(inner, inner_ty, pat_info);
2419 return expected;
2420 } else {
2421 }
2428 } else {
2429 if pat_mutbl > inh_mut {
2432 self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
2434 }
2435
2436 self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2437 self.check_pat(inner, expected, pat_info);
2438 return expected;
2439 }
2440 }
2441 InheritedRefMatchRule::EatBoth { consider_inherited_ref: false } => {
2442 pat_info.binding_mode = ByRef::No;
2445 self.add_rust_2024_migration_desugared_pat(
2446 pat_info.top_info.hir_id,
2447 pat,
2448 match pat_mutbl {
2449 Mutability::Not => '&', Mutability::Mut => 't', },
2452 inh_mut,
2453 )
2454 }
2455 }
2456 }
2457
2458 let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
2459 Ok(()) => {
2460 debug!("check_pat_ref: expected={:?}", expected);
2467 match *expected.kind() {
2468 ty::Ref(_, r_ty, r_mutbl)
2469 if (ref_pat_matches_mut_ref && r_mutbl >= pat_mutbl)
2470 || r_mutbl == pat_mutbl =>
2471 {
2472 if r_mutbl == Mutability::Not {
2473 pat_info.max_ref_mutbl = MutblCap::Not;
2474 }
2475
2476 (expected, r_ty)
2477 }
2478
2479 _ => {
2480 let inner_ty = self.next_ty_var(inner.span);
2481 let ref_ty = self.new_ref_ty(pat.span, pat_mutbl, inner_ty);
2482 debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
2483 let err = self.demand_eqtype_pat_diag(
2484 pat.span,
2485 expected,
2486 ref_ty,
2487 &pat_info.top_info,
2488 );
2489
2490 if let Err(mut err) = err {
2493 self.borrow_pat_suggestion(&mut err, pat);
2494 err.emit();
2495 }
2496 (ref_ty, inner_ty)
2497 }
2498 }
2499 }
2500 Err(guar) => {
2501 let err = Ty::new_error(tcx, guar);
2502 (err, err)
2503 }
2504 };
2505
2506 self.check_pat(inner, inner_ty, pat_info);
2507 ref_ty
2508 }
2509
2510 fn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'tcx>) -> Ty<'tcx> {
2512 let region = self.next_region_var(infer::PatternRegion(span));
2513 Ty::new_ref(self.tcx, region, ty, mutbl)
2514 }
2515
2516 fn error_inherited_ref_mutability_mismatch(
2517 &self,
2518 pat: &'tcx Pat<'tcx>,
2519 pat_prefix_span: Option<Span>,
2520 ) -> ErrorGuaranteed {
2521 let err_msg = "mismatched types";
2522 let err = if let Some(span) = pat_prefix_span {
2523 let mut err = self.dcx().struct_span_err(span, err_msg);
2524 err.code(E0308);
2525 err.note("cannot match inherited `&` with `&mut` pattern");
2526 err.span_suggestion_verbose(
2527 span,
2528 "replace this `&mut` pattern with `&`",
2529 "&",
2530 Applicability::MachineApplicable,
2531 );
2532 err
2533 } else {
2534 self.dcx().struct_span_err(pat.span, err_msg)
2535 };
2536 err.emit()
2537 }
2538
2539 fn try_resolve_slice_ty_to_array_ty(
2540 &self,
2541 before: &'tcx [Pat<'tcx>],
2542 slice: Option<&'tcx Pat<'tcx>>,
2543 span: Span,
2544 ) -> Option<Ty<'tcx>> {
2545 if slice.is_some() {
2546 return None;
2547 }
2548
2549 let tcx = self.tcx;
2550 let len = before.len();
2551 let inner_ty = self.next_ty_var(span);
2552
2553 Some(Ty::new_array(tcx, inner_ty, len.try_into().unwrap()))
2554 }
2555
2556 fn pat_is_irrefutable(&self, decl_origin: Option<DeclOrigin<'_>>) -> bool {
2587 match decl_origin {
2588 Some(DeclOrigin::LocalDecl { els: None }) => true,
2589 Some(DeclOrigin::LocalDecl { els: Some(_) } | DeclOrigin::LetExpr) | None => false,
2590 }
2591 }
2592
2593 fn check_pat_slice(
2604 &self,
2605 span: Span,
2606 before: &'tcx [Pat<'tcx>],
2607 slice: Option<&'tcx Pat<'tcx>>,
2608 after: &'tcx [Pat<'tcx>],
2609 expected: Ty<'tcx>,
2610 pat_info: PatInfo<'tcx>,
2611 ) -> Ty<'tcx> {
2612 let expected = self.try_structurally_resolve_type(span, expected);
2613
2614 if self.pat_is_irrefutable(pat_info.decl_origin) && expected.is_ty_var() {
2617 if let Some(resolved_arr_ty) =
2618 self.try_resolve_slice_ty_to_array_ty(before, slice, span)
2619 {
2620 debug!(?resolved_arr_ty);
2621 let _ = self.demand_eqtype(span, expected, resolved_arr_ty);
2622 }
2623 }
2624
2625 let expected = self.structurally_resolve_type(span, expected);
2626 debug!(?expected);
2627
2628 let (element_ty, opt_slice_ty, inferred) = match *expected.kind() {
2629 ty::Array(element_ty, len) => {
2631 let min = before.len() as u64 + after.len() as u64;
2632 let (opt_slice_ty, expected) =
2633 self.check_array_pat_len(span, element_ty, expected, slice, len, min);
2634 assert!(opt_slice_ty.is_some() || slice.is_none());
2637 (element_ty, opt_slice_ty, expected)
2638 }
2639 ty::Slice(element_ty) => (element_ty, Some(expected), expected),
2640 _ => {
2642 let guar = expected.error_reported().err().unwrap_or_else(|| {
2643 self.error_expected_array_or_slice(span, expected, pat_info)
2644 });
2645 let err = Ty::new_error(self.tcx, guar);
2646 (err, Some(err), err)
2647 }
2648 };
2649
2650 for elt in before {
2652 self.check_pat(elt, element_ty, pat_info);
2653 }
2654 if let Some(slice) = slice {
2656 self.check_pat(slice, opt_slice_ty.unwrap(), pat_info);
2657 }
2658 for elt in after {
2660 self.check_pat(elt, element_ty, pat_info);
2661 }
2662 inferred
2663 }
2664
2665 fn check_array_pat_len(
2670 &self,
2671 span: Span,
2672 element_ty: Ty<'tcx>,
2673 arr_ty: Ty<'tcx>,
2674 slice: Option<&'tcx Pat<'tcx>>,
2675 len: ty::Const<'tcx>,
2676 min_len: u64,
2677 ) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
2678 let len = self.try_structurally_resolve_const(span, len).try_to_target_usize(self.tcx);
2679
2680 let guar = if let Some(len) = len {
2681 if slice.is_none() {
2683 if min_len == len {
2687 return (None, arr_ty);
2688 }
2689
2690 self.error_scrutinee_inconsistent_length(span, min_len, len)
2691 } else if let Some(pat_len) = len.checked_sub(min_len) {
2692 return (Some(Ty::new_array(self.tcx, element_ty, pat_len)), arr_ty);
2695 } else {
2696 self.error_scrutinee_with_rest_inconsistent_length(span, min_len, len)
2699 }
2700 } else if slice.is_none() {
2701 let updated_arr_ty = Ty::new_array(self.tcx, element_ty, min_len);
2704 self.demand_eqtype(span, updated_arr_ty, arr_ty);
2705 return (None, updated_arr_ty);
2706 } else {
2707 self.error_scrutinee_unfixed_length(span)
2711 };
2712
2713 (Some(Ty::new_error(self.tcx, guar)), arr_ty)
2715 }
2716
2717 fn error_scrutinee_inconsistent_length(
2718 &self,
2719 span: Span,
2720 min_len: u64,
2721 size: u64,
2722 ) -> ErrorGuaranteed {
2723 struct_span_code_err!(
2724 self.dcx(),
2725 span,
2726 E0527,
2727 "pattern requires {} element{} but array has {}",
2728 min_len,
2729 pluralize!(min_len),
2730 size,
2731 )
2732 .with_span_label(span, format!("expected {} element{}", size, pluralize!(size)))
2733 .emit()
2734 }
2735
2736 fn error_scrutinee_with_rest_inconsistent_length(
2737 &self,
2738 span: Span,
2739 min_len: u64,
2740 size: u64,
2741 ) -> ErrorGuaranteed {
2742 struct_span_code_err!(
2743 self.dcx(),
2744 span,
2745 E0528,
2746 "pattern requires at least {} element{} but array has {}",
2747 min_len,
2748 pluralize!(min_len),
2749 size,
2750 )
2751 .with_span_label(
2752 span,
2753 format!("pattern cannot match array of {} element{}", size, pluralize!(size),),
2754 )
2755 .emit()
2756 }
2757
2758 fn error_scrutinee_unfixed_length(&self, span: Span) -> ErrorGuaranteed {
2759 struct_span_code_err!(
2760 self.dcx(),
2761 span,
2762 E0730,
2763 "cannot pattern-match on an array without a fixed length",
2764 )
2765 .emit()
2766 }
2767
2768 fn error_expected_array_or_slice(
2769 &self,
2770 span: Span,
2771 expected_ty: Ty<'tcx>,
2772 pat_info: PatInfo<'tcx>,
2773 ) -> ErrorGuaranteed {
2774 let PatInfo { top_info: ti, current_depth, .. } = pat_info;
2775
2776 let mut slice_pat_semantics = false;
2777 let mut as_deref = None;
2778 let mut slicing = None;
2779 if let ty::Ref(_, ty, _) = expected_ty.kind()
2780 && let ty::Array(..) | ty::Slice(..) = ty.kind()
2781 {
2782 slice_pat_semantics = true;
2783 } else if self
2784 .autoderef(span, expected_ty)
2785 .silence_errors()
2786 .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
2787 && let Some(span) = ti.span
2788 && let Some(_) = ti.origin_expr
2789 {
2790 let resolved_ty = self.resolve_vars_if_possible(ti.expected);
2791 let (is_slice_or_array_or_vector, resolved_ty) =
2792 self.is_slice_or_array_or_vector(resolved_ty);
2793 match resolved_ty.kind() {
2794 ty::Adt(adt_def, _)
2795 if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
2796 || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
2797 {
2798 as_deref = Some(errors::AsDerefSuggestion { span: span.shrink_to_hi() });
2800 }
2801 _ => (),
2802 }
2803
2804 let is_top_level = current_depth <= 1;
2805 if is_slice_or_array_or_vector && is_top_level {
2806 slicing = Some(errors::SlicingSuggestion { span: span.shrink_to_hi() });
2807 }
2808 }
2809 self.dcx().emit_err(errors::ExpectedArrayOrSlice {
2810 span,
2811 ty: expected_ty,
2812 slice_pat_semantics,
2813 as_deref,
2814 slicing,
2815 })
2816 }
2817
2818 fn is_slice_or_array_or_vector(&self, ty: Ty<'tcx>) -> (bool, Ty<'tcx>) {
2819 match ty.kind() {
2820 ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did()) => {
2821 (true, ty)
2822 }
2823 ty::Ref(_, ty, _) => self.is_slice_or_array_or_vector(*ty),
2824 ty::Slice(..) | ty::Array(..) => (true, ty),
2825 _ => (false, ty),
2826 }
2827 }
2828
2829 fn add_rust_2024_migration_desugared_pat(
2832 &self,
2833 pat_id: HirId,
2834 subpat: &'tcx Pat<'tcx>,
2835 final_char: char,
2836 def_br_mutbl: Mutability,
2837 ) {
2838 let from_expansion = subpat.span.from_expansion();
2840 let trimmed_span = if from_expansion {
2841 subpat.span
2843 } else {
2844 let trimmed = self.tcx.sess.source_map().span_through_char(subpat.span, final_char);
2845 trimmed.with_ctxt(subpat.span.ctxt())
2848 };
2849
2850 let mut typeck_results = self.typeck_results.borrow_mut();
2851 let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
2852 let info = table.entry(pat_id).or_insert_with(|| ty::Rust2024IncompatiblePatInfo {
2857 primary_labels: Vec::new(),
2858 bad_modifiers: false,
2859 bad_ref_pats: false,
2860 suggest_eliding_modes: !self.tcx.features().ref_pat_eat_one_layer_2024()
2861 && !self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
2862 });
2863
2864 let pat_kind = if let PatKind::Binding(user_bind_annot, _, _, _) = subpat.kind {
2865 info.bad_modifiers = true;
2866 info.suggest_eliding_modes &=
2870 user_bind_annot == BindingMode(ByRef::Yes(def_br_mutbl), Mutability::Not);
2871 "binding modifier"
2872 } else {
2873 info.bad_ref_pats = true;
2874 info.suggest_eliding_modes = false;
2878 "reference pattern"
2879 };
2880 let primary_label = if from_expansion {
2883 info.suggest_eliding_modes = false;
2885 "occurs within macro expansion".to_owned()
2889 } else {
2890 let dbm_str = match def_br_mutbl {
2891 Mutability::Not => "ref",
2892 Mutability::Mut => "ref mut",
2893 };
2894 format!("{pat_kind} not allowed under `{dbm_str}` default binding mode")
2895 };
2896 info.primary_labels.push((trimmed_span, primary_label));
2897 }
2898}