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