]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/check/pat.rs
Rollup merge of #98174 - Kixunil:rename_ptr_as_mut_const_to_cast, r=scottmcm
[rust.git] / compiler / rustc_typeck / src / check / pat.rs
1 use crate::check::FnCtxt;
2 use rustc_ast as ast;
3
4 use rustc_data_structures::fx::FxHashMap;
5 use rustc_errors::{
6     pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
7     MultiSpan,
8 };
9 use rustc_hir as hir;
10 use rustc_hir::def::{CtorKind, DefKind, Res};
11 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
12 use rustc_hir::{HirId, Pat, PatKind};
13 use rustc_infer::infer;
14 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
15 use rustc_middle::middle::stability::EvalResult;
16 use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitable};
17 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
18 use rustc_span::hygiene::DesugaringKind;
19 use rustc_span::lev_distance::find_best_match_for_name;
20 use rustc_span::source_map::{Span, Spanned};
21 use rustc_span::symbol::{kw, sym, Ident};
22 use rustc_span::{BytePos, DUMMY_SP};
23 use rustc_trait_selection::autoderef::Autoderef;
24 use rustc_trait_selection::traits::{ObligationCause, Pattern};
25 use ty::VariantDef;
26
27 use std::cmp;
28 use std::collections::hash_map::Entry::{Occupied, Vacant};
29
30 use super::report_unexpected_variant_res;
31
32 const CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ: &str = "\
33 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
34 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
35 this type has no compile-time size. Therefore, all accesses to trait types must be through \
36 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
37
38 You can read more about trait objects in the Trait Objects section of the Reference: \
39 https://doc.rust-lang.org/reference/types.html#trait-objects";
40
41 /// Information about the expected type at the top level of type checking a pattern.
42 ///
43 /// **NOTE:** This is only for use by diagnostics. Do NOT use for type checking logic!
44 #[derive(Copy, Clone)]
45 struct TopInfo<'tcx> {
46     /// The `expected` type at the top level of type checking a pattern.
47     expected: Ty<'tcx>,
48     /// Was the origin of the `span` from a scrutinee expression?
49     ///
50     /// Otherwise there is no scrutinee and it could be e.g. from the type of a formal parameter.
51     origin_expr: bool,
52     /// The span giving rise to the `expected` type, if one could be provided.
53     ///
54     /// If `origin_expr` is `true`, then this is the span of the scrutinee as in:
55     ///
56     /// - `match scrutinee { ... }`
57     /// - `let _ = scrutinee;`
58     ///
59     /// This is used to point to add context in type errors.
60     /// In the following example, `span` corresponds to the `a + b` expression:
61     ///
62     /// ```text
63     /// error[E0308]: mismatched types
64     ///  --> src/main.rs:L:C
65     ///   |
66     /// L |    let temp: usize = match a + b {
67     ///   |                            ----- this expression has type `usize`
68     /// L |         Ok(num) => num,
69     ///   |         ^^^^^^^ expected `usize`, found enum `std::result::Result`
70     ///   |
71     ///   = note: expected type `usize`
72     ///              found type `std::result::Result<_, _>`
73     /// ```
74     span: Option<Span>,
75     /// This refers to the parent pattern. Used to provide extra diagnostic information on errors.
76     /// ```text
77     /// error[E0308]: mismatched types
78     ///   --> $DIR/const-in-struct-pat.rs:8:17
79     ///   |
80     /// L | struct f;
81     ///   | --------- unit struct defined here
82     /// ...
83     /// L |     let Thing { f } = t;
84     ///   |                 ^
85     ///   |                 |
86     ///   |                 expected struct `std::string::String`, found struct `f`
87     ///   |                 `f` is interpreted as a unit struct, not a new binding
88     ///   |                 help: bind the struct field to a different name instead: `f: other_f`
89     /// ```
90     parent_pat: Option<&'tcx Pat<'tcx>>,
91 }
92
93 impl<'tcx> FnCtxt<'_, 'tcx> {
94     fn pattern_cause(&self, ti: TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
95         let code = Pattern { span: ti.span, root_ty: ti.expected, origin_expr: ti.origin_expr };
96         self.cause(cause_span, code)
97     }
98
99     fn demand_eqtype_pat_diag(
100         &self,
101         cause_span: Span,
102         expected: Ty<'tcx>,
103         actual: Ty<'tcx>,
104         ti: TopInfo<'tcx>,
105     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
106         self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
107     }
108
109     fn demand_eqtype_pat(
110         &self,
111         cause_span: Span,
112         expected: Ty<'tcx>,
113         actual: Ty<'tcx>,
114         ti: TopInfo<'tcx>,
115     ) {
116         if let Some(mut err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) {
117             err.emit();
118         }
119     }
120 }
121
122 const INITIAL_BM: BindingMode = BindingMode::BindByValue(hir::Mutability::Not);
123
124 /// Mode for adjusting the expected type and binding mode.
125 enum AdjustMode {
126     /// Peel off all immediate reference types.
127     Peel,
128     /// Reset binding mode to the initial mode.
129     Reset,
130     /// Pass on the input binding mode and expected type.
131     Pass,
132 }
133
134 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
135     /// Type check the given top level pattern against the `expected` type.
136     ///
137     /// If a `Some(span)` is provided and `origin_expr` holds,
138     /// then the `span` represents the scrutinee's span.
139     /// The scrutinee is found in e.g. `match scrutinee { ... }` and `let pat = scrutinee;`.
140     ///
141     /// Otherwise, `Some(span)` represents the span of a type expression
142     /// which originated the `expected` type.
143     pub fn check_pat_top(
144         &self,
145         pat: &'tcx Pat<'tcx>,
146         expected: Ty<'tcx>,
147         span: Option<Span>,
148         origin_expr: bool,
149     ) {
150         let info = TopInfo { expected, origin_expr, span, parent_pat: None };
151         self.check_pat(pat, expected, INITIAL_BM, info);
152     }
153
154     /// Type check the given `pat` against the `expected` type
155     /// with the provided `def_bm` (default binding mode).
156     ///
157     /// Outside of this module, `check_pat_top` should always be used.
158     /// Conversely, inside this module, `check_pat_top` should never be used.
159     #[instrument(level = "debug", skip(self, ti))]
160     fn check_pat(
161         &self,
162         pat: &'tcx Pat<'tcx>,
163         expected: Ty<'tcx>,
164         def_bm: BindingMode,
165         ti: TopInfo<'tcx>,
166     ) {
167         let path_res = match &pat.kind {
168             PatKind::Path(qpath) => {
169                 Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span))
170             }
171             _ => None,
172         };
173         let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
174         let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
175
176         let ty = match pat.kind {
177             PatKind::Wild => expected,
178             PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
179             PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
180             PatKind::Binding(ba, var_id, _, sub) => {
181                 self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, ti)
182             }
183             PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
184                 self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, def_bm, ti)
185             }
186             PatKind::Path(ref qpath) => {
187                 self.check_pat_path(pat, qpath, path_res.unwrap(), expected, ti)
188             }
189             PatKind::Struct(ref qpath, fields, has_rest_pat) => {
190                 self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, def_bm, ti)
191             }
192             PatKind::Or(pats) => {
193                 let parent_pat = Some(pat);
194                 for pat in pats {
195                     self.check_pat(pat, expected, def_bm, TopInfo { parent_pat, ..ti });
196                 }
197                 expected
198             }
199             PatKind::Tuple(elements, ddpos) => {
200                 self.check_pat_tuple(pat.span, elements, ddpos, expected, def_bm, ti)
201             }
202             PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, def_bm, ti),
203             PatKind::Ref(inner, mutbl) => {
204                 self.check_pat_ref(pat, inner, mutbl, expected, def_bm, ti)
205             }
206             PatKind::Slice(before, slice, after) => {
207                 self.check_pat_slice(pat.span, before, slice, after, expected, def_bm, ti)
208             }
209         };
210
211         self.write_ty(pat.hir_id, ty);
212
213         // (note_1): In most of the cases where (note_1) is referenced
214         // (literals and constants being the exception), we relate types
215         // using strict equality, even though subtyping would be sufficient.
216         // There are a few reasons for this, some of which are fairly subtle
217         // and which cost me (nmatsakis) an hour or two debugging to remember,
218         // so I thought I'd write them down this time.
219         //
220         // 1. There is no loss of expressiveness here, though it does
221         // cause some inconvenience. What we are saying is that the type
222         // of `x` becomes *exactly* what is expected. This can cause unnecessary
223         // errors in some cases, such as this one:
224         //
225         // ```
226         // fn foo<'x>(x: &'x i32) {
227         //    let a = 1;
228         //    let mut z = x;
229         //    z = &a;
230         // }
231         // ```
232         //
233         // The reason we might get an error is that `z` might be
234         // assigned a type like `&'x i32`, and then we would have
235         // a problem when we try to assign `&a` to `z`, because
236         // the lifetime of `&a` (i.e., the enclosing block) is
237         // shorter than `'x`.
238         //
239         // HOWEVER, this code works fine. The reason is that the
240         // expected type here is whatever type the user wrote, not
241         // the initializer's type. In this case the user wrote
242         // nothing, so we are going to create a type variable `Z`.
243         // Then we will assign the type of the initializer (`&'x i32`)
244         // as a subtype of `Z`: `&'x i32 <: Z`. And hence we
245         // will instantiate `Z` as a type `&'0 i32` where `'0` is
246         // a fresh region variable, with the constraint that `'x : '0`.
247         // So basically we're all set.
248         //
249         // Note that there are two tests to check that this remains true
250         // (`regions-reassign-{match,let}-bound-pointer.rs`).
251         //
252         // 2. Things go horribly wrong if we use subtype. The reason for
253         // THIS is a fairly subtle case involving bound regions. See the
254         // `givens` field in `region_constraints`, as well as the test
255         // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
256         // for details. Short version is that we must sometimes detect
257         // relationships between specific region variables and regions
258         // bound in a closure signature, and that detection gets thrown
259         // off when we substitute fresh region variables here to enable
260         // subtyping.
261     }
262
263     /// Compute the new expected type and default binding mode from the old ones
264     /// as well as the pattern form we are currently checking.
265     fn calc_default_binding_mode(
266         &self,
267         pat: &'tcx Pat<'tcx>,
268         expected: Ty<'tcx>,
269         def_bm: BindingMode,
270         adjust_mode: AdjustMode,
271     ) -> (Ty<'tcx>, BindingMode) {
272         match adjust_mode {
273             AdjustMode::Pass => (expected, def_bm),
274             AdjustMode::Reset => (expected, INITIAL_BM),
275             AdjustMode::Peel => self.peel_off_references(pat, expected, def_bm),
276         }
277     }
278
279     /// How should the binding mode and expected type be adjusted?
280     ///
281     /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`.
282     fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> AdjustMode {
283         // When we perform destructuring assignment, we disable default match bindings, which are
284         // unintuitive in this context.
285         if !pat.default_binding_modes {
286             return AdjustMode::Reset;
287         }
288         match &pat.kind {
289             // Type checking these product-like types successfully always require
290             // that the expected type be of those types and not reference types.
291             PatKind::Struct(..)
292             | PatKind::TupleStruct(..)
293             | PatKind::Tuple(..)
294             | PatKind::Box(_)
295             | PatKind::Range(..)
296             | PatKind::Slice(..) => AdjustMode::Peel,
297             // String and byte-string literals result in types `&str` and `&[u8]` respectively.
298             // All other literals result in non-reference types.
299             // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo {}`.
300             //
301             // Call `resolve_vars_if_possible` here for inline const blocks.
302             PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() {
303                 ty::Ref(..) => AdjustMode::Pass,
304                 _ => AdjustMode::Peel,
305             },
306             PatKind::Path(_) => match opt_path_res.unwrap() {
307                 // These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
308                 // Peeling the reference types too early will cause type checking failures.
309                 // Although it would be possible to *also* peel the types of the constants too.
310                 Res::Def(DefKind::Const | DefKind::AssocConst, _) => AdjustMode::Pass,
311                 // In the `ValueNS`, we have `SelfCtor(..) | Ctor(_, Const), _)` remaining which
312                 // could successfully compile. The former being `Self` requires a unit struct.
313                 // In either case, and unlike constants, the pattern itself cannot be
314                 // a reference type wherefore peeling doesn't give up any expressiveness.
315                 _ => AdjustMode::Peel,
316             },
317             // When encountering a `& mut? pat` pattern, reset to "by value".
318             // This is so that `x` and `y` here are by value, as they appear to be:
319             //
320             // ```
321             // match &(&22, &44) {
322             //   (&x, &y) => ...
323             // }
324             // ```
325             //
326             // See issue #46688.
327             PatKind::Ref(..) => AdjustMode::Reset,
328             // A `_` pattern works with any expected type, so there's no need to do anything.
329             PatKind::Wild
330             // Bindings also work with whatever the expected type is,
331             // and moreover if we peel references off, that will give us the wrong binding type.
332             // Also, we can have a subpattern `binding @ pat`.
333             // Each side of the `@` should be treated independently (like with OR-patterns).
334             | PatKind::Binding(..)
335             // An OR-pattern just propagates to each individual alternative.
336             // This is maximally flexible, allowing e.g., `Some(mut x) | &Some(mut x)`.
337             // In that example, `Some(mut x)` results in `Peel` whereas `&Some(mut x)` in `Reset`.
338             | PatKind::Or(_) => AdjustMode::Pass,
339         }
340     }
341
342     /// Peel off as many immediately nested `& mut?` from the expected type as possible
343     /// and return the new expected type and binding default binding mode.
344     /// The adjustments vector, if non-empty is stored in a table.
345     fn peel_off_references(
346         &self,
347         pat: &'tcx Pat<'tcx>,
348         expected: Ty<'tcx>,
349         mut def_bm: BindingMode,
350     ) -> (Ty<'tcx>, BindingMode) {
351         let mut expected = self.resolve_vars_with_obligations(expected);
352
353         // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
354         // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
355         // the `Some(5)` which is not of type Ref.
356         //
357         // For each ampersand peeled off, update the binding mode and push the original
358         // type into the adjustments vector.
359         //
360         // See the examples in `ui/match-defbm*.rs`.
361         let mut pat_adjustments = vec![];
362         while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
363             debug!("inspecting {:?}", expected);
364
365             debug!("current discriminant is Ref, inserting implicit deref");
366             // Preserve the reference type. We'll need it later during THIR lowering.
367             pat_adjustments.push(expected);
368
369             expected = inner_ty;
370             def_bm = ty::BindByReference(match def_bm {
371                 // If default binding mode is by value, make it `ref` or `ref mut`
372                 // (depending on whether we observe `&` or `&mut`).
373                 ty::BindByValue(_) |
374                 // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
375                 ty::BindByReference(hir::Mutability::Mut) => inner_mutability,
376                 // Once a `ref`, always a `ref`.
377                 // This is because a `& &mut` cannot mutate the underlying value.
378                 ty::BindByReference(m @ hir::Mutability::Not) => m,
379             });
380         }
381
382         if !pat_adjustments.is_empty() {
383             debug!("default binding mode is now {:?}", def_bm);
384             self.inh
385                 .typeck_results
386                 .borrow_mut()
387                 .pat_adjustments_mut()
388                 .insert(pat.hir_id, pat_adjustments);
389         }
390
391         (expected, def_bm)
392     }
393
394     fn check_pat_lit(
395         &self,
396         span: Span,
397         lt: &hir::Expr<'tcx>,
398         expected: Ty<'tcx>,
399         ti: TopInfo<'tcx>,
400     ) -> Ty<'tcx> {
401         // We've already computed the type above (when checking for a non-ref pat),
402         // so avoid computing it again.
403         let ty = self.node_ty(lt.hir_id);
404
405         // Byte string patterns behave the same way as array patterns
406         // They can denote both statically and dynamically-sized byte arrays.
407         let mut pat_ty = ty;
408         if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(_), .. }) = lt.kind {
409             let expected = self.structurally_resolved_type(span, expected);
410             if let ty::Ref(_, inner_ty, _) = expected.kind()
411                 && matches!(inner_ty.kind(), ty::Slice(_))
412             {
413                 let tcx = self.tcx;
414                 trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
415                 self.typeck_results
416                     .borrow_mut()
417                     .treat_byte_string_as_slice
418                     .insert(lt.hir_id.local_id);
419                 pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_slice(tcx.types.u8));
420             }
421         }
422
423         // Somewhat surprising: in this case, the subtyping relation goes the
424         // opposite way as the other cases. Actually what we really want is not
425         // a subtyping relation at all but rather that there exists a LUB
426         // (so that they can be compared). However, in practice, constants are
427         // always scalars or strings. For scalars subtyping is irrelevant,
428         // and for strings `ty` is type is `&'static str`, so if we say that
429         //
430         //     &'static str <: expected
431         //
432         // then that's equivalent to there existing a LUB.
433         let cause = self.pattern_cause(ti, span);
434         if let Some(mut err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
435             err.emit_unless(
436                 ti.span
437                     .filter(|&s| {
438                         // In the case of `if`- and `while`-expressions we've already checked
439                         // that `scrutinee: bool`. We know that the pattern is `true`,
440                         // so an error here would be a duplicate and from the wrong POV.
441                         s.is_desugaring(DesugaringKind::CondTemporary)
442                     })
443                     .is_some(),
444             );
445         }
446
447         pat_ty
448     }
449
450     fn check_pat_range(
451         &self,
452         span: Span,
453         lhs: Option<&'tcx hir::Expr<'tcx>>,
454         rhs: Option<&'tcx hir::Expr<'tcx>>,
455         expected: Ty<'tcx>,
456         ti: TopInfo<'tcx>,
457     ) -> Ty<'tcx> {
458         let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr {
459             None => None,
460             Some(expr) => {
461                 let ty = self.check_expr(expr);
462                 // Check that the end-point is possibly of numeric or char type.
463                 // The early check here is not for correctness, but rather better
464                 // diagnostics (e.g. when `&str` is being matched, `expected` will
465                 // be peeled to `str` while ty here is still `&str`, if we don't
466                 // err early here, a rather confusing unification error will be
467                 // emitted instead).
468                 let fail =
469                     !(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error());
470                 Some((fail, ty, expr.span))
471             }
472         };
473         let mut lhs = calc_side(lhs);
474         let mut rhs = calc_side(rhs);
475
476         if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
477             // There exists a side that didn't meet our criteria that the end-point
478             // be of a numeric or char type, as checked in `calc_side` above.
479             self.emit_err_pat_range(span, lhs, rhs);
480             return self.tcx.ty_error();
481         }
482
483         // Unify each side with `expected`.
484         // Subtyping doesn't matter here, as the value is some kind of scalar.
485         let demand_eqtype = |x: &mut _, y| {
486             if let Some((ref mut fail, x_ty, x_span)) = *x
487                 && let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
488             {
489                 if let Some((_, y_ty, y_span)) = y {
490                     self.endpoint_has_type(&mut err, y_span, y_ty);
491                 }
492                 err.emit();
493                 *fail = true;
494             }
495         };
496         demand_eqtype(&mut lhs, rhs);
497         demand_eqtype(&mut rhs, lhs);
498
499         if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
500             return self.tcx.ty_error();
501         }
502
503         // Find the unified type and check if it's of numeric or char type again.
504         // This check is needed if both sides are inference variables.
505         // We require types to be resolved here so that we emit inference failure
506         // rather than "_ is not a char or numeric".
507         let ty = self.structurally_resolved_type(span, expected);
508         if !(ty.is_numeric() || ty.is_char() || ty.references_error()) {
509             if let Some((ref mut fail, _, _)) = lhs {
510                 *fail = true;
511             }
512             if let Some((ref mut fail, _, _)) = rhs {
513                 *fail = true;
514             }
515             self.emit_err_pat_range(span, lhs, rhs);
516             return self.tcx.ty_error();
517         }
518         ty
519     }
520
521     fn endpoint_has_type(&self, err: &mut Diagnostic, span: Span, ty: Ty<'_>) {
522         if !ty.references_error() {
523             err.span_label(span, &format!("this is of type `{}`", ty));
524         }
525     }
526
527     fn emit_err_pat_range(
528         &self,
529         span: Span,
530         lhs: Option<(bool, Ty<'tcx>, Span)>,
531         rhs: Option<(bool, Ty<'tcx>, Span)>,
532     ) {
533         let span = match (lhs, rhs) {
534             (Some((true, ..)), Some((true, ..))) => span,
535             (Some((true, _, sp)), _) => sp,
536             (_, Some((true, _, sp))) => sp,
537             _ => span_bug!(span, "emit_err_pat_range: no side failed or exists but still error?"),
538         };
539         let mut err = struct_span_err!(
540             self.tcx.sess,
541             span,
542             E0029,
543             "only `char` and numeric types are allowed in range patterns"
544         );
545         let msg = |ty| {
546             let ty = self.resolve_vars_if_possible(ty);
547             format!("this is of type `{}` but it should be `char` or numeric", ty)
548         };
549         let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| {
550             err.span_label(first_span, &msg(first_ty));
551             if let Some((_, ty, sp)) = second {
552                 let ty = self.resolve_vars_if_possible(ty);
553                 self.endpoint_has_type(&mut err, sp, ty);
554             }
555         };
556         match (lhs, rhs) {
557             (Some((true, lhs_ty, lhs_sp)), Some((true, rhs_ty, rhs_sp))) => {
558                 err.span_label(lhs_sp, &msg(lhs_ty));
559                 err.span_label(rhs_sp, &msg(rhs_ty));
560             }
561             (Some((true, lhs_ty, lhs_sp)), rhs) => one_side_err(lhs_sp, lhs_ty, rhs),
562             (lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs),
563             _ => span_bug!(span, "Impossible, verified above."),
564         }
565         if self.tcx.sess.teach(&err.get_code().unwrap()) {
566             err.note(
567                 "In a match expression, only numbers and characters can be matched \
568                     against a range. This is because the compiler checks that the range \
569                     is non-empty at compile-time, and is unable to evaluate arbitrary \
570                     comparison functions. If you want to capture values of an orderable \
571                     type between two end-points, you can use a guard.",
572             );
573         }
574         err.emit();
575     }
576
577     fn check_pat_ident(
578         &self,
579         pat: &'tcx Pat<'tcx>,
580         ba: hir::BindingAnnotation,
581         var_id: HirId,
582         sub: Option<&'tcx Pat<'tcx>>,
583         expected: Ty<'tcx>,
584         def_bm: BindingMode,
585         ti: TopInfo<'tcx>,
586     ) -> Ty<'tcx> {
587         // Determine the binding mode...
588         let bm = match ba {
589             hir::BindingAnnotation::Unannotated => def_bm,
590             _ => BindingMode::convert(ba),
591         };
592         // ...and store it in a side table:
593         self.inh.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
594
595         debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
596
597         let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
598         let eq_ty = match bm {
599             ty::BindByReference(mutbl) => {
600                 // If the binding is like `ref x | ref mut x`,
601                 // then `x` is assigned a value of type `&M T` where M is the
602                 // mutability and T is the expected type.
603                 //
604                 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)`
605                 // is required. However, we use equality, which is stronger.
606                 // See (note_1) for an explanation.
607                 self.new_ref_ty(pat.span, mutbl, expected)
608             }
609             // Otherwise, the type of x is the expected type `T`.
610             ty::BindByValue(_) => {
611                 // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
612                 expected
613             }
614         };
615         self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
616
617         // If there are multiple arms, make sure they all agree on
618         // what the type of the binding `x` ought to be.
619         if var_id != pat.hir_id {
620             self.check_binding_alt_eq_ty(pat.span, var_id, local_ty, ti);
621         }
622
623         if let Some(p) = sub {
624             self.check_pat(p, expected, def_bm, TopInfo { parent_pat: Some(pat), ..ti });
625         }
626
627         local_ty
628     }
629
630     fn check_binding_alt_eq_ty(&self, span: Span, var_id: HirId, ty: Ty<'tcx>, ti: TopInfo<'tcx>) {
631         let var_ty = self.local_ty(span, var_id).decl_ty;
632         if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
633             let hir = self.tcx.hir();
634             let var_ty = self.resolve_vars_with_obligations(var_ty);
635             let msg = format!("first introduced with type `{var_ty}` here");
636             err.span_label(hir.span(var_id), msg);
637             let in_match = hir.parent_iter(var_id).any(|(_, n)| {
638                 matches!(
639                     n,
640                     hir::Node::Expr(hir::Expr {
641                         kind: hir::ExprKind::Match(.., hir::MatchSource::Normal),
642                         ..
643                     })
644                 )
645             });
646             let pre = if in_match { "in the same arm, " } else { "" };
647             err.note(&format!("{}a binding must have the same type in all alternatives", pre));
648             // FIXME: check if `var_ty` and `ty` can be made the same type by adding or removing
649             // `ref` or `&` to the pattern.
650             err.emit();
651         }
652     }
653
654     // Precondition: pat is a Ref(_) pattern
655     fn borrow_pat_suggestion(&self, err: &mut Diagnostic, pat: &Pat<'_>) {
656         let tcx = self.tcx;
657         if let PatKind::Ref(inner, mutbl) = pat.kind
658         && let PatKind::Binding(_, _, binding, ..) = inner.kind {
659             let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id);
660             let binding_parent = tcx.hir().get(binding_parent_id);
661             debug!(?inner, ?pat, ?binding_parent);
662
663             let mutability = match mutbl {
664                 ast::Mutability::Mut => "mut",
665                 ast::Mutability::Not => "",
666             };
667
668             let mut_var_suggestion = 'block: {
669                 if !matches!(mutbl, ast::Mutability::Mut) {
670                     break 'block None;
671                 }
672
673                 let ident_kind = match binding_parent {
674                     hir::Node::Param(_) => "parameter",
675                     hir::Node::Local(_) => "variable",
676                     hir::Node::Arm(_) => "binding",
677
678                     // Provide diagnostics only if the parent pattern is struct-like,
679                     // i.e. where `mut binding` makes sense
680                     hir::Node::Pat(Pat { kind, .. }) => match kind {
681                         PatKind::Struct(..)
682                         | PatKind::TupleStruct(..)
683                         | PatKind::Or(..)
684                         | PatKind::Tuple(..)
685                         | PatKind::Slice(..) => "binding",
686
687                         PatKind::Wild
688                         | PatKind::Binding(..)
689                         | PatKind::Path(..)
690                         | PatKind::Box(..)
691                         | PatKind::Ref(..)
692                         | PatKind::Lit(..)
693                         | PatKind::Range(..) => break 'block None,
694                     },
695
696                     // Don't provide suggestions in other cases
697                     _ => break 'block None,
698                 };
699
700                 Some((
701                     pat.span,
702                     format!("to declare a mutable {ident_kind} use"),
703                     format!("mut {binding}"),
704                 ))
705
706             };
707
708             match binding_parent {
709                 // Check that there is explicit type (ie this is not a closure param with inferred type)
710                 // so we don't suggest moving something to the type that does not exist
711                 hir::Node::Param(hir::Param { ty_span, .. }) if binding.span != *ty_span => {
712                     err.multipart_suggestion_verbose(
713                         format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"),
714                         vec![
715                             (pat.span.until(inner.span), "".to_owned()),
716                             (ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())),
717                         ],
718                         Applicability::MachineApplicable
719                     );
720
721                     if let Some((sp, msg, sugg)) = mut_var_suggestion {
722                         err.span_note(sp, format!("{msg}: `{sugg}`"));
723                     }
724                 }
725                 hir::Node::Param(_) | hir::Node::Arm(_) | hir::Node::Pat(_) => {
726                     // rely on match ergonomics or it might be nested `&&pat`
727                     err.span_suggestion_verbose(
728                         pat.span.until(inner.span),
729                         format!("consider removing `&{mutability}` from the pattern"),
730                         "",
731                         Applicability::MaybeIncorrect,
732                     );
733
734                     if let Some((sp, msg, sugg)) = mut_var_suggestion {
735                         err.span_note(sp, format!("{msg}: `{sugg}`"));
736                     }
737                 }
738                 _ if let Some((sp, msg, sugg)) = mut_var_suggestion => {
739                     err.span_suggestion(sp, msg, sugg, Applicability::MachineApplicable);
740                 }
741                 _ => {} // don't provide suggestions in other cases #55175
742             }
743         }
744     }
745
746     pub fn check_dereferenceable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat<'_>) -> bool {
747         if let PatKind::Binding(..) = inner.kind
748             && let Some(mt) = self.shallow_resolve(expected).builtin_deref(true)
749             && let ty::Dynamic(..) = mt.ty.kind()
750         {
751                     // This is "x = SomeTrait" being reduced from
752                     // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
753                     let type_str = self.ty_to_string(expected);
754                     let mut err = struct_span_err!(
755                         self.tcx.sess,
756                         span,
757                         E0033,
758                         "type `{}` cannot be dereferenced",
759                         type_str
760                     );
761                     err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
762                     if self.tcx.sess.teach(&err.get_code().unwrap()) {
763                         err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
764                     }
765                     err.emit();
766                     return false;
767                 }
768         true
769     }
770
771     fn check_pat_struct(
772         &self,
773         pat: &'tcx Pat<'tcx>,
774         qpath: &hir::QPath<'_>,
775         fields: &'tcx [hir::PatField<'tcx>],
776         has_rest_pat: bool,
777         expected: Ty<'tcx>,
778         def_bm: BindingMode,
779         ti: TopInfo<'tcx>,
780     ) -> Ty<'tcx> {
781         // Resolve the path and check the definition for errors.
782         let Some((variant, pat_ty)) = self.check_struct_path(qpath, pat.hir_id) else {
783             let err = self.tcx.ty_error();
784             for field in fields {
785                 let ti = TopInfo { parent_pat: Some(pat), ..ti };
786                 self.check_pat(field.pat, err, def_bm, ti);
787             }
788             return err;
789         };
790
791         // Type-check the path.
792         self.demand_eqtype_pat(pat.span, expected, pat_ty, ti);
793
794         // Type-check subpatterns.
795         if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, has_rest_pat, def_bm, ti) {
796             pat_ty
797         } else {
798             self.tcx.ty_error()
799         }
800     }
801
802     fn check_pat_path<'b>(
803         &self,
804         pat: &Pat<'_>,
805         qpath: &hir::QPath<'_>,
806         path_resolution: (Res, Option<Ty<'tcx>>, &'b [hir::PathSegment<'b>]),
807         expected: Ty<'tcx>,
808         ti: TopInfo<'tcx>,
809     ) -> Ty<'tcx> {
810         let tcx = self.tcx;
811
812         // We have already resolved the path.
813         let (res, opt_ty, segments) = path_resolution;
814         match res {
815             Res::Err => {
816                 self.set_tainted_by_errors();
817                 return tcx.ty_error();
818             }
819             Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fictive | CtorKind::Fn), _) => {
820                 report_unexpected_variant_res(tcx, res, qpath, pat.span);
821                 return tcx.ty_error();
822             }
823             Res::SelfCtor(..)
824             | Res::Def(
825                 DefKind::Ctor(_, CtorKind::Const)
826                 | DefKind::Const
827                 | DefKind::AssocConst
828                 | DefKind::ConstParam,
829                 _,
830             ) => {} // OK
831             _ => bug!("unexpected pattern resolution: {:?}", res),
832         }
833
834         // Type-check the path.
835         let (pat_ty, pat_res) =
836             self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id);
837         if let Some(err) =
838             self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
839         {
840             self.emit_bad_pat_path(err, pat.span, res, pat_res, pat_ty, segments, ti.parent_pat);
841         }
842         pat_ty
843     }
844
845     fn maybe_suggest_range_literal(
846         &self,
847         e: &mut Diagnostic,
848         opt_def_id: Option<hir::def_id::DefId>,
849         ident: Ident,
850     ) -> bool {
851         match opt_def_id {
852             Some(def_id) => match self.tcx.hir().get_if_local(def_id) {
853                 Some(hir::Node::Item(hir::Item {
854                     kind: hir::ItemKind::Const(_, body_id), ..
855                 })) => match self.tcx.hir().get(body_id.hir_id) {
856                     hir::Node::Expr(expr) => {
857                         if hir::is_range_literal(expr) {
858                             let span = self.tcx.hir().span(body_id.hir_id);
859                             if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) {
860                                 e.span_suggestion_verbose(
861                                     ident.span,
862                                     "you may want to move the range into the match block",
863                                     snip,
864                                     Applicability::MachineApplicable,
865                                 );
866                                 return true;
867                             }
868                         }
869                     }
870                     _ => (),
871                 },
872                 _ => (),
873             },
874             _ => (),
875         }
876         false
877     }
878
879     fn emit_bad_pat_path<'b>(
880         &self,
881         mut e: DiagnosticBuilder<'_, ErrorGuaranteed>,
882         pat_span: Span,
883         res: Res,
884         pat_res: Res,
885         pat_ty: Ty<'tcx>,
886         segments: &'b [hir::PathSegment<'b>],
887         parent_pat: Option<&Pat<'_>>,
888     ) {
889         if let Some(span) = self.tcx.hir().res_span(pat_res) {
890             e.span_label(span, &format!("{} defined here", res.descr()));
891             if let [hir::PathSegment { ident, .. }] = &*segments {
892                 e.span_label(
893                     pat_span,
894                     &format!(
895                         "`{}` is interpreted as {} {}, not a new binding",
896                         ident,
897                         res.article(),
898                         res.descr(),
899                     ),
900                 );
901                 match parent_pat {
902                     Some(Pat { kind: hir::PatKind::Struct(..), .. }) => {
903                         e.span_suggestion_verbose(
904                             ident.span.shrink_to_hi(),
905                             "bind the struct field to a different name instead",
906                             format!(": other_{}", ident.as_str().to_lowercase()),
907                             Applicability::HasPlaceholders,
908                         );
909                     }
910                     _ => {
911                         let (type_def_id, item_def_id) = match pat_ty.kind() {
912                             Adt(def, _) => match res {
913                                 Res::Def(DefKind::Const, def_id) => (Some(def.did()), Some(def_id)),
914                                 _ => (None, None),
915                             },
916                             _ => (None, None),
917                         };
918
919                         let ranges = &[
920                             self.tcx.lang_items().range_struct(),
921                             self.tcx.lang_items().range_from_struct(),
922                             self.tcx.lang_items().range_to_struct(),
923                             self.tcx.lang_items().range_full_struct(),
924                             self.tcx.lang_items().range_inclusive_struct(),
925                             self.tcx.lang_items().range_to_inclusive_struct(),
926                         ];
927                         if type_def_id != None && ranges.contains(&type_def_id) {
928                             if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
929                                 let msg = "constants only support matching by type, \
930                                     if you meant to match against a range of values, \
931                                     consider using a range pattern like `min ..= max` in the match block";
932                                 e.note(msg);
933                             }
934                         } else {
935                             let msg = "introduce a new binding instead";
936                             let sugg = format!("other_{}", ident.as_str().to_lowercase());
937                             e.span_suggestion(
938                                 ident.span,
939                                 msg,
940                                 sugg,
941                                 Applicability::HasPlaceholders,
942                             );
943                         }
944                     }
945                 };
946             }
947         }
948         e.emit();
949     }
950
951     fn check_pat_tuple_struct(
952         &self,
953         pat: &'tcx Pat<'tcx>,
954         qpath: &'tcx hir::QPath<'tcx>,
955         subpats: &'tcx [Pat<'tcx>],
956         ddpos: Option<usize>,
957         expected: Ty<'tcx>,
958         def_bm: BindingMode,
959         ti: TopInfo<'tcx>,
960     ) -> Ty<'tcx> {
961         let tcx = self.tcx;
962         let on_error = || {
963             let parent_pat = Some(pat);
964             for pat in subpats {
965                 self.check_pat(pat, tcx.ty_error(), def_bm, TopInfo { parent_pat, ..ti });
966             }
967         };
968         let report_unexpected_res = |res: Res| {
969             let sm = tcx.sess.source_map();
970             let path_str = sm
971                 .span_to_snippet(sm.span_until_char(pat.span, '('))
972                 .map_or_else(|_| String::new(), |s| format!(" `{}`", s.trim_end()));
973             let msg = format!(
974                 "expected tuple struct or tuple variant, found {}{}",
975                 res.descr(),
976                 path_str
977             );
978
979             let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{msg}");
980             match res {
981                 Res::Def(DefKind::Fn | DefKind::AssocFn, _) => {
982                     err.span_label(pat.span, "`fn` calls are not allowed in patterns");
983                     err.help(
984                         "for more information, visit \
985                               https://doc.rust-lang.org/book/ch18-00-patterns.html",
986                     );
987                 }
988                 _ => {
989                     err.span_label(pat.span, "not a tuple variant or struct");
990                 }
991             }
992             err.emit();
993             on_error();
994         };
995
996         // Resolve the path and check the definition for errors.
997         let (res, opt_ty, segments) =
998             self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
999         if res == Res::Err {
1000             self.set_tainted_by_errors();
1001             on_error();
1002             return self.tcx.ty_error();
1003         }
1004
1005         // Type-check the path.
1006         let (pat_ty, res) =
1007             self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id);
1008         if !pat_ty.is_fn() {
1009             report_unexpected_res(res);
1010             return tcx.ty_error();
1011         }
1012
1013         let variant = match res {
1014             Res::Err => {
1015                 self.set_tainted_by_errors();
1016                 on_error();
1017                 return tcx.ty_error();
1018             }
1019             Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
1020                 report_unexpected_res(res);
1021                 return tcx.ty_error();
1022             }
1023             Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
1024             _ => bug!("unexpected pattern resolution: {:?}", res),
1025         };
1026
1027         // Replace constructor type with constructed type for tuple struct patterns.
1028         let pat_ty = pat_ty.fn_sig(tcx).output();
1029         let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1030
1031         // Type-check the tuple struct pattern against the expected type.
1032         let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, ti);
1033         let had_err = if let Some(mut err) = diag {
1034             err.emit();
1035             true
1036         } else {
1037             false
1038         };
1039
1040         // Type-check subpatterns.
1041         if subpats.len() == variant.fields.len()
1042             || subpats.len() < variant.fields.len() && ddpos.is_some()
1043         {
1044             let ty::Adt(_, substs) = pat_ty.kind() else {
1045                 bug!("unexpected pattern type {:?}", pat_ty);
1046             };
1047             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
1048                 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
1049                 self.check_pat(subpat, field_ty, def_bm, TopInfo { parent_pat: Some(pat), ..ti });
1050
1051                 self.tcx.check_stability(
1052                     variant.fields[i].did,
1053                     Some(pat.hir_id),
1054                     subpat.span,
1055                     None,
1056                 );
1057             }
1058         } else {
1059             // Pattern has wrong number of fields.
1060             self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
1061             on_error();
1062             return tcx.ty_error();
1063         }
1064         pat_ty
1065     }
1066
1067     fn e0023(
1068         &self,
1069         pat_span: Span,
1070         res: Res,
1071         qpath: &hir::QPath<'_>,
1072         subpats: &'tcx [Pat<'tcx>],
1073         fields: &'tcx [ty::FieldDef],
1074         expected: Ty<'tcx>,
1075         had_err: bool,
1076     ) {
1077         let subpats_ending = pluralize!(subpats.len());
1078         let fields_ending = pluralize!(fields.len());
1079
1080         let subpat_spans = if subpats.is_empty() {
1081             vec![pat_span]
1082         } else {
1083             subpats.iter().map(|p| p.span).collect()
1084         };
1085         let last_subpat_span = *subpat_spans.last().unwrap();
1086         let res_span = self.tcx.def_span(res.def_id());
1087         let def_ident_span = self.tcx.def_ident_span(res.def_id()).unwrap_or(res_span);
1088         let field_def_spans = if fields.is_empty() {
1089             vec![res_span]
1090         } else {
1091             fields.iter().map(|f| f.ident(self.tcx).span).collect()
1092         };
1093         let last_field_def_span = *field_def_spans.last().unwrap();
1094
1095         let mut err = struct_span_err!(
1096             self.tcx.sess,
1097             MultiSpan::from_spans(subpat_spans),
1098             E0023,
1099             "this pattern has {} field{}, but the corresponding {} has {} field{}",
1100             subpats.len(),
1101             subpats_ending,
1102             res.descr(),
1103             fields.len(),
1104             fields_ending,
1105         );
1106         err.span_label(
1107             last_subpat_span,
1108             &format!("expected {} field{}, found {}", fields.len(), fields_ending, subpats.len()),
1109         );
1110         if self.tcx.sess.source_map().is_multiline(qpath.span().between(last_subpat_span)) {
1111             err.span_label(qpath.span(), "");
1112         }
1113         if self.tcx.sess.source_map().is_multiline(def_ident_span.between(last_field_def_span)) {
1114             err.span_label(def_ident_span, format!("{} defined here", res.descr()));
1115         }
1116         for span in &field_def_spans[..field_def_spans.len() - 1] {
1117             err.span_label(*span, "");
1118         }
1119         err.span_label(
1120             last_field_def_span,
1121             &format!("{} has {} field{}", res.descr(), fields.len(), fields_ending),
1122         );
1123
1124         // Identify the case `Some(x, y)` where the expected type is e.g. `Option<(T, U)>`.
1125         // More generally, the expected type wants a tuple variant with one field of an
1126         // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
1127         // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
1128         let missing_parentheses = match (&expected.kind(), fields, had_err) {
1129             // #67037: only do this if we could successfully type-check the expected type against
1130             // the tuple struct pattern. Otherwise the substs could get out of range on e.g.,
1131             // `let P() = U;` where `P != U` with `struct P<T>(T);`.
1132             (ty::Adt(_, substs), [field], false) => {
1133                 let field_ty = self.field_ty(pat_span, field, substs);
1134                 match field_ty.kind() {
1135                     ty::Tuple(fields) => fields.len() == subpats.len(),
1136                     _ => false,
1137                 }
1138             }
1139             _ => false,
1140         };
1141         if missing_parentheses {
1142             let (left, right) = match subpats {
1143                 // This is the zero case; we aim to get the "hi" part of the `QPath`'s
1144                 // span as the "lo" and then the "hi" part of the pattern's span as the "hi".
1145                 // This looks like:
1146                 //
1147                 // help: missing parentheses
1148                 //   |
1149                 // L |     let A(()) = A(());
1150                 //   |          ^  ^
1151                 [] => (qpath.span().shrink_to_hi(), pat_span),
1152                 // Easy case. Just take the "lo" of the first sub-pattern and the "hi" of the
1153                 // last sub-pattern. In the case of `A(x)` the first and last may coincide.
1154                 // This looks like:
1155                 //
1156                 // help: missing parentheses
1157                 //   |
1158                 // L |     let A((x, y)) = A((1, 2));
1159                 //   |           ^    ^
1160                 [first, ..] => (first.span.shrink_to_lo(), subpats.last().unwrap().span),
1161             };
1162             err.multipart_suggestion(
1163                 "missing parentheses",
1164                 vec![(left, "(".to_string()), (right.shrink_to_hi(), ")".to_string())],
1165                 Applicability::MachineApplicable,
1166             );
1167         } else if fields.len() > subpats.len() && pat_span != DUMMY_SP {
1168             let after_fields_span = pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi();
1169             let all_fields_span = match subpats {
1170                 [] => after_fields_span,
1171                 [field] => field.span,
1172                 [first, .., last] => first.span.to(last.span),
1173             };
1174
1175             // Check if all the fields in the pattern are wildcards.
1176             let all_wildcards = subpats.iter().all(|pat| matches!(pat.kind, PatKind::Wild));
1177             let first_tail_wildcard =
1178                 subpats.iter().enumerate().fold(None, |acc, (pos, pat)| match (acc, &pat.kind) {
1179                     (None, PatKind::Wild) => Some(pos),
1180                     (Some(_), PatKind::Wild) => acc,
1181                     _ => None,
1182                 });
1183             let tail_span = match first_tail_wildcard {
1184                 None => after_fields_span,
1185                 Some(0) => subpats[0].span.to(after_fields_span),
1186                 Some(pos) => subpats[pos - 1].span.shrink_to_hi().to(after_fields_span),
1187             };
1188
1189             // FIXME: heuristic-based suggestion to check current types for where to add `_`.
1190             let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", ");
1191             if !subpats.is_empty() {
1192                 wildcard_sugg = String::from(", ") + &wildcard_sugg;
1193             }
1194
1195             err.span_suggestion_verbose(
1196                 after_fields_span,
1197                 "use `_` to explicitly ignore each field",
1198                 wildcard_sugg,
1199                 Applicability::MaybeIncorrect,
1200             );
1201
1202             // Only suggest `..` if more than one field is missing
1203             // or the pattern consists of all wildcards.
1204             if fields.len() - subpats.len() > 1 || all_wildcards {
1205                 if subpats.is_empty() || all_wildcards {
1206                     err.span_suggestion_verbose(
1207                         all_fields_span,
1208                         "use `..` to ignore all fields",
1209                         "..",
1210                         Applicability::MaybeIncorrect,
1211                     );
1212                 } else {
1213                     err.span_suggestion_verbose(
1214                         tail_span,
1215                         "use `..` to ignore the rest of the fields",
1216                         ", ..",
1217                         Applicability::MaybeIncorrect,
1218                     );
1219                 }
1220             }
1221         }
1222
1223         err.emit();
1224     }
1225
1226     fn check_pat_tuple(
1227         &self,
1228         span: Span,
1229         elements: &'tcx [Pat<'tcx>],
1230         ddpos: Option<usize>,
1231         expected: Ty<'tcx>,
1232         def_bm: BindingMode,
1233         ti: TopInfo<'tcx>,
1234     ) -> Ty<'tcx> {
1235         let tcx = self.tcx;
1236         let mut expected_len = elements.len();
1237         if ddpos.is_some() {
1238             // Require known type only when `..` is present.
1239             if let ty::Tuple(tys) = self.structurally_resolved_type(span, expected).kind() {
1240                 expected_len = tys.len();
1241             }
1242         }
1243         let max_len = cmp::max(expected_len, elements.len());
1244
1245         let element_tys_iter = (0..max_len).map(|_| {
1246             self.next_ty_var(
1247                 // FIXME: `MiscVariable` for now -- obtaining the span and name information
1248                 // from all tuple elements isn't trivial.
1249                 TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span },
1250             )
1251         });
1252         let element_tys = tcx.mk_type_list(element_tys_iter);
1253         let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
1254         if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) {
1255             err.emit();
1256             // Walk subpatterns with an expected type of `err` in this case to silence
1257             // further errors being emitted when using the bindings. #50333
1258             let element_tys_iter = (0..max_len).map(|_| tcx.ty_error());
1259             for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
1260                 self.check_pat(elem, tcx.ty_error(), def_bm, ti);
1261             }
1262             tcx.mk_tup(element_tys_iter)
1263         } else {
1264             for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
1265                 self.check_pat(elem, element_tys[i], def_bm, ti);
1266             }
1267             pat_ty
1268         }
1269     }
1270
1271     fn check_struct_pat_fields(
1272         &self,
1273         adt_ty: Ty<'tcx>,
1274         pat: &'tcx Pat<'tcx>,
1275         variant: &'tcx ty::VariantDef,
1276         fields: &'tcx [hir::PatField<'tcx>],
1277         has_rest_pat: bool,
1278         def_bm: BindingMode,
1279         ti: TopInfo<'tcx>,
1280     ) -> bool {
1281         let tcx = self.tcx;
1282
1283         let ty::Adt(adt, substs) = adt_ty.kind() else {
1284             span_bug!(pat.span, "struct pattern is not an ADT");
1285         };
1286
1287         // Index the struct fields' types.
1288         let field_map = variant
1289             .fields
1290             .iter()
1291             .enumerate()
1292             .map(|(i, field)| (field.ident(self.tcx).normalize_to_macros_2_0(), (i, field)))
1293             .collect::<FxHashMap<_, _>>();
1294
1295         // Keep track of which fields have already appeared in the pattern.
1296         let mut used_fields = FxHashMap::default();
1297         let mut no_field_errors = true;
1298
1299         let mut inexistent_fields = vec![];
1300         // Typecheck each field.
1301         for field in fields {
1302             let span = field.span;
1303             let ident = tcx.adjust_ident(field.ident, variant.def_id);
1304             let field_ty = match used_fields.entry(ident) {
1305                 Occupied(occupied) => {
1306                     self.error_field_already_bound(span, field.ident, *occupied.get());
1307                     no_field_errors = false;
1308                     tcx.ty_error()
1309                 }
1310                 Vacant(vacant) => {
1311                     vacant.insert(span);
1312                     field_map
1313                         .get(&ident)
1314                         .map(|(i, f)| {
1315                             self.write_field_index(field.hir_id, *i);
1316                             self.tcx.check_stability(f.did, Some(pat.hir_id), span, None);
1317                             self.field_ty(span, f, substs)
1318                         })
1319                         .unwrap_or_else(|| {
1320                             inexistent_fields.push(field);
1321                             no_field_errors = false;
1322                             tcx.ty_error()
1323                         })
1324                 }
1325             };
1326
1327             self.check_pat(field.pat, field_ty, def_bm, TopInfo { parent_pat: Some(pat), ..ti });
1328         }
1329
1330         let mut unmentioned_fields = variant
1331             .fields
1332             .iter()
1333             .map(|field| (field, field.ident(self.tcx).normalize_to_macros_2_0()))
1334             .filter(|(_, ident)| !used_fields.contains_key(ident))
1335             .collect::<Vec<_>>();
1336
1337         let inexistent_fields_err = if !(inexistent_fields.is_empty() || variant.is_recovered())
1338             && !inexistent_fields.iter().any(|field| field.ident.name == kw::Underscore)
1339         {
1340             Some(self.error_inexistent_fields(
1341                 adt.variant_descr(),
1342                 &inexistent_fields,
1343                 &mut unmentioned_fields,
1344                 variant,
1345                 substs,
1346             ))
1347         } else {
1348             None
1349         };
1350
1351         // Require `..` if struct has non_exhaustive attribute.
1352         let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local();
1353         if non_exhaustive && !has_rest_pat {
1354             self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty());
1355         }
1356
1357         let mut unmentioned_err = None;
1358         // Report an error if an incorrect number of fields was specified.
1359         if adt.is_union() {
1360             if fields.len() != 1 {
1361                 tcx.sess
1362                     .struct_span_err(pat.span, "union patterns should have exactly one field")
1363                     .emit();
1364             }
1365             if has_rest_pat {
1366                 tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
1367             }
1368         } else if !unmentioned_fields.is_empty() {
1369             let accessible_unmentioned_fields: Vec<_> = unmentioned_fields
1370                 .iter()
1371                 .copied()
1372                 .filter(|(field, _)| {
1373                     field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
1374                         && !matches!(
1375                             tcx.eval_stability(field.did, None, DUMMY_SP, None),
1376                             EvalResult::Deny { .. }
1377                         )
1378                         // We only want to report the error if it is hidden and not local
1379                         && !(tcx.is_doc_hidden(field.did) && !field.did.is_local())
1380                 })
1381                 .collect();
1382
1383             if !has_rest_pat {
1384                 if accessible_unmentioned_fields.is_empty() {
1385                     unmentioned_err = Some(self.error_no_accessible_fields(pat, fields));
1386                 } else {
1387                     unmentioned_err = Some(self.error_unmentioned_fields(
1388                         pat,
1389                         &accessible_unmentioned_fields,
1390                         accessible_unmentioned_fields.len() != unmentioned_fields.len(),
1391                         fields,
1392                     ));
1393                 }
1394             } else if non_exhaustive && !accessible_unmentioned_fields.is_empty() {
1395                 self.lint_non_exhaustive_omitted_patterns(
1396                     pat,
1397                     &accessible_unmentioned_fields,
1398                     adt_ty,
1399                 )
1400             }
1401         }
1402         match (inexistent_fields_err, unmentioned_err) {
1403             (Some(mut i), Some(mut u)) => {
1404                 if let Some(mut e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
1405                     // We don't want to show the nonexistent fields error when this was
1406                     // `Foo { a, b }` when it should have been `Foo(a, b)`.
1407                     i.delay_as_bug();
1408                     u.delay_as_bug();
1409                     e.emit();
1410                 } else {
1411                     i.emit();
1412                     u.emit();
1413                 }
1414             }
1415             (None, Some(mut u)) => {
1416                 if let Some(mut e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
1417                     u.delay_as_bug();
1418                     e.emit();
1419                 } else {
1420                     u.emit();
1421                 }
1422             }
1423             (Some(mut err), None) => {
1424                 err.emit();
1425             }
1426             (None, None) if let Some(mut err) =
1427                     self.error_tuple_variant_index_shorthand(variant, pat, fields) =>
1428             {
1429                 err.emit();
1430             }
1431             (None, None) => {}
1432         }
1433         no_field_errors
1434     }
1435
1436     fn error_tuple_variant_index_shorthand(
1437         &self,
1438         variant: &VariantDef,
1439         pat: &'_ Pat<'_>,
1440         fields: &[hir::PatField<'_>],
1441     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
1442         // if this is a tuple struct, then all field names will be numbers
1443         // so if any fields in a struct pattern use shorthand syntax, they will
1444         // be invalid identifiers (for example, Foo { 0, 1 }).
1445         if let (CtorKind::Fn, PatKind::Struct(qpath, field_patterns, ..)) =
1446             (variant.ctor_kind, &pat.kind)
1447         {
1448             let has_shorthand_field_name = field_patterns.iter().any(|field| field.is_shorthand);
1449             if has_shorthand_field_name {
1450                 let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
1451                     s.print_qpath(qpath, false)
1452                 });
1453                 let mut err = struct_span_err!(
1454                     self.tcx.sess,
1455                     pat.span,
1456                     E0769,
1457                     "tuple variant `{path}` written as struct variant",
1458                 );
1459                 err.span_suggestion_verbose(
1460                     qpath.span().shrink_to_hi().to(pat.span.shrink_to_hi()),
1461                     "use the tuple variant pattern syntax instead",
1462                     format!("({})", self.get_suggested_tuple_struct_pattern(fields, variant)),
1463                     Applicability::MaybeIncorrect,
1464                 );
1465                 return Some(err);
1466             }
1467         }
1468         None
1469     }
1470
1471     fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) {
1472         let sess = self.tcx.sess;
1473         let sm = sess.source_map();
1474         let sp_brace = sm.end_point(pat.span);
1475         let sp_comma = sm.end_point(pat.span.with_hi(sp_brace.hi()));
1476         let sugg = if no_fields || sp_brace != sp_comma { ".. }" } else { ", .. }" };
1477
1478         let mut err = struct_span_err!(
1479             sess,
1480             pat.span,
1481             E0638,
1482             "`..` required with {descr} marked as non-exhaustive",
1483         );
1484         err.span_suggestion_verbose(
1485             sp_comma,
1486             "add `..` at the end of the field list to ignore all other fields",
1487             sugg,
1488             Applicability::MachineApplicable,
1489         );
1490         err.emit();
1491     }
1492
1493     fn error_field_already_bound(&self, span: Span, ident: Ident, other_field: Span) {
1494         struct_span_err!(
1495             self.tcx.sess,
1496             span,
1497             E0025,
1498             "field `{}` bound multiple times in the pattern",
1499             ident
1500         )
1501         .span_label(span, format!("multiple uses of `{ident}` in pattern"))
1502         .span_label(other_field, format!("first use of `{ident}`"))
1503         .emit();
1504     }
1505
1506     fn error_inexistent_fields(
1507         &self,
1508         kind_name: &str,
1509         inexistent_fields: &[&hir::PatField<'tcx>],
1510         unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>,
1511         variant: &ty::VariantDef,
1512         substs: &'tcx ty::List<ty::subst::GenericArg<'tcx>>,
1513     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
1514         let tcx = self.tcx;
1515         let (field_names, t, plural) = if inexistent_fields.len() == 1 {
1516             (format!("a field named `{}`", inexistent_fields[0].ident), "this", "")
1517         } else {
1518             (
1519                 format!(
1520                     "fields named {}",
1521                     inexistent_fields
1522                         .iter()
1523                         .map(|field| format!("`{}`", field.ident))
1524                         .collect::<Vec<String>>()
1525                         .join(", ")
1526                 ),
1527                 "these",
1528                 "s",
1529             )
1530         };
1531         let spans = inexistent_fields.iter().map(|field| field.ident.span).collect::<Vec<_>>();
1532         let mut err = struct_span_err!(
1533             tcx.sess,
1534             spans,
1535             E0026,
1536             "{} `{}` does not have {}",
1537             kind_name,
1538             tcx.def_path_str(variant.def_id),
1539             field_names
1540         );
1541         if let Some(pat_field) = inexistent_fields.last() {
1542             err.span_label(
1543                 pat_field.ident.span,
1544                 format!(
1545                     "{} `{}` does not have {} field{}",
1546                     kind_name,
1547                     tcx.def_path_str(variant.def_id),
1548                     t,
1549                     plural
1550                 ),
1551             );
1552
1553             if unmentioned_fields.len() == 1 {
1554                 let input =
1555                     unmentioned_fields.iter().map(|(_, field)| field.name).collect::<Vec<_>>();
1556                 let suggested_name = find_best_match_for_name(&input, pat_field.ident.name, None);
1557                 if let Some(suggested_name) = suggested_name {
1558                     err.span_suggestion(
1559                         pat_field.ident.span,
1560                         "a field with a similar name exists",
1561                         suggested_name,
1562                         Applicability::MaybeIncorrect,
1563                     );
1564
1565                     // When we have a tuple struct used with struct we don't want to suggest using
1566                     // the (valid) struct syntax with numeric field names. Instead we want to
1567                     // suggest the expected syntax. We infer that this is the case by parsing the
1568                     // `Ident` into an unsized integer. The suggestion will be emitted elsewhere in
1569                     // `smart_resolve_context_dependent_help`.
1570                     if suggested_name.to_ident_string().parse::<usize>().is_err() {
1571                         // We don't want to throw `E0027` in case we have thrown `E0026` for them.
1572                         unmentioned_fields.retain(|&(_, x)| x.name != suggested_name);
1573                     }
1574                 } else if inexistent_fields.len() == 1 {
1575                     match pat_field.pat.kind {
1576                         PatKind::Lit(expr)
1577                             if !self.can_coerce(
1578                                 self.typeck_results.borrow().expr_ty(expr),
1579                                 self.field_ty(
1580                                     unmentioned_fields[0].1.span,
1581                                     unmentioned_fields[0].0,
1582                                     substs,
1583                                 ),
1584                             ) => {}
1585                         _ => {
1586                             let unmentioned_field = unmentioned_fields[0].1.name;
1587                             err.span_suggestion_short(
1588                                 pat_field.ident.span,
1589                                 &format!(
1590                                     "`{}` has a field named `{}`",
1591                                     tcx.def_path_str(variant.def_id),
1592                                     unmentioned_field
1593                                 ),
1594                                 unmentioned_field.to_string(),
1595                                 Applicability::MaybeIncorrect,
1596                             );
1597                         }
1598                     }
1599                 }
1600             }
1601         }
1602         if tcx.sess.teach(&err.get_code().unwrap()) {
1603             err.note(
1604                 "This error indicates that a struct pattern attempted to \
1605                  extract a non-existent field from a struct. Struct fields \
1606                  are identified by the name used before the colon : so struct \
1607                  patterns should resemble the declaration of the struct type \
1608                  being matched.\n\n\
1609                  If you are using shorthand field patterns but want to refer \
1610                  to the struct field by a different name, you should rename \
1611                  it explicitly.",
1612             );
1613         }
1614         err
1615     }
1616
1617     fn error_tuple_variant_as_struct_pat(
1618         &self,
1619         pat: &Pat<'_>,
1620         fields: &'tcx [hir::PatField<'tcx>],
1621         variant: &ty::VariantDef,
1622     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
1623         if let (CtorKind::Fn, PatKind::Struct(qpath, ..)) = (variant.ctor_kind, &pat.kind) {
1624             let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
1625                 s.print_qpath(qpath, false)
1626             });
1627             let mut err = struct_span_err!(
1628                 self.tcx.sess,
1629                 pat.span,
1630                 E0769,
1631                 "tuple variant `{}` written as struct variant",
1632                 path
1633             );
1634             let (sugg, appl) = if fields.len() == variant.fields.len() {
1635                 (
1636                     self.get_suggested_tuple_struct_pattern(fields, variant),
1637                     Applicability::MachineApplicable,
1638                 )
1639             } else {
1640                 (
1641                     variant.fields.iter().map(|_| "_").collect::<Vec<&str>>().join(", "),
1642                     Applicability::MaybeIncorrect,
1643                 )
1644             };
1645             err.span_suggestion_verbose(
1646                 qpath.span().shrink_to_hi().to(pat.span.shrink_to_hi()),
1647                 "use the tuple variant pattern syntax instead",
1648                 format!("({})", sugg),
1649                 appl,
1650             );
1651             return Some(err);
1652         }
1653         None
1654     }
1655
1656     fn get_suggested_tuple_struct_pattern(
1657         &self,
1658         fields: &[hir::PatField<'_>],
1659         variant: &VariantDef,
1660     ) -> String {
1661         let variant_field_idents =
1662             variant.fields.iter().map(|f| f.ident(self.tcx)).collect::<Vec<Ident>>();
1663         fields
1664             .iter()
1665             .map(|field| {
1666                 match self.tcx.sess.source_map().span_to_snippet(field.pat.span) {
1667                     Ok(f) => {
1668                         // Field names are numbers, but numbers
1669                         // are not valid identifiers
1670                         if variant_field_idents.contains(&field.ident) {
1671                             String::from("_")
1672                         } else {
1673                             f
1674                         }
1675                     }
1676                     Err(_) => rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
1677                         s.print_pat(field.pat)
1678                     }),
1679                 }
1680             })
1681             .collect::<Vec<String>>()
1682             .join(", ")
1683     }
1684
1685     /// Returns a diagnostic reporting a struct pattern which is missing an `..` due to
1686     /// inaccessible fields.
1687     ///
1688     /// ```text
1689     /// error: pattern requires `..` due to inaccessible fields
1690     ///   --> src/main.rs:10:9
1691     ///    |
1692     /// LL |     let foo::Foo {} = foo::Foo::default();
1693     ///    |         ^^^^^^^^^^^
1694     ///    |
1695     /// help: add a `..`
1696     ///    |
1697     /// LL |     let foo::Foo { .. } = foo::Foo::default();
1698     ///    |                  ^^^^^^
1699     /// ```
1700     fn error_no_accessible_fields(
1701         &self,
1702         pat: &Pat<'_>,
1703         fields: &'tcx [hir::PatField<'tcx>],
1704     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
1705         let mut err = self
1706             .tcx
1707             .sess
1708             .struct_span_err(pat.span, "pattern requires `..` due to inaccessible fields");
1709
1710         if let Some(field) = fields.last() {
1711             err.span_suggestion_verbose(
1712                 field.span.shrink_to_hi(),
1713                 "ignore the inaccessible and unused fields",
1714                 ", ..",
1715                 Applicability::MachineApplicable,
1716             );
1717         } else {
1718             let qpath_span = if let PatKind::Struct(qpath, ..) = &pat.kind {
1719                 qpath.span()
1720             } else {
1721                 bug!("`error_no_accessible_fields` called on non-struct pattern");
1722             };
1723
1724             // Shrink the span to exclude the `foo:Foo` in `foo::Foo { }`.
1725             let span = pat.span.with_lo(qpath_span.shrink_to_hi().hi());
1726             err.span_suggestion_verbose(
1727                 span,
1728                 "ignore the inaccessible and unused fields",
1729                 " { .. }",
1730                 Applicability::MachineApplicable,
1731             );
1732         }
1733         err
1734     }
1735
1736     /// Report that a pattern for a `#[non_exhaustive]` struct marked with `non_exhaustive_omitted_patterns`
1737     /// is not exhaustive enough.
1738     ///
1739     /// Nb: the partner lint for enums lives in `compiler/rustc_mir_build/src/thir/pattern/usefulness.rs`.
1740     fn lint_non_exhaustive_omitted_patterns(
1741         &self,
1742         pat: &Pat<'_>,
1743         unmentioned_fields: &[(&ty::FieldDef, Ident)],
1744         ty: Ty<'tcx>,
1745     ) {
1746         fn joined_uncovered_patterns(witnesses: &[&Ident]) -> String {
1747             const LIMIT: usize = 3;
1748             match witnesses {
1749                 [] => bug!(),
1750                 [witness] => format!("`{}`", witness),
1751                 [head @ .., tail] if head.len() < LIMIT => {
1752                     let head: Vec<_> = head.iter().map(<_>::to_string).collect();
1753                     format!("`{}` and `{}`", head.join("`, `"), tail)
1754                 }
1755                 _ => {
1756                     let (head, tail) = witnesses.split_at(LIMIT);
1757                     let head: Vec<_> = head.iter().map(<_>::to_string).collect();
1758                     format!("`{}` and {} more", head.join("`, `"), tail.len())
1759                 }
1760             }
1761         }
1762         let joined_patterns = joined_uncovered_patterns(
1763             &unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
1764         );
1765
1766         self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, |build| {
1767         let mut lint = build.build("some fields are not explicitly listed");
1768         lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
1769
1770         lint.help(
1771             "ensure that all fields are mentioned explicitly by adding the suggested fields",
1772         );
1773         lint.note(&format!(
1774             "the pattern is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
1775             ty,
1776         ));
1777         lint.emit();
1778     });
1779     }
1780
1781     /// Returns a diagnostic reporting a struct pattern which does not mention some fields.
1782     ///
1783     /// ```text
1784     /// error[E0027]: pattern does not mention field `bar`
1785     ///   --> src/main.rs:15:9
1786     ///    |
1787     /// LL |     let foo::Foo {} = foo::Foo::new();
1788     ///    |         ^^^^^^^^^^^ missing field `bar`
1789     /// ```
1790     fn error_unmentioned_fields(
1791         &self,
1792         pat: &Pat<'_>,
1793         unmentioned_fields: &[(&ty::FieldDef, Ident)],
1794         have_inaccessible_fields: bool,
1795         fields: &'tcx [hir::PatField<'tcx>],
1796     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
1797         let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" };
1798         let field_names = if unmentioned_fields.len() == 1 {
1799             format!("field `{}`{}", unmentioned_fields[0].1, inaccessible)
1800         } else {
1801             let fields = unmentioned_fields
1802                 .iter()
1803                 .map(|(_, name)| format!("`{}`", name))
1804                 .collect::<Vec<String>>()
1805                 .join(", ");
1806             format!("fields {}{}", fields, inaccessible)
1807         };
1808         let mut err = struct_span_err!(
1809             self.tcx.sess,
1810             pat.span,
1811             E0027,
1812             "pattern does not mention {}",
1813             field_names
1814         );
1815         err.span_label(pat.span, format!("missing {}", field_names));
1816         let len = unmentioned_fields.len();
1817         let (prefix, postfix, sp) = match fields {
1818             [] => match &pat.kind {
1819                 PatKind::Struct(path, [], false) => {
1820                     (" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi()))
1821                 }
1822                 _ => return err,
1823             },
1824             [.., field] => {
1825                 // Account for last field having a trailing comma or parse recovery at the tail of
1826                 // the pattern to avoid invalid suggestion (#78511).
1827                 let tail = field.span.shrink_to_hi().with_hi(pat.span.hi());
1828                 match &pat.kind {
1829                     PatKind::Struct(..) => (", ", " }", tail),
1830                     _ => return err,
1831                 }
1832             }
1833         };
1834         err.span_suggestion(
1835             sp,
1836             &format!(
1837                 "include the missing field{} in the pattern{}",
1838                 pluralize!(len),
1839                 if have_inaccessible_fields { " and ignore the inaccessible fields" } else { "" }
1840             ),
1841             format!(
1842                 "{}{}{}{}",
1843                 prefix,
1844                 unmentioned_fields
1845                     .iter()
1846                     .map(|(_, name)| name.to_string())
1847                     .collect::<Vec<_>>()
1848                     .join(", "),
1849                 if have_inaccessible_fields { ", .." } else { "" },
1850                 postfix,
1851             ),
1852             Applicability::MachineApplicable,
1853         );
1854         err.span_suggestion(
1855             sp,
1856             &format!(
1857                 "if you don't care about {these} missing field{s}, you can explicitly ignore {them}",
1858                 these = pluralize!("this", len),
1859                 s = pluralize!(len),
1860                 them = if len == 1 { "it" } else { "them" },
1861             ),
1862             format!("{}..{}", prefix, postfix),
1863             Applicability::MachineApplicable,
1864         );
1865         err
1866     }
1867
1868     fn check_pat_box(
1869         &self,
1870         span: Span,
1871         inner: &'tcx Pat<'tcx>,
1872         expected: Ty<'tcx>,
1873         def_bm: BindingMode,
1874         ti: TopInfo<'tcx>,
1875     ) -> Ty<'tcx> {
1876         let tcx = self.tcx;
1877         let (box_ty, inner_ty) = if self.check_dereferenceable(span, expected, inner) {
1878             // Here, `demand::subtype` is good enough, but I don't
1879             // think any errors can be introduced by using `demand::eqtype`.
1880             let inner_ty = self.next_ty_var(TypeVariableOrigin {
1881                 kind: TypeVariableOriginKind::TypeInference,
1882                 span: inner.span,
1883             });
1884             let box_ty = tcx.mk_box(inner_ty);
1885             self.demand_eqtype_pat(span, expected, box_ty, ti);
1886             (box_ty, inner_ty)
1887         } else {
1888             let err = tcx.ty_error();
1889             (err, err)
1890         };
1891         self.check_pat(inner, inner_ty, def_bm, ti);
1892         box_ty
1893     }
1894
1895     // Precondition: Pat is Ref(inner)
1896     fn check_pat_ref(
1897         &self,
1898         pat: &'tcx Pat<'tcx>,
1899         inner: &'tcx Pat<'tcx>,
1900         mutbl: hir::Mutability,
1901         expected: Ty<'tcx>,
1902         def_bm: BindingMode,
1903         ti: TopInfo<'tcx>,
1904     ) -> Ty<'tcx> {
1905         let tcx = self.tcx;
1906         let expected = self.shallow_resolve(expected);
1907         let (rptr_ty, inner_ty) = if self.check_dereferenceable(pat.span, expected, inner) {
1908             // `demand::subtype` would be good enough, but using `eqtype` turns
1909             // out to be equally general. See (note_1) for details.
1910
1911             // Take region, inner-type from expected type if we can,
1912             // to avoid creating needless variables. This also helps with
1913             // the bad interactions of the given hack detailed in (note_1).
1914             debug!("check_pat_ref: expected={:?}", expected);
1915             match *expected.kind() {
1916                 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
1917                 _ => {
1918                     let inner_ty = self.next_ty_var(TypeVariableOrigin {
1919                         kind: TypeVariableOriginKind::TypeInference,
1920                         span: inner.span,
1921                     });
1922                     let rptr_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
1923                     debug!("check_pat_ref: demanding {:?} = {:?}", expected, rptr_ty);
1924                     let err = self.demand_eqtype_pat_diag(pat.span, expected, rptr_ty, ti);
1925
1926                     // Look for a case like `fn foo(&foo: u32)` and suggest
1927                     // `fn foo(foo: &u32)`
1928                     if let Some(mut err) = err {
1929                         self.borrow_pat_suggestion(&mut err, pat);
1930                         err.emit();
1931                     }
1932                     (rptr_ty, inner_ty)
1933                 }
1934             }
1935         } else {
1936             let err = tcx.ty_error();
1937             (err, err)
1938         };
1939         self.check_pat(inner, inner_ty, def_bm, TopInfo { parent_pat: Some(pat), ..ti });
1940         rptr_ty
1941     }
1942
1943     /// Create a reference type with a fresh region variable.
1944     fn new_ref_ty(&self, span: Span, mutbl: hir::Mutability, ty: Ty<'tcx>) -> Ty<'tcx> {
1945         let region = self.next_region_var(infer::PatternRegion(span));
1946         let mt = ty::TypeAndMut { ty, mutbl };
1947         self.tcx.mk_ref(region, mt)
1948     }
1949
1950     /// Type check a slice pattern.
1951     ///
1952     /// Syntactically, these look like `[pat_0, ..., pat_n]`.
1953     /// Semantically, we are type checking a pattern with structure:
1954     /// ```ignore (not-rust)
1955     /// [before_0, ..., before_n, (slice, after_0, ... after_n)?]
1956     /// ```
1957     /// The type of `slice`, if it is present, depends on the `expected` type.
1958     /// If `slice` is missing, then so is `after_i`.
1959     /// If `slice` is present, it can still represent 0 elements.
1960     fn check_pat_slice(
1961         &self,
1962         span: Span,
1963         before: &'tcx [Pat<'tcx>],
1964         slice: Option<&'tcx Pat<'tcx>>,
1965         after: &'tcx [Pat<'tcx>],
1966         expected: Ty<'tcx>,
1967         def_bm: BindingMode,
1968         ti: TopInfo<'tcx>,
1969     ) -> Ty<'tcx> {
1970         let expected = self.structurally_resolved_type(span, expected);
1971         let (element_ty, opt_slice_ty, inferred) = match *expected.kind() {
1972             // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
1973             ty::Array(element_ty, len) => {
1974                 let min = before.len() as u64 + after.len() as u64;
1975                 let (opt_slice_ty, expected) =
1976                     self.check_array_pat_len(span, element_ty, expected, slice, len, min);
1977                 // `opt_slice_ty.is_none()` => `slice.is_none()`.
1978                 // Note, though, that opt_slice_ty could be `Some(error_ty)`.
1979                 assert!(opt_slice_ty.is_some() || slice.is_none());
1980                 (element_ty, opt_slice_ty, expected)
1981             }
1982             ty::Slice(element_ty) => (element_ty, Some(expected), expected),
1983             // The expected type must be an array or slice, but was neither, so error.
1984             _ => {
1985                 if !expected.references_error() {
1986                     self.error_expected_array_or_slice(span, expected, ti);
1987                 }
1988                 let err = self.tcx.ty_error();
1989                 (err, Some(err), err)
1990             }
1991         };
1992
1993         // Type check all the patterns before `slice`.
1994         for elt in before {
1995             self.check_pat(elt, element_ty, def_bm, ti);
1996         }
1997         // Type check the `slice`, if present, against its expected type.
1998         if let Some(slice) = slice {
1999             self.check_pat(slice, opt_slice_ty.unwrap(), def_bm, ti);
2000         }
2001         // Type check the elements after `slice`, if present.
2002         for elt in after {
2003             self.check_pat(elt, element_ty, def_bm, ti);
2004         }
2005         inferred
2006     }
2007
2008     /// Type check the length of an array pattern.
2009     ///
2010     /// Returns both the type of the variable length pattern (or `None`), and the potentially
2011     /// inferred array type. We only return `None` for the slice type if `slice.is_none()`.
2012     fn check_array_pat_len(
2013         &self,
2014         span: Span,
2015         element_ty: Ty<'tcx>,
2016         arr_ty: Ty<'tcx>,
2017         slice: Option<&'tcx Pat<'tcx>>,
2018         len: ty::Const<'tcx>,
2019         min_len: u64,
2020     ) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
2021         if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) {
2022             // Now we know the length...
2023             if slice.is_none() {
2024                 // ...and since there is no variable-length pattern,
2025                 // we require an exact match between the number of elements
2026                 // in the array pattern and as provided by the matched type.
2027                 if min_len == len {
2028                     return (None, arr_ty);
2029                 }
2030
2031                 self.error_scrutinee_inconsistent_length(span, min_len, len);
2032             } else if let Some(pat_len) = len.checked_sub(min_len) {
2033                 // The variable-length pattern was there,
2034                 // so it has an array type with the remaining elements left as its size...
2035                 return (Some(self.tcx.mk_array(element_ty, pat_len)), arr_ty);
2036             } else {
2037                 // ...however, in this case, there were no remaining elements.
2038                 // That is, the slice pattern requires more than the array type offers.
2039                 self.error_scrutinee_with_rest_inconsistent_length(span, min_len, len);
2040             }
2041         } else if slice.is_none() {
2042             // We have a pattern with a fixed length,
2043             // which we can use to infer the length of the array.
2044             let updated_arr_ty = self.tcx.mk_array(element_ty, min_len);
2045             self.demand_eqtype(span, updated_arr_ty, arr_ty);
2046             return (None, updated_arr_ty);
2047         } else {
2048             // We have a variable-length pattern and don't know the array length.
2049             // This happens if we have e.g.,
2050             // `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
2051             self.error_scrutinee_unfixed_length(span);
2052         }
2053
2054         // If we get here, we must have emitted an error.
2055         (Some(self.tcx.ty_error()), arr_ty)
2056     }
2057
2058     fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
2059         struct_span_err!(
2060             self.tcx.sess,
2061             span,
2062             E0527,
2063             "pattern requires {} element{} but array has {}",
2064             min_len,
2065             pluralize!(min_len),
2066             size,
2067         )
2068         .span_label(span, format!("expected {} element{}", size, pluralize!(size)))
2069         .emit();
2070     }
2071
2072     fn error_scrutinee_with_rest_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
2073         struct_span_err!(
2074             self.tcx.sess,
2075             span,
2076             E0528,
2077             "pattern requires at least {} element{} but array has {}",
2078             min_len,
2079             pluralize!(min_len),
2080             size,
2081         )
2082         .span_label(
2083             span,
2084             format!("pattern cannot match array of {} element{}", size, pluralize!(size),),
2085         )
2086         .emit();
2087     }
2088
2089     fn error_scrutinee_unfixed_length(&self, span: Span) {
2090         struct_span_err!(
2091             self.tcx.sess,
2092             span,
2093             E0730,
2094             "cannot pattern-match on an array without a fixed length",
2095         )
2096         .emit();
2097     }
2098
2099     fn error_expected_array_or_slice(&self, span: Span, expected_ty: Ty<'tcx>, ti: TopInfo<'tcx>) {
2100         let mut err = struct_span_err!(
2101             self.tcx.sess,
2102             span,
2103             E0529,
2104             "expected an array or slice, found `{expected_ty}`"
2105         );
2106         if let ty::Ref(_, ty, _) = expected_ty.kind()
2107             && let ty::Array(..) | ty::Slice(..) = ty.kind()
2108         {
2109             err.help("the semantics of slice patterns changed recently; see issue #62254");
2110         } else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
2111             .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
2112             && let (Some(span), true) = (ti.span, ti.origin_expr)
2113             && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
2114         {
2115             let ty = self.resolve_vars_if_possible(ti.expected);
2116             let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(&mut err, snippet.clone(), ty);
2117             match is_slice_or_array_or_vector.1.kind() {
2118                 ty::Adt(adt_def, _)
2119                     if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
2120                         || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
2121                 {
2122                     // Slicing won't work here, but `.as_deref()` might (issue #91328).
2123                     err.span_suggestion(
2124                         span,
2125                         "consider using `as_deref` here",
2126                         format!("{snippet}.as_deref()"),
2127                         Applicability::MaybeIncorrect,
2128                     );
2129                 }
2130                 _ => ()
2131             }
2132             if is_slice_or_array_or_vector.0 {
2133                 err.span_suggestion(
2134                     span,
2135                     "consider slicing here",
2136                     format!("{snippet}[..]"),
2137                     Applicability::MachineApplicable,
2138                 );
2139             }
2140         }
2141         err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
2142         err.emit();
2143     }
2144
2145     fn is_slice_or_array_or_vector(
2146         &self,
2147         err: &mut Diagnostic,
2148         snippet: String,
2149         ty: Ty<'tcx>,
2150     ) -> (bool, Ty<'tcx>) {
2151         match ty.kind() {
2152             ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did()) => {
2153                 (true, ty)
2154             }
2155             ty::Ref(_, ty, _) => self.is_slice_or_array_or_vector(err, snippet, *ty),
2156             ty::Slice(..) | ty::Array(..) => (true, ty),
2157             _ => (false, ty),
2158         }
2159     }
2160 }