rustc_hir_typeck/
pat.rs

1use std::cmp;
2use std::collections::hash_map::Entry::{Occupied, Vacant};
3
4use rustc_abi::FieldIdx;
5use rustc_ast as ast;
6use rustc_data_structures::fx::FxHashMap;
7use rustc_errors::codes::*;
8use rustc_errors::{
9    Applicability, Diag, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err,
10};
11use rustc_hir::def::{CtorKind, DefKind, Res};
12use rustc_hir::pat_util::EnumerateAndAdjustIterator;
13use rustc_hir::{
14    self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatExpr,
15    PatExprKind, PatKind, expr_needs_parens,
16};
17use rustc_infer::infer;
18use rustc_middle::traits::PatternOriginExpr;
19use rustc_middle::ty::{self, Ty, TypeVisitableExt};
20use rustc_middle::{bug, span_bug};
21use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
22use rustc_session::parse::feature_err;
23use rustc_span::edit_distance::find_best_match_for_name;
24use rustc_span::edition::Edition;
25use rustc_span::hygiene::DesugaringKind;
26use rustc_span::source_map::Spanned;
27use rustc_span::{BytePos, DUMMY_SP, Ident, Span, kw, sym};
28use rustc_trait_selection::infer::InferCtxtExt;
29use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
30use tracing::{debug, instrument, trace};
31use ty::VariantDef;
32
33use super::report_unexpected_variant_res;
34use crate::expectation::Expectation;
35use crate::gather_locals::DeclOrigin;
36use crate::{FnCtxt, LoweredTy, errors};
37
38const CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ: &str = "\
39This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
40pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
41this type has no compile-time size. Therefore, all accesses to trait types must be through \
42pointers. If you encounter this error you should try to avoid dereferencing the pointer.
43
44You can read more about trait objects in the Trait Objects section of the Reference: \
45https://doc.rust-lang.org/reference/types.html#trait-objects";
46
47fn is_number(text: &str) -> bool {
48    text.chars().all(|c: char| c.is_digit(10))
49}
50
51/// Information about the expected type at the top level of type checking a pattern.
52///
53/// **NOTE:** This is only for use by diagnostics. Do NOT use for type checking logic!
54#[derive(Copy, Clone)]
55struct TopInfo<'tcx> {
56    /// The `expected` type at the top level of type checking a pattern.
57    expected: Ty<'tcx>,
58    /// Was the origin of the `span` from a scrutinee expression?
59    ///
60    /// Otherwise there is no scrutinee and it could be e.g. from the type of a formal parameter.
61    origin_expr: Option<&'tcx hir::Expr<'tcx>>,
62    /// The span giving rise to the `expected` type, if one could be provided.
63    ///
64    /// If `origin_expr` is `true`, then this is the span of the scrutinee as in:
65    ///
66    /// - `match scrutinee { ... }`
67    /// - `let _ = scrutinee;`
68    ///
69    /// This is used to point to add context in type errors.
70    /// In the following example, `span` corresponds to the `a + b` expression:
71    ///
72    /// ```text
73    /// error[E0308]: mismatched types
74    ///  --> src/main.rs:L:C
75    ///   |
76    /// L |    let temp: usize = match a + b {
77    ///   |                            ----- this expression has type `usize`
78    /// L |         Ok(num) => num,
79    ///   |         ^^^^^^^ expected `usize`, found enum `std::result::Result`
80    ///   |
81    ///   = note: expected type `usize`
82    ///              found type `std::result::Result<_, _>`
83    /// ```
84    span: Option<Span>,
85    /// The [`HirId`] of the top-level pattern.
86    hir_id: HirId,
87}
88
89#[derive(Copy, Clone)]
90struct PatInfo<'tcx> {
91    binding_mode: ByRef,
92    max_ref_mutbl: MutblCap,
93    top_info: TopInfo<'tcx>,
94    decl_origin: Option<DeclOrigin<'tcx>>,
95
96    /// The depth of current pattern
97    current_depth: u32,
98}
99
100impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
101    fn pattern_cause(&self, ti: &TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
102        // If origin_expr exists, then expected represents the type of origin_expr.
103        // If span also exists, then span == origin_expr.span (although it doesn't need to exist).
104        // In that case, we can peel away references from both and treat them
105        // as the same.
106        let origin_expr_info = ti.origin_expr.map(|mut cur_expr| {
107            let mut count = 0;
108
109            // cur_ty may have more layers of references than cur_expr.
110            // We can only make suggestions about cur_expr, however, so we'll
111            // use that as our condition for stopping.
112            while let ExprKind::AddrOf(.., inner) = &cur_expr.kind {
113                cur_expr = inner;
114                count += 1;
115            }
116
117            PatternOriginExpr {
118                peeled_span: cur_expr.span,
119                peeled_count: count,
120                peeled_prefix_suggestion_parentheses: expr_needs_parens(cur_expr),
121            }
122        });
123
124        let code = ObligationCauseCode::Pattern {
125            span: ti.span,
126            root_ty: ti.expected,
127            origin_expr: origin_expr_info,
128        };
129        self.cause(cause_span, code)
130    }
131
132    fn demand_eqtype_pat_diag(
133        &'a self,
134        cause_span: Span,
135        expected: Ty<'tcx>,
136        actual: Ty<'tcx>,
137        ti: &TopInfo<'tcx>,
138    ) -> Result<(), Diag<'a>> {
139        self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
140            .map_err(|mut diag| {
141                if let Some(expr) = ti.origin_expr {
142                    self.suggest_fn_call(&mut diag, expr, expected, |output| {
143                        self.can_eq(self.param_env, output, actual)
144                    });
145                }
146                diag
147            })
148    }
149
150    fn demand_eqtype_pat(
151        &self,
152        cause_span: Span,
153        expected: Ty<'tcx>,
154        actual: Ty<'tcx>,
155        ti: &TopInfo<'tcx>,
156    ) -> Result<(), ErrorGuaranteed> {
157        self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map_err(|err| err.emit())
158    }
159}
160
161/// Mode for adjusting the expected type and binding mode.
162#[derive(Clone, Copy, Debug, PartialEq, Eq)]
163enum AdjustMode {
164    /// Peel off all immediate reference types.
165    Peel,
166    /// Reset binding mode to the initial mode.
167    /// Used for destructuring assignment, where we don't want any match ergonomics.
168    Reset,
169    /// Pass on the input binding mode and expected type.
170    Pass,
171}
172
173/// `ref mut` bindings (explicit or match-ergonomics) are not allowed behind an `&` reference.
174/// Normally, the borrow checker enforces this, but for (currently experimental) match ergonomics,
175/// we track this when typing patterns for two purposes:
176///
177/// - For RFC 3627's Rule 3, when this would prevent us from binding with `ref mut`, we limit the
178///   default binding mode to be by shared `ref` when it would otherwise be `ref mut`.
179///
180/// - For RFC 3627's Rule 5, we allow `&` patterns to match against `&mut` references, treating them
181///   as if they were shared references. Since the scrutinee is mutable in this case, the borrow
182///   checker won't catch if we bind with `ref mut`, so we need to throw an error ourselves.
183#[derive(Clone, Copy, Debug, PartialEq, Eq)]
184enum MutblCap {
185    /// Mutability restricted to immutable.
186    Not,
187
188    /// Mutability restricted to immutable, but only because of the pattern
189    /// (not the scrutinee type).
190    ///
191    /// The contained span, if present, points to an `&` pattern
192    /// that is the reason for the restriction,
193    /// and which will be reported in a diagnostic.
194    WeaklyNot(Option<Span>),
195
196    /// No restriction on mutability
197    Mut,
198}
199
200impl MutblCap {
201    #[must_use]
202    fn cap_to_weakly_not(self, span: Option<Span>) -> Self {
203        match self {
204            MutblCap::Not => MutblCap::Not,
205            _ => MutblCap::WeaklyNot(span),
206        }
207    }
208
209    #[must_use]
210    fn as_mutbl(self) -> Mutability {
211        match self {
212            MutblCap::Not | MutblCap::WeaklyNot(_) => Mutability::Not,
213            MutblCap::Mut => Mutability::Mut,
214        }
215    }
216}
217
218/// Variations on RFC 3627's Rule 4: when do reference patterns match against inherited references?
219///
220/// "Inherited reference" designates the `&`/`&mut` types that arise from using match ergonomics, i.e.
221/// from matching a reference type with a non-reference pattern. E.g. when `Some(x)` matches on
222/// `&mut Option<&T>`, `x` gets type `&mut &T` and the outer `&mut` is considered "inherited".
223#[derive(Clone, Copy, Debug, PartialEq, Eq)]
224enum InheritedRefMatchRule {
225    /// Reference patterns consume only the inherited reference if possible, regardless of whether
226    /// the underlying type being matched against is a reference type. If there is no inherited
227    /// reference, a reference will be consumed from the underlying type.
228    EatOuter,
229    /// Reference patterns consume only a reference from the underlying type if possible. If the
230    /// underlying type is not a reference type, the inherited reference will be consumed.
231    EatInner,
232    /// When the underlying type is a reference type, reference patterns consume both layers of
233    /// reference, i.e. they both reset the binding mode and consume the reference type.
234    EatBoth {
235        /// If `true`, an inherited reference will be considered when determining whether a reference
236        /// pattern matches a given type:
237        /// - If the underlying type is not a reference, a reference pattern may eat the inherited reference;
238        /// - If the underlying type is a reference, a reference pattern matches if it can eat either one
239        ///    of the underlying and inherited references. E.g. a `&mut` pattern is allowed if either the
240        ///    underlying type is `&mut` or the inherited reference is `&mut`.
241        /// If `false`, a reference pattern is only matched against the underlying type.
242        /// This is `false` for stable Rust and `true` for both the `ref_pat_eat_one_layer_2024` and
243        /// `ref_pat_eat_one_layer_2024_structural` feature gates.
244        consider_inherited_ref: bool,
245    },
246}
247
248impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
249    /// Experimental pattern feature: after matching against a shared reference, do we limit the
250    /// default binding mode in subpatterns to be `ref` when it would otherwise be `ref mut`?
251    /// This corresponds to Rule 3 of RFC 3627.
252    fn downgrade_mut_inside_shared(&self) -> bool {
253        // NB: RFC 3627 proposes stabilizing Rule 3 in all editions. If we adopt the same behavior
254        // across all editions, this may be removed.
255        self.tcx.features().ref_pat_eat_one_layer_2024_structural()
256    }
257
258    /// Experimental pattern feature: when do reference patterns match against inherited references?
259    /// This corresponds to variations on Rule 4 of RFC 3627.
260    fn ref_pat_matches_inherited_ref(&self, edition: Edition) -> InheritedRefMatchRule {
261        // NB: The particular rule used here is likely to differ across editions, so calls to this
262        // may need to become edition checks after match ergonomics stabilize.
263        if edition.at_least_rust_2024() {
264            if self.tcx.features().ref_pat_eat_one_layer_2024() {
265                InheritedRefMatchRule::EatOuter
266            } else if self.tcx.features().ref_pat_eat_one_layer_2024_structural() {
267                InheritedRefMatchRule::EatInner
268            } else {
269                // Currently, matching against an inherited ref on edition 2024 is an error.
270                // Use `EatBoth` as a fallback to be similar to stable Rust.
271                InheritedRefMatchRule::EatBoth { consider_inherited_ref: false }
272            }
273        } else {
274            InheritedRefMatchRule::EatBoth {
275                consider_inherited_ref: self.tcx.features().ref_pat_eat_one_layer_2024()
276                    || self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
277            }
278        }
279    }
280
281    /// Experimental pattern feature: do `&` patterns match against `&mut` references, treating them
282    /// as if they were shared references? This corresponds to Rule 5 of RFC 3627.
283    fn ref_pat_matches_mut_ref(&self) -> bool {
284        // NB: RFC 3627 proposes stabilizing Rule 5 in all editions. If we adopt the same behavior
285        // across all editions, this may be removed.
286        self.tcx.features().ref_pat_eat_one_layer_2024()
287            || self.tcx.features().ref_pat_eat_one_layer_2024_structural()
288    }
289
290    /// Type check the given top level pattern against the `expected` type.
291    ///
292    /// If a `Some(span)` is provided and `origin_expr` holds,
293    /// then the `span` represents the scrutinee's span.
294    /// The scrutinee is found in e.g. `match scrutinee { ... }` and `let pat = scrutinee;`.
295    ///
296    /// Otherwise, `Some(span)` represents the span of a type expression
297    /// which originated the `expected` type.
298    pub(crate) fn check_pat_top(
299        &self,
300        pat: &'tcx Pat<'tcx>,
301        expected: Ty<'tcx>,
302        span: Option<Span>,
303        origin_expr: Option<&'tcx hir::Expr<'tcx>>,
304        decl_origin: Option<DeclOrigin<'tcx>>,
305    ) {
306        let top_info = TopInfo { expected, origin_expr, span, hir_id: pat.hir_id };
307        let pat_info = PatInfo {
308            binding_mode: ByRef::No,
309            max_ref_mutbl: MutblCap::Mut,
310            top_info,
311            decl_origin,
312            current_depth: 0,
313        };
314        self.check_pat(pat, expected, pat_info);
315    }
316
317    /// Type check the given `pat` against the `expected` type
318    /// with the provided `binding_mode` (default binding mode).
319    ///
320    /// Outside of this module, `check_pat_top` should always be used.
321    /// Conversely, inside this module, `check_pat_top` should never be used.
322    #[instrument(level = "debug", skip(self, pat_info))]
323    fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) {
324        let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info;
325
326        let path_res = match pat.kind {
327            PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
328                Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span))
329            }
330            _ => None,
331        };
332        let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
333        let (expected, binding_mode, max_ref_mutbl) =
334            self.calc_default_binding_mode(pat, expected, binding_mode, adjust_mode, max_ref_mutbl);
335        let pat_info = PatInfo {
336            binding_mode,
337            max_ref_mutbl,
338            top_info: ti,
339            decl_origin: pat_info.decl_origin,
340            current_depth: current_depth + 1,
341        };
342
343        let ty = match pat.kind {
344            PatKind::Wild | PatKind::Err(_) => expected,
345            // We allow any type here; we ensure that the type is uninhabited during match checking.
346            PatKind::Never => expected,
347            PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
348                let ty = self.check_pat_path(
349                    *hir_id,
350                    pat.hir_id,
351                    *span,
352                    qpath,
353                    path_res.unwrap(),
354                    expected,
355                    &pat_info.top_info,
356                );
357                self.write_ty(*hir_id, ty);
358                ty
359            }
360            PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info),
361            PatKind::Range(lhs, rhs, _) => {
362                self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info)
363            }
364            PatKind::Binding(ba, var_id, ident, sub) => {
365                self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
366            }
367            PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
368                self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
369            }
370            PatKind::Struct(ref qpath, fields, has_rest_pat) => {
371                self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
372            }
373            PatKind::Guard(pat, cond) => {
374                self.check_pat(pat, expected, pat_info);
375                self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {});
376                expected
377            }
378            PatKind::Or(pats) => {
379                for pat in pats {
380                    self.check_pat(pat, expected, pat_info);
381                }
382                expected
383            }
384            PatKind::Tuple(elements, ddpos) => {
385                self.check_pat_tuple(pat.span, elements, ddpos, expected, pat_info)
386            }
387            PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info),
388            PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info),
389            PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info),
390            PatKind::Slice(before, slice, after) => {
391                self.check_pat_slice(pat.span, before, slice, after, expected, pat_info)
392            }
393        };
394
395        self.write_ty(pat.hir_id, ty);
396
397        // (note_1): In most of the cases where (note_1) is referenced
398        // (literals and constants being the exception), we relate types
399        // using strict equality, even though subtyping would be sufficient.
400        // There are a few reasons for this, some of which are fairly subtle
401        // and which cost me (nmatsakis) an hour or two debugging to remember,
402        // so I thought I'd write them down this time.
403        //
404        // 1. There is no loss of expressiveness here, though it does
405        // cause some inconvenience. What we are saying is that the type
406        // of `x` becomes *exactly* what is expected. This can cause unnecessary
407        // errors in some cases, such as this one:
408        //
409        // ```
410        // fn foo<'x>(x: &'x i32) {
411        //    let a = 1;
412        //    let mut z = x;
413        //    z = &a;
414        // }
415        // ```
416        //
417        // The reason we might get an error is that `z` might be
418        // assigned a type like `&'x i32`, and then we would have
419        // a problem when we try to assign `&a` to `z`, because
420        // the lifetime of `&a` (i.e., the enclosing block) is
421        // shorter than `'x`.
422        //
423        // HOWEVER, this code works fine. The reason is that the
424        // expected type here is whatever type the user wrote, not
425        // the initializer's type. In this case the user wrote
426        // nothing, so we are going to create a type variable `Z`.
427        // Then we will assign the type of the initializer (`&'x i32`)
428        // as a subtype of `Z`: `&'x i32 <: Z`. And hence we
429        // will instantiate `Z` as a type `&'0 i32` where `'0` is
430        // a fresh region variable, with the constraint that `'x : '0`.
431        // So basically we're all set.
432        //
433        // Note that there are two tests to check that this remains true
434        // (`regions-reassign-{match,let}-bound-pointer.rs`).
435        //
436        // 2. An outdated issue related to the old HIR borrowck. See the test
437        // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
438    }
439
440    /// Compute the new expected type and default binding mode from the old ones
441    /// as well as the pattern form we are currently checking.
442    fn calc_default_binding_mode(
443        &self,
444        pat: &'tcx Pat<'tcx>,
445        expected: Ty<'tcx>,
446        def_br: ByRef,
447        adjust_mode: AdjustMode,
448        max_ref_mutbl: MutblCap,
449    ) -> (Ty<'tcx>, ByRef, MutblCap) {
450        #[cfg(debug_assertions)]
451        if def_br == ByRef::Yes(Mutability::Mut)
452            && max_ref_mutbl != MutblCap::Mut
453            && self.downgrade_mut_inside_shared()
454        {
455            span_bug!(pat.span, "Pattern mutability cap violated!");
456        }
457        match adjust_mode {
458            AdjustMode::Pass => (expected, def_br, max_ref_mutbl),
459            AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut),
460            AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl),
461        }
462    }
463
464    /// How should the binding mode and expected type be adjusted?
465    ///
466    /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`.
467    fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> AdjustMode {
468        // When we perform destructuring assignment, we disable default match bindings, which are
469        // unintuitive in this context.
470        if !pat.default_binding_modes {
471            return AdjustMode::Reset;
472        }
473        match &pat.kind {
474            // Type checking these product-like types successfully always require
475            // that the expected type be of those types and not reference types.
476            PatKind::Struct(..)
477            | PatKind::TupleStruct(..)
478            | PatKind::Tuple(..)
479            | PatKind::Box(_)
480            | PatKind::Deref(_)
481            | PatKind::Range(..)
482            | PatKind::Slice(..) => AdjustMode::Peel,
483            // A never pattern behaves somewhat like a literal or unit variant.
484            PatKind::Never => AdjustMode::Peel,
485            PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => match opt_path_res.unwrap() {
486                // These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
487                // Peeling the reference types too early will cause type checking failures.
488                // Although it would be possible to *also* peel the types of the constants too.
489                Res::Def(DefKind::Const | DefKind::AssocConst, _) => AdjustMode::Pass,
490                // In the `ValueNS`, we have `SelfCtor(..) | Ctor(_, Const), _)` remaining which
491                // could successfully compile. The former being `Self` requires a unit struct.
492                // In either case, and unlike constants, the pattern itself cannot be
493                // a reference type wherefore peeling doesn't give up any expressiveness.
494                _ => AdjustMode::Peel,
495            },
496
497            // String and byte-string literals result in types `&str` and `&[u8]` respectively.
498            // All other literals result in non-reference types.
499            // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
500            //
501            // Call `resolve_vars_if_possible` here for inline const blocks.
502            PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() {
503                ty::Ref(..) => AdjustMode::Pass,
504                _ => AdjustMode::Peel,
505            },
506
507            // Ref patterns are complicated, we handle them in `check_pat_ref`.
508            PatKind::Ref(..) => AdjustMode::Pass,
509            // A `_` pattern works with any expected type, so there's no need to do anything.
510            PatKind::Wild
511            // A malformed pattern doesn't have an expected type, so let's just accept any type.
512            | PatKind::Err(_)
513            // Bindings also work with whatever the expected type is,
514            // and moreover if we peel references off, that will give us the wrong binding type.
515            // Also, we can have a subpattern `binding @ pat`.
516            // Each side of the `@` should be treated independently (like with OR-patterns).
517            | PatKind::Binding(..)
518            // An OR-pattern just propagates to each individual alternative.
519            // This is maximally flexible, allowing e.g., `Some(mut x) | &Some(mut x)`.
520            // In that example, `Some(mut x)` results in `Peel` whereas `&Some(mut x)` in `Reset`.
521            | PatKind::Or(_)
522            // Like or-patterns, guard patterns just propogate to their subpatterns.
523            | PatKind::Guard(..) => AdjustMode::Pass,
524        }
525    }
526
527    /// Peel off as many immediately nested `& mut?` from the expected type as possible
528    /// and return the new expected type and binding default binding mode.
529    /// The adjustments vector, if non-empty is stored in a table.
530    fn peel_off_references(
531        &self,
532        pat: &'tcx Pat<'tcx>,
533        expected: Ty<'tcx>,
534        mut def_br: ByRef,
535        mut max_ref_mutbl: MutblCap,
536    ) -> (Ty<'tcx>, ByRef, MutblCap) {
537        let mut expected = self.try_structurally_resolve_type(pat.span, expected);
538        // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
539        // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
540        // the `Some(5)` which is not of type Ref.
541        //
542        // For each ampersand peeled off, update the binding mode and push the original
543        // type into the adjustments vector.
544        //
545        // See the examples in `ui/match-defbm*.rs`.
546        let mut pat_adjustments = vec![];
547        while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
548            debug!("inspecting {:?}", expected);
549
550            debug!("current discriminant is Ref, inserting implicit deref");
551            // Preserve the reference type. We'll need it later during THIR lowering.
552            pat_adjustments.push(expected);
553
554            expected = self.try_structurally_resolve_type(pat.span, inner_ty);
555            def_br = ByRef::Yes(match def_br {
556                // If default binding mode is by value, make it `ref` or `ref mut`
557                // (depending on whether we observe `&` or `&mut`).
558                ByRef::No |
559                // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
560                ByRef::Yes(Mutability::Mut) => inner_mutability,
561                // Once a `ref`, always a `ref`.
562                // This is because a `& &mut` cannot mutate the underlying value.
563                ByRef::Yes(Mutability::Not) => Mutability::Not,
564            });
565        }
566
567        if self.downgrade_mut_inside_shared() {
568            def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl());
569        }
570        if def_br == ByRef::Yes(Mutability::Not) {
571            max_ref_mutbl = MutblCap::Not;
572        }
573
574        if !pat_adjustments.is_empty() {
575            debug!("default binding mode is now {:?}", def_br);
576            self.typeck_results
577                .borrow_mut()
578                .pat_adjustments_mut()
579                .insert(pat.hir_id, pat_adjustments);
580        }
581
582        (expected, def_br, max_ref_mutbl)
583    }
584
585    fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
586        let ty = match &lt.kind {
587            rustc_hir::PatExprKind::Lit { lit, negated } => {
588                let ty = self.check_expr_lit(lit, Expectation::NoExpectation);
589                if *negated {
590                    self.register_bound(
591                        ty,
592                        self.tcx.require_lang_item(LangItem::Neg, Some(lt.span)),
593                        ObligationCause::dummy_with_span(lt.span),
594                    );
595                }
596                ty
597            }
598            rustc_hir::PatExprKind::ConstBlock(c) => {
599                self.check_expr_const_block(c, Expectation::NoExpectation)
600            }
601            rustc_hir::PatExprKind::Path(qpath) => {
602                let (res, opt_ty, segments) =
603                    self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span);
604                self.instantiate_value_path(segments, opt_ty, res, lt.span, lt.span, lt.hir_id).0
605            }
606        };
607        self.write_ty(lt.hir_id, ty);
608        ty
609    }
610
611    fn check_pat_lit(
612        &self,
613        span: Span,
614        lt: &hir::PatExpr<'tcx>,
615        expected: Ty<'tcx>,
616        ti: &TopInfo<'tcx>,
617    ) -> Ty<'tcx> {
618        // We've already computed the type above (when checking for a non-ref pat),
619        // so avoid computing it again.
620        let ty = self.node_ty(lt.hir_id);
621
622        // Byte string patterns behave the same way as array patterns
623        // They can denote both statically and dynamically-sized byte arrays.
624        let mut pat_ty = ty;
625        if let hir::PatExprKind::Lit {
626            lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, ..
627        } = lt.kind
628        {
629            let expected = self.structurally_resolve_type(span, expected);
630            if let ty::Ref(_, inner_ty, _) = *expected.kind()
631                && self.try_structurally_resolve_type(span, inner_ty).is_slice()
632            {
633                let tcx = self.tcx;
634                trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
635                self.typeck_results
636                    .borrow_mut()
637                    .treat_byte_string_as_slice
638                    .insert(lt.hir_id.local_id);
639                pat_ty =
640                    Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8));
641            }
642        }
643
644        if self.tcx.features().string_deref_patterns()
645            && let hir::PatExprKind::Lit {
646                lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
647            } = lt.kind
648        {
649            let tcx = self.tcx;
650            let expected = self.resolve_vars_if_possible(expected);
651            pat_ty = match expected.kind() {
652                ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => expected,
653                ty::Str => Ty::new_static_str(tcx),
654                _ => pat_ty,
655            };
656        }
657
658        // Somewhat surprising: in this case, the subtyping relation goes the
659        // opposite way as the other cases. Actually what we really want is not
660        // a subtyping relation at all but rather that there exists a LUB
661        // (so that they can be compared). However, in practice, constants are
662        // always scalars or strings. For scalars subtyping is irrelevant,
663        // and for strings `ty` is type is `&'static str`, so if we say that
664        //
665        //     &'static str <: expected
666        //
667        // then that's equivalent to there existing a LUB.
668        let cause = self.pattern_cause(ti, span);
669        if let Err(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
670            err.emit_unless(
671                ti.span
672                    .filter(|&s| {
673                        // In the case of `if`- and `while`-expressions we've already checked
674                        // that `scrutinee: bool`. We know that the pattern is `true`,
675                        // so an error here would be a duplicate and from the wrong POV.
676                        s.is_desugaring(DesugaringKind::CondTemporary)
677                    })
678                    .is_some(),
679            );
680        }
681
682        pat_ty
683    }
684
685    fn check_pat_range(
686        &self,
687        span: Span,
688        lhs: Option<&'tcx hir::PatExpr<'tcx>>,
689        rhs: Option<&'tcx hir::PatExpr<'tcx>>,
690        expected: Ty<'tcx>,
691        ti: &TopInfo<'tcx>,
692    ) -> Ty<'tcx> {
693        let calc_side = |opt_expr: Option<&'tcx hir::PatExpr<'tcx>>| match opt_expr {
694            None => None,
695            Some(expr) => {
696                let ty = self.check_pat_expr_unadjusted(expr);
697                // Check that the end-point is possibly of numeric or char type.
698                // The early check here is not for correctness, but rather better
699                // diagnostics (e.g. when `&str` is being matched, `expected` will
700                // be peeled to `str` while ty here is still `&str`, if we don't
701                // err early here, a rather confusing unification error will be
702                // emitted instead).
703                let fail =
704                    !(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error());
705                Some((fail, ty, expr.span))
706            }
707        };
708        let mut lhs = calc_side(lhs);
709        let mut rhs = calc_side(rhs);
710
711        if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
712            // There exists a side that didn't meet our criteria that the end-point
713            // be of a numeric or char type, as checked in `calc_side` above.
714            let guar = self.emit_err_pat_range(span, lhs, rhs);
715            return Ty::new_error(self.tcx, guar);
716        }
717
718        // Unify each side with `expected`.
719        // Subtyping doesn't matter here, as the value is some kind of scalar.
720        let demand_eqtype = |x: &mut _, y| {
721            if let Some((ref mut fail, x_ty, x_span)) = *x
722                && let Err(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
723            {
724                if let Some((_, y_ty, y_span)) = y {
725                    self.endpoint_has_type(&mut err, y_span, y_ty);
726                }
727                err.emit();
728                *fail = true;
729            }
730        };
731        demand_eqtype(&mut lhs, rhs);
732        demand_eqtype(&mut rhs, lhs);
733
734        if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
735            return Ty::new_misc_error(self.tcx);
736        }
737
738        // Find the unified type and check if it's of numeric or char type again.
739        // This check is needed if both sides are inference variables.
740        // We require types to be resolved here so that we emit inference failure
741        // rather than "_ is not a char or numeric".
742        let ty = self.structurally_resolve_type(span, expected);
743        if !(ty.is_numeric() || ty.is_char() || ty.references_error()) {
744            if let Some((ref mut fail, _, _)) = lhs {
745                *fail = true;
746            }
747            if let Some((ref mut fail, _, _)) = rhs {
748                *fail = true;
749            }
750            let guar = self.emit_err_pat_range(span, lhs, rhs);
751            return Ty::new_error(self.tcx, guar);
752        }
753        ty
754    }
755
756    fn endpoint_has_type(&self, err: &mut Diag<'_>, span: Span, ty: Ty<'_>) {
757        if !ty.references_error() {
758            err.span_label(span, format!("this is of type `{ty}`"));
759        }
760    }
761
762    fn emit_err_pat_range(
763        &self,
764        span: Span,
765        lhs: Option<(bool, Ty<'tcx>, Span)>,
766        rhs: Option<(bool, Ty<'tcx>, Span)>,
767    ) -> ErrorGuaranteed {
768        let span = match (lhs, rhs) {
769            (Some((true, ..)), Some((true, ..))) => span,
770            (Some((true, _, sp)), _) => sp,
771            (_, Some((true, _, sp))) => sp,
772            _ => span_bug!(span, "emit_err_pat_range: no side failed or exists but still error?"),
773        };
774        let mut err = struct_span_code_err!(
775            self.dcx(),
776            span,
777            E0029,
778            "only `char` and numeric types are allowed in range patterns"
779        );
780        let msg = |ty| {
781            let ty = self.resolve_vars_if_possible(ty);
782            format!("this is of type `{ty}` but it should be `char` or numeric")
783        };
784        let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| {
785            err.span_label(first_span, msg(first_ty));
786            if let Some((_, ty, sp)) = second {
787                let ty = self.resolve_vars_if_possible(ty);
788                self.endpoint_has_type(&mut err, sp, ty);
789            }
790        };
791        match (lhs, rhs) {
792            (Some((true, lhs_ty, lhs_sp)), Some((true, rhs_ty, rhs_sp))) => {
793                err.span_label(lhs_sp, msg(lhs_ty));
794                err.span_label(rhs_sp, msg(rhs_ty));
795            }
796            (Some((true, lhs_ty, lhs_sp)), rhs) => one_side_err(lhs_sp, lhs_ty, rhs),
797            (lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs),
798            _ => span_bug!(span, "Impossible, verified above."),
799        }
800        if (lhs, rhs).references_error() {
801            err.downgrade_to_delayed_bug();
802        }
803        if self.tcx.sess.teach(err.code.unwrap()) {
804            err.note(
805                "In a match expression, only numbers and characters can be matched \
806                    against a range. This is because the compiler checks that the range \
807                    is non-empty at compile-time, and is unable to evaluate arbitrary \
808                    comparison functions. If you want to capture values of an orderable \
809                    type between two end-points, you can use a guard.",
810            );
811        }
812        err.emit()
813    }
814
815    fn check_pat_ident(
816        &self,
817        pat: &'tcx Pat<'tcx>,
818        user_bind_annot: BindingMode,
819        var_id: HirId,
820        ident: Ident,
821        sub: Option<&'tcx Pat<'tcx>>,
822        expected: Ty<'tcx>,
823        pat_info: PatInfo<'tcx>,
824    ) -> Ty<'tcx> {
825        let PatInfo { binding_mode: def_br, top_info: ti, .. } = pat_info;
826
827        // Determine the binding mode...
828        let bm = match user_bind_annot {
829            BindingMode(ByRef::No, Mutability::Mut) if let ByRef::Yes(def_br_mutbl) = def_br => {
830                // Only mention the experimental `mut_ref` feature if if we're in edition 2024 and
831                // using other experimental matching features compatible with it.
832                if pat.span.at_least_rust_2024()
833                    && (self.tcx.features().ref_pat_eat_one_layer_2024()
834                        || self.tcx.features().ref_pat_eat_one_layer_2024_structural())
835                {
836                    if !self.tcx.features().mut_ref() {
837                        feature_err(
838                            &self.tcx.sess,
839                            sym::mut_ref,
840                            pat.span.until(ident.span),
841                            "binding cannot be both mutable and by-reference",
842                        )
843                        .emit();
844                    }
845
846                    BindingMode(def_br, Mutability::Mut)
847                } else {
848                    // `mut` resets the binding mode on edition <= 2021
849                    self.add_rust_2024_migration_desugared_pat(
850                        pat_info.top_info.hir_id,
851                        pat,
852                        't', // last char of `mut`
853                        def_br_mutbl,
854                    );
855                    BindingMode(ByRef::No, Mutability::Mut)
856                }
857            }
858            BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
859            BindingMode(ByRef::Yes(user_br_mutbl), _) => {
860                if let ByRef::Yes(def_br_mutbl) = def_br {
861                    // `ref`/`ref mut` overrides the binding mode on edition <= 2021
862                    self.add_rust_2024_migration_desugared_pat(
863                        pat_info.top_info.hir_id,
864                        pat,
865                        match user_br_mutbl {
866                            Mutability::Not => 'f', // last char of `ref`
867                            Mutability::Mut => 't', // last char of `ref mut`
868                        },
869                        def_br_mutbl,
870                    );
871                }
872                user_bind_annot
873            }
874        };
875
876        if bm.0 == ByRef::Yes(Mutability::Mut)
877            && let MutblCap::WeaklyNot(and_pat_span) = pat_info.max_ref_mutbl
878        {
879            let mut err = struct_span_code_err!(
880                self.dcx(),
881                ident.span,
882                E0596,
883                "cannot borrow as mutable inside an `&` pattern"
884            );
885
886            if let Some(span) = and_pat_span {
887                err.span_suggestion(
888                    span,
889                    "replace this `&` with `&mut`",
890                    "&mut ",
891                    Applicability::MachineApplicable,
892                );
893            }
894            err.emit();
895        }
896
897        // ...and store it in a side table:
898        self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
899
900        debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
901
902        let local_ty = self.local_ty(pat.span, pat.hir_id);
903        let eq_ty = match bm.0 {
904            ByRef::Yes(mutbl) => {
905                // If the binding is like `ref x | ref mut x`,
906                // then `x` is assigned a value of type `&M T` where M is the
907                // mutability and T is the expected type.
908                //
909                // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)`
910                // is required. However, we use equality, which is stronger.
911                // See (note_1) for an explanation.
912                self.new_ref_ty(pat.span, mutbl, expected)
913            }
914            // Otherwise, the type of x is the expected type `T`.
915            ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
916        };
917
918        // We have a concrete type for the local, so we do not need to taint it and hide follow up errors *using* the local.
919        let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, &ti);
920
921        // If there are multiple arms, make sure they all agree on
922        // what the type of the binding `x` ought to be.
923        if var_id != pat.hir_id {
924            self.check_binding_alt_eq_ty(user_bind_annot, pat.span, var_id, local_ty, &ti);
925        }
926
927        if let Some(p) = sub {
928            self.check_pat(p, expected, pat_info);
929        }
930
931        local_ty
932    }
933
934    /// When a variable is bound several times in a `PatKind::Or`, it'll resolve all of the
935    /// subsequent bindings of the same name to the first usage. Verify that all of these
936    /// bindings have the same type by comparing them all against the type of that first pat.
937    fn check_binding_alt_eq_ty(
938        &self,
939        ba: BindingMode,
940        span: Span,
941        var_id: HirId,
942        ty: Ty<'tcx>,
943        ti: &TopInfo<'tcx>,
944    ) {
945        let var_ty = self.local_ty(span, var_id);
946        if let Err(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
947            let hir = self.tcx.hir();
948            let var_ty = self.resolve_vars_if_possible(var_ty);
949            let msg = format!("first introduced with type `{var_ty}` here");
950            err.span_label(hir.span(var_id), msg);
951            let in_match = self.tcx.hir_parent_iter(var_id).any(|(_, n)| {
952                matches!(
953                    n,
954                    hir::Node::Expr(hir::Expr {
955                        kind: hir::ExprKind::Match(.., hir::MatchSource::Normal),
956                        ..
957                    })
958                )
959            });
960            let pre = if in_match { "in the same arm, " } else { "" };
961            err.note(format!("{pre}a binding must have the same type in all alternatives"));
962            self.suggest_adding_missing_ref_or_removing_ref(
963                &mut err,
964                span,
965                var_ty,
966                self.resolve_vars_if_possible(ty),
967                ba,
968            );
969            err.emit();
970        }
971    }
972
973    fn suggest_adding_missing_ref_or_removing_ref(
974        &self,
975        err: &mut Diag<'_>,
976        span: Span,
977        expected: Ty<'tcx>,
978        actual: Ty<'tcx>,
979        ba: BindingMode,
980    ) {
981        match (expected.kind(), actual.kind(), ba) {
982            (ty::Ref(_, inner_ty, _), _, BindingMode::NONE)
983                if self.can_eq(self.param_env, *inner_ty, actual) =>
984            {
985                err.span_suggestion_verbose(
986                    span.shrink_to_lo(),
987                    "consider adding `ref`",
988                    "ref ",
989                    Applicability::MaybeIncorrect,
990                );
991            }
992            (_, ty::Ref(_, inner_ty, _), BindingMode::REF)
993                if self.can_eq(self.param_env, expected, *inner_ty) =>
994            {
995                err.span_suggestion_verbose(
996                    span.with_hi(span.lo() + BytePos(4)),
997                    "consider removing `ref`",
998                    "",
999                    Applicability::MaybeIncorrect,
1000                );
1001            }
1002            _ => (),
1003        }
1004    }
1005
1006    /// Precondition: pat is a `Ref(_)` pattern
1007    fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) {
1008        let tcx = self.tcx;
1009        if let PatKind::Ref(inner, mutbl) = pat.kind
1010            && let PatKind::Binding(_, _, binding, ..) = inner.kind
1011        {
1012            let binding_parent = tcx.parent_hir_node(pat.hir_id);
1013            debug!(?inner, ?pat, ?binding_parent);
1014
1015            let mutability = match mutbl {
1016                ast::Mutability::Mut => "mut",
1017                ast::Mutability::Not => "",
1018            };
1019
1020            let mut_var_suggestion = 'block: {
1021                if mutbl.is_not() {
1022                    break 'block None;
1023                }
1024
1025                let ident_kind = match binding_parent {
1026                    hir::Node::Param(_) => "parameter",
1027                    hir::Node::LetStmt(_) => "variable",
1028                    hir::Node::Arm(_) => "binding",
1029
1030                    // Provide diagnostics only if the parent pattern is struct-like,
1031                    // i.e. where `mut binding` makes sense
1032                    hir::Node::Pat(Pat { kind, .. }) => match kind {
1033                        PatKind::Struct(..)
1034                        | PatKind::TupleStruct(..)
1035                        | PatKind::Or(..)
1036                        | PatKind::Guard(..)
1037                        | PatKind::Tuple(..)
1038                        | PatKind::Slice(..) => "binding",
1039
1040                        PatKind::Wild
1041                        | PatKind::Never
1042                        | PatKind::Binding(..)
1043                        | PatKind::Box(..)
1044                        | PatKind::Deref(_)
1045                        | PatKind::Ref(..)
1046                        | PatKind::Expr(..)
1047                        | PatKind::Range(..)
1048                        | PatKind::Err(_) => break 'block None,
1049                    },
1050
1051                    // Don't provide suggestions in other cases
1052                    _ => break 'block None,
1053                };
1054
1055                Some((
1056                    pat.span,
1057                    format!("to declare a mutable {ident_kind} use"),
1058                    format!("mut {binding}"),
1059                ))
1060            };
1061
1062            match binding_parent {
1063                // Check that there is explicit type (ie this is not a closure param with inferred type)
1064                // so we don't suggest moving something to the type that does not exist
1065                hir::Node::Param(hir::Param { ty_span, pat, .. }) if pat.span != *ty_span => {
1066                    err.multipart_suggestion_verbose(
1067                        format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"),
1068                        vec![
1069                            (pat.span.until(inner.span), "".to_owned()),
1070                            (ty_span.shrink_to_lo(), mutbl.ref_prefix_str().to_owned()),
1071                        ],
1072                        Applicability::MachineApplicable
1073                    );
1074
1075                    if let Some((sp, msg, sugg)) = mut_var_suggestion {
1076                        err.span_note(sp, format!("{msg}: `{sugg}`"));
1077                    }
1078                }
1079                hir::Node::Pat(pt) if let PatKind::TupleStruct(_, pat_arr, _) = pt.kind => {
1080                    for i in pat_arr.iter() {
1081                        if let PatKind::Ref(the_ref, _) = i.kind
1082                            && let PatKind::Binding(mt, _, ident, _) = the_ref.kind
1083                        {
1084                            let BindingMode(_, mtblty) = mt;
1085                            err.span_suggestion_verbose(
1086                                i.span,
1087                                format!("consider removing `&{mutability}` from the pattern"),
1088                                mtblty.prefix_str().to_string() + &ident.name.to_string(),
1089                                Applicability::MaybeIncorrect,
1090                            );
1091                        }
1092                    }
1093                    if let Some((sp, msg, sugg)) = mut_var_suggestion {
1094                        err.span_note(sp, format!("{msg}: `{sugg}`"));
1095                    }
1096                }
1097                hir::Node::Param(_) | hir::Node::Arm(_) | hir::Node::Pat(_) => {
1098                    // rely on match ergonomics or it might be nested `&&pat`
1099                    err.span_suggestion_verbose(
1100                        pat.span.until(inner.span),
1101                        format!("consider removing `&{mutability}` from the pattern"),
1102                        "",
1103                        Applicability::MaybeIncorrect,
1104                    );
1105
1106                    if let Some((sp, msg, sugg)) = mut_var_suggestion {
1107                        err.span_note(sp, format!("{msg}: `{sugg}`"));
1108                    }
1109                }
1110                _ if let Some((sp, msg, sugg)) = mut_var_suggestion => {
1111                    err.span_suggestion(sp, msg, sugg, Applicability::MachineApplicable);
1112                }
1113                _ => {} // don't provide suggestions in other cases #55175
1114            }
1115        }
1116    }
1117
1118    fn check_dereferenceable(
1119        &self,
1120        span: Span,
1121        expected: Ty<'tcx>,
1122        inner: &Pat<'_>,
1123    ) -> Result<(), ErrorGuaranteed> {
1124        if let PatKind::Binding(..) = inner.kind
1125            && let Some(pointee_ty) = self.shallow_resolve(expected).builtin_deref(true)
1126            && let ty::Dynamic(..) = pointee_ty.kind()
1127        {
1128            // This is "x = dyn SomeTrait" being reduced from
1129            // "let &x = &dyn SomeTrait" or "let box x = Box<dyn SomeTrait>", an error.
1130            let type_str = self.ty_to_string(expected);
1131            let mut err = struct_span_code_err!(
1132                self.dcx(),
1133                span,
1134                E0033,
1135                "type `{}` cannot be dereferenced",
1136                type_str
1137            );
1138            err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
1139            if self.tcx.sess.teach(err.code.unwrap()) {
1140                err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
1141            }
1142            return Err(err.emit());
1143        }
1144        Ok(())
1145    }
1146
1147    fn check_pat_struct(
1148        &self,
1149        pat: &'tcx Pat<'tcx>,
1150        qpath: &hir::QPath<'tcx>,
1151        fields: &'tcx [hir::PatField<'tcx>],
1152        has_rest_pat: bool,
1153        expected: Ty<'tcx>,
1154        pat_info: PatInfo<'tcx>,
1155    ) -> Ty<'tcx> {
1156        // Resolve the path and check the definition for errors.
1157        let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) {
1158            Ok(data) => data,
1159            Err(guar) => {
1160                let err = Ty::new_error(self.tcx, guar);
1161                for field in fields {
1162                    self.check_pat(field.pat, err, pat_info);
1163                }
1164                return err;
1165            }
1166        };
1167
1168        // Type-check the path.
1169        let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
1170
1171        // Type-check subpatterns.
1172        match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
1173            Ok(()) => pat_ty,
1174            Err(guar) => Ty::new_error(self.tcx, guar),
1175        }
1176    }
1177
1178    fn check_pat_path(
1179        &self,
1180        path_id: HirId,
1181        pat_id_for_diag: HirId,
1182        span: Span,
1183        qpath: &hir::QPath<'_>,
1184        path_resolution: (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
1185        expected: Ty<'tcx>,
1186        ti: &TopInfo<'tcx>,
1187    ) -> Ty<'tcx> {
1188        let tcx = self.tcx;
1189
1190        // We have already resolved the path.
1191        let (res, opt_ty, segments) = path_resolution;
1192        match res {
1193            Res::Err => {
1194                let e =
1195                    self.dcx().span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted");
1196                self.set_tainted_by_errors(e);
1197                return Ty::new_error(tcx, e);
1198            }
1199            Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
1200                let expected = "unit struct, unit variant or constant";
1201                let e = report_unexpected_variant_res(tcx, res, None, qpath, span, E0533, expected);
1202                return Ty::new_error(tcx, e);
1203            }
1204            Res::SelfCtor(def_id) => {
1205                if let ty::Adt(adt_def, _) = *tcx.type_of(def_id).skip_binder().kind()
1206                    && adt_def.is_struct()
1207                    && let Some((CtorKind::Const, _)) = adt_def.non_enum_variant().ctor
1208                {
1209                    // Ok, we allow unit struct ctors in patterns only.
1210                } else {
1211                    let e = report_unexpected_variant_res(
1212                        tcx,
1213                        res,
1214                        None,
1215                        qpath,
1216                        span,
1217                        E0533,
1218                        "unit struct",
1219                    );
1220                    return Ty::new_error(tcx, e);
1221                }
1222            }
1223            Res::Def(
1224                DefKind::Ctor(_, CtorKind::Const)
1225                | DefKind::Const
1226                | DefKind::AssocConst
1227                | DefKind::ConstParam,
1228                _,
1229            ) => {} // OK
1230            _ => bug!("unexpected pattern resolution: {:?}", res),
1231        }
1232
1233        // Type-check the path.
1234        let (pat_ty, pat_res) =
1235            self.instantiate_value_path(segments, opt_ty, res, span, span, path_id);
1236        if let Err(err) =
1237            self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, pat_ty)
1238        {
1239            self.emit_bad_pat_path(err, pat_id_for_diag, span, res, pat_res, pat_ty, segments);
1240        }
1241        pat_ty
1242    }
1243
1244    fn maybe_suggest_range_literal(
1245        &self,
1246        e: &mut Diag<'_>,
1247        opt_def_id: Option<hir::def_id::DefId>,
1248        ident: Ident,
1249    ) -> bool {
1250        match opt_def_id {
1251            Some(def_id) => match self.tcx.hir_get_if_local(def_id) {
1252                Some(hir::Node::Item(hir::Item {
1253                    kind: hir::ItemKind::Const(_, _, _, body_id),
1254                    ..
1255                })) => match self.tcx.hir_node(body_id.hir_id) {
1256                    hir::Node::Expr(expr) => {
1257                        if hir::is_range_literal(expr) {
1258                            let span = self.tcx.hir().span(body_id.hir_id);
1259                            if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) {
1260                                e.span_suggestion_verbose(
1261                                    ident.span,
1262                                    "you may want to move the range into the match block",
1263                                    snip,
1264                                    Applicability::MachineApplicable,
1265                                );
1266                                return true;
1267                            }
1268                        }
1269                    }
1270                    _ => (),
1271                },
1272                _ => (),
1273            },
1274            _ => (),
1275        }
1276        false
1277    }
1278
1279    fn emit_bad_pat_path(
1280        &self,
1281        mut e: Diag<'_>,
1282        hir_id: HirId,
1283        pat_span: Span,
1284        res: Res,
1285        pat_res: Res,
1286        pat_ty: Ty<'tcx>,
1287        segments: &'tcx [hir::PathSegment<'tcx>],
1288    ) {
1289        if let Some(span) = self.tcx.hir().res_span(pat_res) {
1290            e.span_label(span, format!("{} defined here", res.descr()));
1291            if let [hir::PathSegment { ident, .. }] = &*segments {
1292                e.span_label(
1293                    pat_span,
1294                    format!(
1295                        "`{}` is interpreted as {} {}, not a new binding",
1296                        ident,
1297                        res.article(),
1298                        res.descr(),
1299                    ),
1300                );
1301                match self.tcx.parent_hir_node(hir_id) {
1302                    hir::Node::PatField(..) => {
1303                        e.span_suggestion_verbose(
1304                            ident.span.shrink_to_hi(),
1305                            "bind the struct field to a different name instead",
1306                            format!(": other_{}", ident.as_str().to_lowercase()),
1307                            Applicability::HasPlaceholders,
1308                        );
1309                    }
1310                    _ => {
1311                        let (type_def_id, item_def_id) = match pat_ty.kind() {
1312                            ty::Adt(def, _) => match res {
1313                                Res::Def(DefKind::Const, def_id) => (Some(def.did()), Some(def_id)),
1314                                _ => (None, None),
1315                            },
1316                            _ => (None, None),
1317                        };
1318
1319                        let ranges = &[
1320                            self.tcx.lang_items().range_struct(),
1321                            self.tcx.lang_items().range_from_struct(),
1322                            self.tcx.lang_items().range_to_struct(),
1323                            self.tcx.lang_items().range_full_struct(),
1324                            self.tcx.lang_items().range_inclusive_struct(),
1325                            self.tcx.lang_items().range_to_inclusive_struct(),
1326                        ];
1327                        if type_def_id != None && ranges.contains(&type_def_id) {
1328                            if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
1329                                let msg = "constants only support matching by type, \
1330                                    if you meant to match against a range of values, \
1331                                    consider using a range pattern like `min ..= max` in the match block";
1332                                e.note(msg);
1333                            }
1334                        } else {
1335                            let msg = "introduce a new binding instead";
1336                            let sugg = format!("other_{}", ident.as_str().to_lowercase());
1337                            e.span_suggestion(
1338                                ident.span,
1339                                msg,
1340                                sugg,
1341                                Applicability::HasPlaceholders,
1342                            );
1343                        }
1344                    }
1345                };
1346            }
1347        }
1348        e.emit();
1349    }
1350
1351    fn check_pat_tuple_struct(
1352        &self,
1353        pat: &'tcx Pat<'tcx>,
1354        qpath: &'tcx hir::QPath<'tcx>,
1355        subpats: &'tcx [Pat<'tcx>],
1356        ddpos: hir::DotDotPos,
1357        expected: Ty<'tcx>,
1358        pat_info: PatInfo<'tcx>,
1359    ) -> Ty<'tcx> {
1360        let tcx = self.tcx;
1361        let on_error = |e| {
1362            for pat in subpats {
1363                self.check_pat(pat, Ty::new_error(tcx, e), pat_info);
1364            }
1365        };
1366        let report_unexpected_res = |res: Res| {
1367            let expected = "tuple struct or tuple variant";
1368            let e = report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected);
1369            on_error(e);
1370            e
1371        };
1372
1373        // Resolve the path and check the definition for errors.
1374        let (res, opt_ty, segments) =
1375            self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
1376        if res == Res::Err {
1377            let e = self.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
1378            self.set_tainted_by_errors(e);
1379            on_error(e);
1380            return Ty::new_error(tcx, e);
1381        }
1382
1383        // Type-check the path.
1384        let (pat_ty, res) =
1385            self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
1386        if !pat_ty.is_fn() {
1387            let e = report_unexpected_res(res);
1388            return Ty::new_error(tcx, e);
1389        }
1390
1391        let variant = match res {
1392            Res::Err => {
1393                self.dcx().span_bug(pat.span, "`Res::Err` but no error emitted");
1394            }
1395            Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
1396                let e = report_unexpected_res(res);
1397                return Ty::new_error(tcx, e);
1398            }
1399            Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
1400            _ => bug!("unexpected pattern resolution: {:?}", res),
1401        };
1402
1403        // Replace constructor type with constructed type for tuple struct patterns.
1404        let pat_ty = pat_ty.fn_sig(tcx).output();
1405        let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1406
1407        // Type-check the tuple struct pattern against the expected type.
1408        let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info);
1409        let had_err = diag.map_err(|diag| diag.emit());
1410
1411        // Type-check subpatterns.
1412        if subpats.len() == variant.fields.len()
1413            || subpats.len() < variant.fields.len() && ddpos.as_opt_usize().is_some()
1414        {
1415            let ty::Adt(_, args) = pat_ty.kind() else {
1416                bug!("unexpected pattern type {:?}", pat_ty);
1417            };
1418            for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
1419                let field = &variant.fields[FieldIdx::from_usize(i)];
1420                let field_ty = self.field_ty(subpat.span, field, args);
1421                self.check_pat(subpat, field_ty, pat_info);
1422
1423                self.tcx.check_stability(
1424                    variant.fields[FieldIdx::from_usize(i)].did,
1425                    Some(subpat.hir_id),
1426                    subpat.span,
1427                    None,
1428                );
1429            }
1430            if let Err(e) = had_err {
1431                on_error(e);
1432                return Ty::new_error(tcx, e);
1433            }
1434        } else {
1435            let e = self.emit_err_pat_wrong_number_of_fields(
1436                pat.span,
1437                res,
1438                qpath,
1439                subpats,
1440                &variant.fields.raw,
1441                expected,
1442                had_err,
1443            );
1444            on_error(e);
1445            return Ty::new_error(tcx, e);
1446        }
1447        pat_ty
1448    }
1449
1450    fn emit_err_pat_wrong_number_of_fields(
1451        &self,
1452        pat_span: Span,
1453        res: Res,
1454        qpath: &hir::QPath<'_>,
1455        subpats: &'tcx [Pat<'tcx>],
1456        fields: &'tcx [ty::FieldDef],
1457        expected: Ty<'tcx>,
1458        had_err: Result<(), ErrorGuaranteed>,
1459    ) -> ErrorGuaranteed {
1460        let subpats_ending = pluralize!(subpats.len());
1461        let fields_ending = pluralize!(fields.len());
1462
1463        let subpat_spans = if subpats.is_empty() {
1464            vec![pat_span]
1465        } else {
1466            subpats.iter().map(|p| p.span).collect()
1467        };
1468        let last_subpat_span = *subpat_spans.last().unwrap();
1469        let res_span = self.tcx.def_span(res.def_id());
1470        let def_ident_span = self.tcx.def_ident_span(res.def_id()).unwrap_or(res_span);
1471        let field_def_spans = if fields.is_empty() {
1472            vec![res_span]
1473        } else {
1474            fields.iter().map(|f| f.ident(self.tcx).span).collect()
1475        };
1476        let last_field_def_span = *field_def_spans.last().unwrap();
1477
1478        let mut err = struct_span_code_err!(
1479            self.dcx(),
1480            MultiSpan::from_spans(subpat_spans),
1481            E0023,
1482            "this pattern has {} field{}, but the corresponding {} has {} field{}",
1483            subpats.len(),
1484            subpats_ending,
1485            res.descr(),
1486            fields.len(),
1487            fields_ending,
1488        );
1489        err.span_label(
1490            last_subpat_span,
1491            format!("expected {} field{}, found {}", fields.len(), fields_ending, subpats.len()),
1492        );
1493        if self.tcx.sess.source_map().is_multiline(qpath.span().between(last_subpat_span)) {
1494            err.span_label(qpath.span(), "");
1495        }
1496        if self.tcx.sess.source_map().is_multiline(def_ident_span.between(last_field_def_span)) {
1497            err.span_label(def_ident_span, format!("{} defined here", res.descr()));
1498        }
1499        for span in &field_def_spans[..field_def_spans.len() - 1] {
1500            err.span_label(*span, "");
1501        }
1502        err.span_label(
1503            last_field_def_span,
1504            format!("{} has {} field{}", res.descr(), fields.len(), fields_ending),
1505        );
1506
1507        // Identify the case `Some(x, y)` where the expected type is e.g. `Option<(T, U)>`.
1508        // More generally, the expected type wants a tuple variant with one field of an
1509        // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
1510        // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
1511        let missing_parentheses = match (expected.kind(), fields, had_err) {
1512            // #67037: only do this if we could successfully type-check the expected type against
1513            // the tuple struct pattern. Otherwise the args could get out of range on e.g.,
1514            // `let P() = U;` where `P != U` with `struct P<T>(T);`.
1515            (ty::Adt(_, args), [field], Ok(())) => {
1516                let field_ty = self.field_ty(pat_span, field, args);
1517                match field_ty.kind() {
1518                    ty::Tuple(fields) => fields.len() == subpats.len(),
1519                    _ => false,
1520                }
1521            }
1522            _ => false,
1523        };
1524        if missing_parentheses {
1525            let (left, right) = match subpats {
1526                // This is the zero case; we aim to get the "hi" part of the `QPath`'s
1527                // span as the "lo" and then the "hi" part of the pattern's span as the "hi".
1528                // This looks like:
1529                //
1530                // help: missing parentheses
1531                //   |
1532                // L |     let A(()) = A(());
1533                //   |          ^  ^
1534                [] => (qpath.span().shrink_to_hi(), pat_span),
1535                // Easy case. Just take the "lo" of the first sub-pattern and the "hi" of the
1536                // last sub-pattern. In the case of `A(x)` the first and last may coincide.
1537                // This looks like:
1538                //
1539                // help: missing parentheses
1540                //   |
1541                // L |     let A((x, y)) = A((1, 2));
1542                //   |           ^    ^
1543                [first, ..] => (first.span.shrink_to_lo(), subpats.last().unwrap().span),
1544            };
1545            err.multipart_suggestion(
1546                "missing parentheses",
1547                vec![(left, "(".to_string()), (right.shrink_to_hi(), ")".to_string())],
1548                Applicability::MachineApplicable,
1549            );
1550        } else if fields.len() > subpats.len() && pat_span != DUMMY_SP {
1551            let after_fields_span = pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi();
1552            let all_fields_span = match subpats {
1553                [] => after_fields_span,
1554                [field] => field.span,
1555                [first, .., last] => first.span.to(last.span),
1556            };
1557
1558            // Check if all the fields in the pattern are wildcards.
1559            let all_wildcards = subpats.iter().all(|pat| matches!(pat.kind, PatKind::Wild));
1560            let first_tail_wildcard =
1561                subpats.iter().enumerate().fold(None, |acc, (pos, pat)| match (acc, &pat.kind) {
1562                    (None, PatKind::Wild) => Some(pos),
1563                    (Some(_), PatKind::Wild) => acc,
1564                    _ => None,
1565                });
1566            let tail_span = match first_tail_wildcard {
1567                None => after_fields_span,
1568                Some(0) => subpats[0].span.to(after_fields_span),
1569                Some(pos) => subpats[pos - 1].span.shrink_to_hi().to(after_fields_span),
1570            };
1571
1572            // FIXME: heuristic-based suggestion to check current types for where to add `_`.
1573            let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", ");
1574            if !subpats.is_empty() {
1575                wildcard_sugg = String::from(", ") + &wildcard_sugg;
1576            }
1577
1578            err.span_suggestion_verbose(
1579                after_fields_span,
1580                "use `_` to explicitly ignore each field",
1581                wildcard_sugg,
1582                Applicability::MaybeIncorrect,
1583            );
1584
1585            // Only suggest `..` if more than one field is missing
1586            // or the pattern consists of all wildcards.
1587            if fields.len() - subpats.len() > 1 || all_wildcards {
1588                if subpats.is_empty() || all_wildcards {
1589                    err.span_suggestion_verbose(
1590                        all_fields_span,
1591                        "use `..` to ignore all fields",
1592                        "..",
1593                        Applicability::MaybeIncorrect,
1594                    );
1595                } else {
1596                    err.span_suggestion_verbose(
1597                        tail_span,
1598                        "use `..` to ignore the rest of the fields",
1599                        ", ..",
1600                        Applicability::MaybeIncorrect,
1601                    );
1602                }
1603            }
1604        }
1605
1606        err.emit()
1607    }
1608
1609    fn check_pat_tuple(
1610        &self,
1611        span: Span,
1612        elements: &'tcx [Pat<'tcx>],
1613        ddpos: hir::DotDotPos,
1614        expected: Ty<'tcx>,
1615        pat_info: PatInfo<'tcx>,
1616    ) -> Ty<'tcx> {
1617        let tcx = self.tcx;
1618        let mut expected_len = elements.len();
1619        if ddpos.as_opt_usize().is_some() {
1620            // Require known type only when `..` is present.
1621            if let ty::Tuple(tys) = self.structurally_resolve_type(span, expected).kind() {
1622                expected_len = tys.len();
1623            }
1624        }
1625        let max_len = cmp::max(expected_len, elements.len());
1626
1627        let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(span));
1628        let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
1629        let pat_ty = Ty::new_tup(tcx, element_tys);
1630        if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, &pat_info.top_info) {
1631            // Walk subpatterns with an expected type of `err` in this case to silence
1632            // further errors being emitted when using the bindings. #50333
1633            let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
1634            for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
1635                self.check_pat(elem, Ty::new_error(tcx, reported), pat_info);
1636            }
1637            Ty::new_tup_from_iter(tcx, element_tys_iter)
1638        } else {
1639            for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
1640                self.check_pat(elem, element_tys[i], pat_info);
1641            }
1642            pat_ty
1643        }
1644    }
1645
1646    fn check_struct_pat_fields(
1647        &self,
1648        adt_ty: Ty<'tcx>,
1649        pat: &'tcx Pat<'tcx>,
1650        variant: &'tcx ty::VariantDef,
1651        fields: &'tcx [hir::PatField<'tcx>],
1652        has_rest_pat: bool,
1653        pat_info: PatInfo<'tcx>,
1654    ) -> Result<(), ErrorGuaranteed> {
1655        let tcx = self.tcx;
1656
1657        let ty::Adt(adt, args) = adt_ty.kind() else {
1658            span_bug!(pat.span, "struct pattern is not an ADT");
1659        };
1660
1661        // Index the struct fields' types.
1662        let field_map = variant
1663            .fields
1664            .iter_enumerated()
1665            .map(|(i, field)| (field.ident(self.tcx).normalize_to_macros_2_0(), (i, field)))
1666            .collect::<FxHashMap<_, _>>();
1667
1668        // Keep track of which fields have already appeared in the pattern.
1669        let mut used_fields = FxHashMap::default();
1670        let mut result = Ok(());
1671
1672        let mut inexistent_fields = vec![];
1673        // Typecheck each field.
1674        for field in fields {
1675            let span = field.span;
1676            let ident = tcx.adjust_ident(field.ident, variant.def_id);
1677            let field_ty = match used_fields.entry(ident) {
1678                Occupied(occupied) => {
1679                    let guar = self.error_field_already_bound(span, field.ident, *occupied.get());
1680                    result = Err(guar);
1681                    Ty::new_error(tcx, guar)
1682                }
1683                Vacant(vacant) => {
1684                    vacant.insert(span);
1685                    field_map
1686                        .get(&ident)
1687                        .map(|(i, f)| {
1688                            self.write_field_index(field.hir_id, *i);
1689                            self.tcx.check_stability(f.did, Some(field.hir_id), span, None);
1690                            self.field_ty(span, f, args)
1691                        })
1692                        .unwrap_or_else(|| {
1693                            inexistent_fields.push(field);
1694                            Ty::new_misc_error(tcx)
1695                        })
1696                }
1697            };
1698
1699            self.check_pat(field.pat, field_ty, pat_info);
1700        }
1701
1702        let mut unmentioned_fields = variant
1703            .fields
1704            .iter()
1705            .map(|field| (field, field.ident(self.tcx).normalize_to_macros_2_0()))
1706            .filter(|(_, ident)| !used_fields.contains_key(ident))
1707            .collect::<Vec<_>>();
1708
1709        let inexistent_fields_err = if !inexistent_fields.is_empty()
1710            && !inexistent_fields.iter().any(|field| field.ident.name == kw::Underscore)
1711        {
1712            // we don't care to report errors for a struct if the struct itself is tainted
1713            variant.has_errors()?;
1714            Some(self.error_inexistent_fields(
1715                adt.variant_descr(),
1716                &inexistent_fields,
1717                &mut unmentioned_fields,
1718                pat,
1719                variant,
1720                args,
1721            ))
1722        } else {
1723            None
1724        };
1725
1726        // Require `..` if struct has non_exhaustive attribute.
1727        let non_exhaustive = variant.field_list_has_applicable_non_exhaustive();
1728        if non_exhaustive && !has_rest_pat {
1729            self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty());
1730        }
1731
1732        let mut unmentioned_err = None;
1733        // Report an error if an incorrect number of fields was specified.
1734        if adt.is_union() {
1735            if fields.len() != 1 {
1736                self.dcx().emit_err(errors::UnionPatMultipleFields { span: pat.span });
1737            }
1738            if has_rest_pat {
1739                self.dcx().emit_err(errors::UnionPatDotDot { span: pat.span });
1740            }
1741        } else if !unmentioned_fields.is_empty() {
1742            let accessible_unmentioned_fields: Vec<_> = unmentioned_fields
1743                .iter()
1744                .copied()
1745                .filter(|(field, _)| self.is_field_suggestable(field, pat.hir_id, pat.span))
1746                .collect();
1747
1748            if !has_rest_pat {
1749                if accessible_unmentioned_fields.is_empty() {
1750                    unmentioned_err = Some(self.error_no_accessible_fields(pat, fields));
1751                } else {
1752                    unmentioned_err = Some(self.error_unmentioned_fields(
1753                        pat,
1754                        &accessible_unmentioned_fields,
1755                        accessible_unmentioned_fields.len() != unmentioned_fields.len(),
1756                        fields,
1757                    ));
1758                }
1759            } else if non_exhaustive && !accessible_unmentioned_fields.is_empty() {
1760                self.lint_non_exhaustive_omitted_patterns(
1761                    pat,
1762                    &accessible_unmentioned_fields,
1763                    adt_ty,
1764                )
1765            }
1766        }
1767        match (inexistent_fields_err, unmentioned_err) {
1768            (Some(i), Some(u)) => {
1769                if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
1770                    // We don't want to show the nonexistent fields error when this was
1771                    // `Foo { a, b }` when it should have been `Foo(a, b)`.
1772                    i.delay_as_bug();
1773                    u.delay_as_bug();
1774                    Err(e)
1775                } else {
1776                    i.emit();
1777                    Err(u.emit())
1778                }
1779            }
1780            (None, Some(u)) => {
1781                if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
1782                    u.delay_as_bug();
1783                    Err(e)
1784                } else {
1785                    Err(u.emit())
1786                }
1787            }
1788            (Some(err), None) => Err(err.emit()),
1789            (None, None) => {
1790                self.error_tuple_variant_index_shorthand(variant, pat, fields)?;
1791                result
1792            }
1793        }
1794    }
1795
1796    fn error_tuple_variant_index_shorthand(
1797        &self,
1798        variant: &VariantDef,
1799        pat: &'_ Pat<'_>,
1800        fields: &[hir::PatField<'_>],
1801    ) -> Result<(), ErrorGuaranteed> {
1802        // if this is a tuple struct, then all field names will be numbers
1803        // so if any fields in a struct pattern use shorthand syntax, they will
1804        // be invalid identifiers (for example, Foo { 0, 1 }).
1805        if let (Some(CtorKind::Fn), PatKind::Struct(qpath, field_patterns, ..)) =
1806            (variant.ctor_kind(), &pat.kind)
1807        {
1808            let has_shorthand_field_name = field_patterns.iter().any(|field| field.is_shorthand);
1809            if has_shorthand_field_name {
1810                let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
1811                let mut err = struct_span_code_err!(
1812                    self.dcx(),
1813                    pat.span,
1814                    E0769,
1815                    "tuple variant `{path}` written as struct variant",
1816                );
1817                err.span_suggestion_verbose(
1818                    qpath.span().shrink_to_hi().to(pat.span.shrink_to_hi()),
1819                    "use the tuple variant pattern syntax instead",
1820                    format!("({})", self.get_suggested_tuple_struct_pattern(fields, variant)),
1821                    Applicability::MaybeIncorrect,
1822                );
1823                return Err(err.emit());
1824            }
1825        }
1826        Ok(())
1827    }
1828
1829    fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) {
1830        let sess = self.tcx.sess;
1831        let sm = sess.source_map();
1832        let sp_brace = sm.end_point(pat.span);
1833        let sp_comma = sm.end_point(pat.span.with_hi(sp_brace.hi()));
1834        let sugg = if no_fields || sp_brace != sp_comma { ".. }" } else { ", .. }" };
1835
1836        struct_span_code_err!(
1837            self.dcx(),
1838            pat.span,
1839            E0638,
1840            "`..` required with {descr} marked as non-exhaustive",
1841        )
1842        .with_span_suggestion_verbose(
1843            sp_comma,
1844            "add `..` at the end of the field list to ignore all other fields",
1845            sugg,
1846            Applicability::MachineApplicable,
1847        )
1848        .emit();
1849    }
1850
1851    fn error_field_already_bound(
1852        &self,
1853        span: Span,
1854        ident: Ident,
1855        other_field: Span,
1856    ) -> ErrorGuaranteed {
1857        struct_span_code_err!(
1858            self.dcx(),
1859            span,
1860            E0025,
1861            "field `{}` bound multiple times in the pattern",
1862            ident
1863        )
1864        .with_span_label(span, format!("multiple uses of `{ident}` in pattern"))
1865        .with_span_label(other_field, format!("first use of `{ident}`"))
1866        .emit()
1867    }
1868
1869    fn error_inexistent_fields(
1870        &self,
1871        kind_name: &str,
1872        inexistent_fields: &[&hir::PatField<'tcx>],
1873        unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>,
1874        pat: &'tcx Pat<'tcx>,
1875        variant: &ty::VariantDef,
1876        args: ty::GenericArgsRef<'tcx>,
1877    ) -> Diag<'a> {
1878        let tcx = self.tcx;
1879        let (field_names, t, plural) = if let [field] = inexistent_fields {
1880            (format!("a field named `{}`", field.ident), "this", "")
1881        } else {
1882            (
1883                format!(
1884                    "fields named {}",
1885                    inexistent_fields
1886                        .iter()
1887                        .map(|field| format!("`{}`", field.ident))
1888                        .collect::<Vec<String>>()
1889                        .join(", ")
1890                ),
1891                "these",
1892                "s",
1893            )
1894        };
1895        let spans = inexistent_fields.iter().map(|field| field.ident.span).collect::<Vec<_>>();
1896        let mut err = struct_span_code_err!(
1897            self.dcx(),
1898            spans,
1899            E0026,
1900            "{} `{}` does not have {}",
1901            kind_name,
1902            tcx.def_path_str(variant.def_id),
1903            field_names
1904        );
1905        if let Some(pat_field) = inexistent_fields.last() {
1906            err.span_label(
1907                pat_field.ident.span,
1908                format!(
1909                    "{} `{}` does not have {} field{}",
1910                    kind_name,
1911                    tcx.def_path_str(variant.def_id),
1912                    t,
1913                    plural
1914                ),
1915            );
1916
1917            if let [(field_def, field)] = unmentioned_fields.as_slice()
1918                && self.is_field_suggestable(field_def, pat.hir_id, pat.span)
1919            {
1920                let suggested_name =
1921                    find_best_match_for_name(&[field.name], pat_field.ident.name, None);
1922                if let Some(suggested_name) = suggested_name {
1923                    err.span_suggestion(
1924                        pat_field.ident.span,
1925                        "a field with a similar name exists",
1926                        suggested_name,
1927                        Applicability::MaybeIncorrect,
1928                    );
1929
1930                    // When we have a tuple struct used with struct we don't want to suggest using
1931                    // the (valid) struct syntax with numeric field names. Instead we want to
1932                    // suggest the expected syntax. We infer that this is the case by parsing the
1933                    // `Ident` into an unsized integer. The suggestion will be emitted elsewhere in
1934                    // `smart_resolve_context_dependent_help`.
1935                    if suggested_name.to_ident_string().parse::<usize>().is_err() {
1936                        // We don't want to throw `E0027` in case we have thrown `E0026` for them.
1937                        unmentioned_fields.retain(|&(_, x)| x.name != suggested_name);
1938                    }
1939                } else if inexistent_fields.len() == 1 {
1940                    match pat_field.pat.kind {
1941                        PatKind::Expr(_)
1942                            if !self.may_coerce(
1943                                self.typeck_results.borrow().node_type(pat_field.pat.hir_id),
1944                                self.field_ty(field.span, field_def, args),
1945                            ) => {}
1946                        _ => {
1947                            err.span_suggestion_short(
1948                                pat_field.ident.span,
1949                                format!(
1950                                    "`{}` has a field named `{}`",
1951                                    tcx.def_path_str(variant.def_id),
1952                                    field.name,
1953                                ),
1954                                field.name,
1955                                Applicability::MaybeIncorrect,
1956                            );
1957                        }
1958                    }
1959                }
1960            }
1961        }
1962        if tcx.sess.teach(err.code.unwrap()) {
1963            err.note(
1964                "This error indicates that a struct pattern attempted to \
1965                 extract a nonexistent field from a struct. Struct fields \
1966                 are identified by the name used before the colon : so struct \
1967                 patterns should resemble the declaration of the struct type \
1968                 being matched.\n\n\
1969                 If you are using shorthand field patterns but want to refer \
1970                 to the struct field by a different name, you should rename \
1971                 it explicitly.",
1972            );
1973        }
1974        err
1975    }
1976
1977    fn error_tuple_variant_as_struct_pat(
1978        &self,
1979        pat: &Pat<'_>,
1980        fields: &'tcx [hir::PatField<'tcx>],
1981        variant: &ty::VariantDef,
1982    ) -> Result<(), ErrorGuaranteed> {
1983        if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) =
1984            (variant.ctor_kind(), &pat.kind)
1985        {
1986            let is_tuple_struct_match = !pattern_fields.is_empty()
1987                && pattern_fields.iter().map(|field| field.ident.name.as_str()).all(is_number);
1988            if is_tuple_struct_match {
1989                return Ok(());
1990            }
1991
1992            // we don't care to report errors for a struct if the struct itself is tainted
1993            variant.has_errors()?;
1994
1995            let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
1996            let mut err = struct_span_code_err!(
1997                self.dcx(),
1998                pat.span,
1999                E0769,
2000                "tuple variant `{}` written as struct variant",
2001                path
2002            );
2003            let (sugg, appl) = if fields.len() == variant.fields.len() {
2004                (
2005                    self.get_suggested_tuple_struct_pattern(fields, variant),
2006                    Applicability::MachineApplicable,
2007                )
2008            } else {
2009                (
2010                    variant.fields.iter().map(|_| "_").collect::<Vec<&str>>().join(", "),
2011                    Applicability::MaybeIncorrect,
2012                )
2013            };
2014            err.span_suggestion_verbose(
2015                qpath.span().shrink_to_hi().to(pat.span.shrink_to_hi()),
2016                "use the tuple variant pattern syntax instead",
2017                format!("({sugg})"),
2018                appl,
2019            );
2020            return Err(err.emit());
2021        }
2022        Ok(())
2023    }
2024
2025    fn get_suggested_tuple_struct_pattern(
2026        &self,
2027        fields: &[hir::PatField<'_>],
2028        variant: &VariantDef,
2029    ) -> String {
2030        let variant_field_idents =
2031            variant.fields.iter().map(|f| f.ident(self.tcx)).collect::<Vec<Ident>>();
2032        fields
2033            .iter()
2034            .map(|field| {
2035                match self.tcx.sess.source_map().span_to_snippet(field.pat.span) {
2036                    Ok(f) => {
2037                        // Field names are numbers, but numbers
2038                        // are not valid identifiers
2039                        if variant_field_idents.contains(&field.ident) {
2040                            String::from("_")
2041                        } else {
2042                            f
2043                        }
2044                    }
2045                    Err(_) => rustc_hir_pretty::pat_to_string(&self.tcx, field.pat),
2046                }
2047            })
2048            .collect::<Vec<String>>()
2049            .join(", ")
2050    }
2051
2052    /// Returns a diagnostic reporting a struct pattern which is missing an `..` due to
2053    /// inaccessible fields.
2054    ///
2055    /// ```text
2056    /// error: pattern requires `..` due to inaccessible fields
2057    ///   --> src/main.rs:10:9
2058    ///    |
2059    /// LL |     let foo::Foo {} = foo::Foo::default();
2060    ///    |         ^^^^^^^^^^^
2061    ///    |
2062    /// help: add a `..`
2063    ///    |
2064    /// LL |     let foo::Foo { .. } = foo::Foo::default();
2065    ///    |                  ^^^^^^
2066    /// ```
2067    fn error_no_accessible_fields(
2068        &self,
2069        pat: &Pat<'_>,
2070        fields: &'tcx [hir::PatField<'tcx>],
2071    ) -> Diag<'a> {
2072        let mut err = self
2073            .dcx()
2074            .struct_span_err(pat.span, "pattern requires `..` due to inaccessible fields");
2075
2076        if let Some(field) = fields.last() {
2077            err.span_suggestion_verbose(
2078                field.span.shrink_to_hi(),
2079                "ignore the inaccessible and unused fields",
2080                ", ..",
2081                Applicability::MachineApplicable,
2082            );
2083        } else {
2084            let qpath_span = if let PatKind::Struct(qpath, ..) = &pat.kind {
2085                qpath.span()
2086            } else {
2087                bug!("`error_no_accessible_fields` called on non-struct pattern");
2088            };
2089
2090            // Shrink the span to exclude the `foo:Foo` in `foo::Foo { }`.
2091            let span = pat.span.with_lo(qpath_span.shrink_to_hi().hi());
2092            err.span_suggestion_verbose(
2093                span,
2094                "ignore the inaccessible and unused fields",
2095                " { .. }",
2096                Applicability::MachineApplicable,
2097            );
2098        }
2099        err
2100    }
2101
2102    /// Report that a pattern for a `#[non_exhaustive]` struct marked with `non_exhaustive_omitted_patterns`
2103    /// is not exhaustive enough.
2104    ///
2105    /// Nb: the partner lint for enums lives in `compiler/rustc_mir_build/src/thir/pattern/usefulness.rs`.
2106    fn lint_non_exhaustive_omitted_patterns(
2107        &self,
2108        pat: &Pat<'_>,
2109        unmentioned_fields: &[(&ty::FieldDef, Ident)],
2110        ty: Ty<'tcx>,
2111    ) {
2112        fn joined_uncovered_patterns(witnesses: &[&Ident]) -> String {
2113            const LIMIT: usize = 3;
2114            match witnesses {
2115                [] => {
2116                    unreachable!(
2117                        "expected an uncovered pattern, otherwise why are we emitting an error?"
2118                    )
2119                }
2120                [witness] => format!("`{witness}`"),
2121                [head @ .., tail] if head.len() < LIMIT => {
2122                    let head: Vec<_> = head.iter().map(<_>::to_string).collect();
2123                    format!("`{}` and `{}`", head.join("`, `"), tail)
2124                }
2125                _ => {
2126                    let (head, tail) = witnesses.split_at(LIMIT);
2127                    let head: Vec<_> = head.iter().map(<_>::to_string).collect();
2128                    format!("`{}` and {} more", head.join("`, `"), tail.len())
2129                }
2130            }
2131        }
2132        let joined_patterns = joined_uncovered_patterns(
2133            &unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
2134        );
2135
2136        self.tcx.node_span_lint(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, |lint| {
2137            lint.primary_message("some fields are not explicitly listed");
2138            lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
2139            lint.help(
2140                "ensure that all fields are mentioned explicitly by adding the suggested fields",
2141            );
2142            lint.note(format!(
2143                "the pattern is of type `{ty}` and the `non_exhaustive_omitted_patterns` attribute was found",
2144            ));
2145        });
2146    }
2147
2148    /// Returns a diagnostic reporting a struct pattern which does not mention some fields.
2149    ///
2150    /// ```text
2151    /// error[E0027]: pattern does not mention field `bar`
2152    ///   --> src/main.rs:15:9
2153    ///    |
2154    /// LL |     let foo::Foo {} = foo::Foo::new();
2155    ///    |         ^^^^^^^^^^^ missing field `bar`
2156    /// ```
2157    fn error_unmentioned_fields(
2158        &self,
2159        pat: &Pat<'_>,
2160        unmentioned_fields: &[(&ty::FieldDef, Ident)],
2161        have_inaccessible_fields: bool,
2162        fields: &'tcx [hir::PatField<'tcx>],
2163    ) -> Diag<'a> {
2164        let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" };
2165        let field_names = if let [(_, field)] = unmentioned_fields {
2166            format!("field `{field}`{inaccessible}")
2167        } else {
2168            let fields = unmentioned_fields
2169                .iter()
2170                .map(|(_, name)| format!("`{name}`"))
2171                .collect::<Vec<String>>()
2172                .join(", ");
2173            format!("fields {fields}{inaccessible}")
2174        };
2175        let mut err = struct_span_code_err!(
2176            self.dcx(),
2177            pat.span,
2178            E0027,
2179            "pattern does not mention {}",
2180            field_names
2181        );
2182        err.span_label(pat.span, format!("missing {field_names}"));
2183        let len = unmentioned_fields.len();
2184        let (prefix, postfix, sp) = match fields {
2185            [] => match &pat.kind {
2186                PatKind::Struct(path, [], false) => {
2187                    (" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi()))
2188                }
2189                _ => return err,
2190            },
2191            [.., field] => {
2192                // Account for last field having a trailing comma or parse recovery at the tail of
2193                // the pattern to avoid invalid suggestion (#78511).
2194                let tail = field.span.shrink_to_hi().with_hi(pat.span.hi());
2195                match &pat.kind {
2196                    PatKind::Struct(..) => (", ", " }", tail),
2197                    _ => return err,
2198                }
2199            }
2200        };
2201        err.span_suggestion(
2202            sp,
2203            format!(
2204                "include the missing field{} in the pattern{}",
2205                pluralize!(len),
2206                if have_inaccessible_fields { " and ignore the inaccessible fields" } else { "" }
2207            ),
2208            format!(
2209                "{}{}{}{}",
2210                prefix,
2211                unmentioned_fields
2212                    .iter()
2213                    .map(|(_, name)| {
2214                        let field_name = name.to_string();
2215                        if is_number(&field_name) { format!("{field_name}: _") } else { field_name }
2216                    })
2217                    .collect::<Vec<_>>()
2218                    .join(", "),
2219                if have_inaccessible_fields { ", .." } else { "" },
2220                postfix,
2221            ),
2222            Applicability::MachineApplicable,
2223        );
2224        err.span_suggestion(
2225            sp,
2226            format!(
2227                "if you don't care about {these} missing field{s}, you can explicitly ignore {them}",
2228                these = pluralize!("this", len),
2229                s = pluralize!(len),
2230                them = if len == 1 { "it" } else { "them" },
2231            ),
2232            format!(
2233                "{}{}{}{}",
2234                prefix,
2235                unmentioned_fields
2236                    .iter()
2237                    .map(|(_, name)| {
2238                        let field_name = name.to_string();
2239                        format!("{field_name}: _")
2240                    })
2241                    .collect::<Vec<_>>()
2242                    .join(", "),
2243                if have_inaccessible_fields { ", .." } else { "" },
2244                postfix,
2245            ),
2246            Applicability::MachineApplicable,
2247        );
2248        err.span_suggestion(
2249            sp,
2250            "or always ignore missing fields here",
2251            format!("{prefix}..{postfix}"),
2252            Applicability::MachineApplicable,
2253        );
2254        err
2255    }
2256
2257    fn check_pat_box(
2258        &self,
2259        span: Span,
2260        inner: &'tcx Pat<'tcx>,
2261        expected: Ty<'tcx>,
2262        pat_info: PatInfo<'tcx>,
2263    ) -> Ty<'tcx> {
2264        let tcx = self.tcx;
2265        let (box_ty, inner_ty) = self
2266            .check_dereferenceable(span, expected, inner)
2267            .and_then(|()| {
2268                // Here, `demand::subtype` is good enough, but I don't
2269                // think any errors can be introduced by using `demand::eqtype`.
2270                let inner_ty = self.next_ty_var(inner.span);
2271                let box_ty = Ty::new_box(tcx, inner_ty);
2272                self.demand_eqtype_pat(span, expected, box_ty, &pat_info.top_info)?;
2273                Ok((box_ty, inner_ty))
2274            })
2275            .unwrap_or_else(|guar| {
2276                let err = Ty::new_error(tcx, guar);
2277                (err, err)
2278            });
2279        self.check_pat(inner, inner_ty, pat_info);
2280        box_ty
2281    }
2282
2283    fn check_pat_deref(
2284        &self,
2285        span: Span,
2286        inner: &'tcx Pat<'tcx>,
2287        expected: Ty<'tcx>,
2288        pat_info: PatInfo<'tcx>,
2289    ) -> Ty<'tcx> {
2290        let tcx = self.tcx;
2291        // Register a `DerefPure` bound, which is required by all `deref!()` pats.
2292        self.register_bound(
2293            expected,
2294            tcx.require_lang_item(hir::LangItem::DerefPure, Some(span)),
2295            self.misc(span),
2296        );
2297        // <expected as Deref>::Target
2298        let ty = Ty::new_projection(
2299            tcx,
2300            tcx.require_lang_item(hir::LangItem::DerefTarget, Some(span)),
2301            [expected],
2302        );
2303        let ty = self.normalize(span, ty);
2304        let ty = self.try_structurally_resolve_type(span, ty);
2305        self.check_pat(inner, ty, pat_info);
2306
2307        // Check if the pattern has any `ref mut` bindings, which would require
2308        // `DerefMut` to be emitted in MIR building instead of just `Deref`.
2309        // We do this *after* checking the inner pattern, since we want to make
2310        // sure to apply any match-ergonomics adjustments.
2311        if self.typeck_results.borrow().pat_has_ref_mut_binding(inner) {
2312            self.register_bound(
2313                expected,
2314                tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)),
2315                self.misc(span),
2316            );
2317        }
2318
2319        expected
2320    }
2321
2322    // Precondition: Pat is Ref(inner)
2323    fn check_pat_ref(
2324        &self,
2325        pat: &'tcx Pat<'tcx>,
2326        inner: &'tcx Pat<'tcx>,
2327        pat_mutbl: Mutability,
2328        mut expected: Ty<'tcx>,
2329        mut pat_info: PatInfo<'tcx>,
2330    ) -> Ty<'tcx> {
2331        let tcx = self.tcx;
2332
2333        let pat_prefix_span =
2334            inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end));
2335
2336        let ref_pat_matches_mut_ref = self.ref_pat_matches_mut_ref();
2337        if ref_pat_matches_mut_ref && pat_mutbl == Mutability::Not {
2338            // If `&` patterns can match against mutable reference types (RFC 3627, Rule 5), we need
2339            // to prevent subpatterns from binding with `ref mut`. Subpatterns of a shared reference
2340            // pattern should have read-only access to the scrutinee, and the borrow checker won't
2341            // catch it in this case.
2342            pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(pat_prefix_span);
2343        }
2344
2345        expected = self.try_structurally_resolve_type(pat.span, expected);
2346        // Determine whether we're consuming an inherited reference and resetting the default
2347        // binding mode, based on edition and enabled experimental features.
2348        if let ByRef::Yes(inh_mut) = pat_info.binding_mode {
2349            match self.ref_pat_matches_inherited_ref(pat.span.edition()) {
2350                InheritedRefMatchRule::EatOuter => {
2351                    // ref pattern attempts to consume inherited reference
2352                    if pat_mutbl > inh_mut {
2353                        // Tried to match inherited `ref` with `&mut`
2354                        // NB: This assumes that `&` patterns can match against mutable references
2355                        // (RFC 3627, Rule 5). If we implement a pattern typing ruleset with Rule 4E
2356                        // but not Rule 5, we'll need to check that here.
2357                        debug_assert!(ref_pat_matches_mut_ref);
2358                        self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
2359                    }
2360
2361                    pat_info.binding_mode = ByRef::No;
2362                    self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2363                    self.check_pat(inner, expected, pat_info);
2364                    return expected;
2365                }
2366                InheritedRefMatchRule::EatInner => {
2367                    if let ty::Ref(_, _, r_mutbl) = *expected.kind()
2368                        && pat_mutbl <= r_mutbl
2369                    {
2370                        // Match against the reference type; don't consume the inherited ref.
2371                        // NB: The check for compatible pattern and ref type mutability assumes that
2372                        // `&` patterns can match against mutable references (RFC 3627, Rule 5). If
2373                        // we implement a pattern typing ruleset with Rule 4 (including the fallback
2374                        // to matching the inherited ref when the inner ref can't match) but not
2375                        // Rule 5, we'll need to check that here.
2376                        debug_assert!(ref_pat_matches_mut_ref);
2377                        // NB: For RFC 3627's Rule 3, we limit the default binding mode's ref
2378                        // mutability to `pat_info.max_ref_mutbl`. If we implement a pattern typing
2379                        // ruleset with Rule 4 but not Rule 3, we'll need to check that here.
2380                        debug_assert!(self.downgrade_mut_inside_shared());
2381                        let mutbl_cap = cmp::min(r_mutbl, pat_info.max_ref_mutbl.as_mutbl());
2382                        pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(mutbl_cap);
2383                    } else {
2384                        // The reference pattern can't match against the expected type, so try
2385                        // matching against the inherited ref instead.
2386                        if pat_mutbl > inh_mut {
2387                            // We can't match an inherited shared reference with `&mut`.
2388                            // NB: This assumes that `&` patterns can match against mutable
2389                            // references (RFC 3627, Rule 5). If we implement a pattern typing
2390                            // ruleset with Rule 4 but not Rule 5, we'll need to check that here.
2391                            // FIXME(ref_pat_eat_one_layer_2024_structural): If we already tried
2392                            // matching the real reference, the error message should explain that
2393                            // falling back to the inherited reference didn't work. This should be
2394                            // the same error as the old-Edition version below.
2395                            debug_assert!(ref_pat_matches_mut_ref);
2396                            self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
2397                        }
2398
2399                        pat_info.binding_mode = ByRef::No;
2400                        self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2401                        self.check_pat(inner, expected, pat_info);
2402                        return expected;
2403                    }
2404                }
2405                InheritedRefMatchRule::EatBoth { consider_inherited_ref: true } => {
2406                    // Reset binding mode on old editions
2407                    pat_info.binding_mode = ByRef::No;
2408
2409                    if let ty::Ref(_, inner_ty, _) = *expected.kind() {
2410                        // Consume both the inherited and inner references.
2411                        if pat_mutbl.is_mut() && inh_mut.is_mut() {
2412                            // As a special case, a `&mut` reference pattern will be able to match
2413                            // against a reference type of any mutability if the inherited ref is
2414                            // mutable. Since this allows us to match against a shared reference
2415                            // type, we refer to this as "falling back" to matching the inherited
2416                            // reference, though we consume the real reference as well. We handle
2417                            // this here to avoid adding this case to the common logic below.
2418                            self.check_pat(inner, inner_ty, pat_info);
2419                            return expected;
2420                        } else {
2421                            // Otherwise, use the common logic below for matching the inner
2422                            // reference type.
2423                            // FIXME(ref_pat_eat_one_layer_2024_structural): If this results in a
2424                            // mutability mismatch, the error message should explain that falling
2425                            // back to the inherited reference didn't work. This should be the same
2426                            // error as the Edition 2024 version above.
2427                        }
2428                    } else {
2429                        // The expected type isn't a reference type, so only match against the
2430                        // inherited reference.
2431                        if pat_mutbl > inh_mut {
2432                            // We can't match a lone inherited shared reference with `&mut`.
2433                            self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
2434                        }
2435
2436                        self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2437                        self.check_pat(inner, expected, pat_info);
2438                        return expected;
2439                    }
2440                }
2441                InheritedRefMatchRule::EatBoth { consider_inherited_ref: false } => {
2442                    // Reset binding mode on stable Rust. This will be a type error below if
2443                    // `expected` is not a reference type.
2444                    pat_info.binding_mode = ByRef::No;
2445                    self.add_rust_2024_migration_desugared_pat(
2446                        pat_info.top_info.hir_id,
2447                        pat,
2448                        match pat_mutbl {
2449                            Mutability::Not => '&', // last char of `&`
2450                            Mutability::Mut => 't', // last char of `&mut`
2451                        },
2452                        inh_mut,
2453                    )
2454                }
2455            }
2456        }
2457
2458        let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
2459            Ok(()) => {
2460                // `demand::subtype` would be good enough, but using `eqtype` turns
2461                // out to be equally general. See (note_1) for details.
2462
2463                // Take region, inner-type from expected type if we can,
2464                // to avoid creating needless variables. This also helps with
2465                // the bad interactions of the given hack detailed in (note_1).
2466                debug!("check_pat_ref: expected={:?}", expected);
2467                match *expected.kind() {
2468                    ty::Ref(_, r_ty, r_mutbl)
2469                        if (ref_pat_matches_mut_ref && r_mutbl >= pat_mutbl)
2470                            || r_mutbl == pat_mutbl =>
2471                    {
2472                        if r_mutbl == Mutability::Not {
2473                            pat_info.max_ref_mutbl = MutblCap::Not;
2474                        }
2475
2476                        (expected, r_ty)
2477                    }
2478
2479                    _ => {
2480                        let inner_ty = self.next_ty_var(inner.span);
2481                        let ref_ty = self.new_ref_ty(pat.span, pat_mutbl, inner_ty);
2482                        debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
2483                        let err = self.demand_eqtype_pat_diag(
2484                            pat.span,
2485                            expected,
2486                            ref_ty,
2487                            &pat_info.top_info,
2488                        );
2489
2490                        // Look for a case like `fn foo(&foo: u32)` and suggest
2491                        // `fn foo(foo: &u32)`
2492                        if let Err(mut err) = err {
2493                            self.borrow_pat_suggestion(&mut err, pat);
2494                            err.emit();
2495                        }
2496                        (ref_ty, inner_ty)
2497                    }
2498                }
2499            }
2500            Err(guar) => {
2501                let err = Ty::new_error(tcx, guar);
2502                (err, err)
2503            }
2504        };
2505
2506        self.check_pat(inner, inner_ty, pat_info);
2507        ref_ty
2508    }
2509
2510    /// Create a reference type with a fresh region variable.
2511    fn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'tcx>) -> Ty<'tcx> {
2512        let region = self.next_region_var(infer::PatternRegion(span));
2513        Ty::new_ref(self.tcx, region, ty, mutbl)
2514    }
2515
2516    fn error_inherited_ref_mutability_mismatch(
2517        &self,
2518        pat: &'tcx Pat<'tcx>,
2519        pat_prefix_span: Option<Span>,
2520    ) -> ErrorGuaranteed {
2521        let err_msg = "mismatched types";
2522        let err = if let Some(span) = pat_prefix_span {
2523            let mut err = self.dcx().struct_span_err(span, err_msg);
2524            err.code(E0308);
2525            err.note("cannot match inherited `&` with `&mut` pattern");
2526            err.span_suggestion_verbose(
2527                span,
2528                "replace this `&mut` pattern with `&`",
2529                "&",
2530                Applicability::MachineApplicable,
2531            );
2532            err
2533        } else {
2534            self.dcx().struct_span_err(pat.span, err_msg)
2535        };
2536        err.emit()
2537    }
2538
2539    fn try_resolve_slice_ty_to_array_ty(
2540        &self,
2541        before: &'tcx [Pat<'tcx>],
2542        slice: Option<&'tcx Pat<'tcx>>,
2543        span: Span,
2544    ) -> Option<Ty<'tcx>> {
2545        if slice.is_some() {
2546            return None;
2547        }
2548
2549        let tcx = self.tcx;
2550        let len = before.len();
2551        let inner_ty = self.next_ty_var(span);
2552
2553        Some(Ty::new_array(tcx, inner_ty, len.try_into().unwrap()))
2554    }
2555
2556    /// Used to determines whether we can infer the expected type in the slice pattern to be of type array.
2557    /// This is only possible if we're in an irrefutable pattern. If we were to allow this in refutable
2558    /// patterns we wouldn't e.g. report ambiguity in the following situation:
2559    ///
2560    /// ```ignore(rust)
2561    /// struct Zeroes;
2562    ///    const ARR: [usize; 2] = [0; 2];
2563    ///    const ARR2: [usize; 2] = [2; 2];
2564    ///
2565    ///    impl Into<&'static [usize; 2]> for Zeroes {
2566    ///        fn into(self) -> &'static [usize; 2] {
2567    ///            &ARR
2568    ///        }
2569    ///    }
2570    ///
2571    ///    impl Into<&'static [usize]> for Zeroes {
2572    ///        fn into(self) -> &'static [usize] {
2573    ///            &ARR2
2574    ///        }
2575    ///    }
2576    ///
2577    ///    fn main() {
2578    ///        let &[a, b]: &[usize] = Zeroes.into() else {
2579    ///           ..
2580    ///        };
2581    ///    }
2582    /// ```
2583    ///
2584    /// If we're in an irrefutable pattern we prefer the array impl candidate given that
2585    /// the slice impl candidate would be rejected anyway (if no ambiguity existed).
2586    fn pat_is_irrefutable(&self, decl_origin: Option<DeclOrigin<'_>>) -> bool {
2587        match decl_origin {
2588            Some(DeclOrigin::LocalDecl { els: None }) => true,
2589            Some(DeclOrigin::LocalDecl { els: Some(_) } | DeclOrigin::LetExpr) | None => false,
2590        }
2591    }
2592
2593    /// Type check a slice pattern.
2594    ///
2595    /// Syntactically, these look like `[pat_0, ..., pat_n]`.
2596    /// Semantically, we are type checking a pattern with structure:
2597    /// ```ignore (not-rust)
2598    /// [before_0, ..., before_n, (slice, after_0, ... after_n)?]
2599    /// ```
2600    /// The type of `slice`, if it is present, depends on the `expected` type.
2601    /// If `slice` is missing, then so is `after_i`.
2602    /// If `slice` is present, it can still represent 0 elements.
2603    fn check_pat_slice(
2604        &self,
2605        span: Span,
2606        before: &'tcx [Pat<'tcx>],
2607        slice: Option<&'tcx Pat<'tcx>>,
2608        after: &'tcx [Pat<'tcx>],
2609        expected: Ty<'tcx>,
2610        pat_info: PatInfo<'tcx>,
2611    ) -> Ty<'tcx> {
2612        let expected = self.try_structurally_resolve_type(span, expected);
2613
2614        // If the pattern is irrefutable and `expected` is an infer ty, we try to equate it
2615        // to an array if the given pattern allows it. See issue #76342
2616        if self.pat_is_irrefutable(pat_info.decl_origin) && expected.is_ty_var() {
2617            if let Some(resolved_arr_ty) =
2618                self.try_resolve_slice_ty_to_array_ty(before, slice, span)
2619            {
2620                debug!(?resolved_arr_ty);
2621                let _ = self.demand_eqtype(span, expected, resolved_arr_ty);
2622            }
2623        }
2624
2625        let expected = self.structurally_resolve_type(span, expected);
2626        debug!(?expected);
2627
2628        let (element_ty, opt_slice_ty, inferred) = match *expected.kind() {
2629            // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
2630            ty::Array(element_ty, len) => {
2631                let min = before.len() as u64 + after.len() as u64;
2632                let (opt_slice_ty, expected) =
2633                    self.check_array_pat_len(span, element_ty, expected, slice, len, min);
2634                // `opt_slice_ty.is_none()` => `slice.is_none()`.
2635                // Note, though, that opt_slice_ty could be `Some(error_ty)`.
2636                assert!(opt_slice_ty.is_some() || slice.is_none());
2637                (element_ty, opt_slice_ty, expected)
2638            }
2639            ty::Slice(element_ty) => (element_ty, Some(expected), expected),
2640            // The expected type must be an array or slice, but was neither, so error.
2641            _ => {
2642                let guar = expected.error_reported().err().unwrap_or_else(|| {
2643                    self.error_expected_array_or_slice(span, expected, pat_info)
2644                });
2645                let err = Ty::new_error(self.tcx, guar);
2646                (err, Some(err), err)
2647            }
2648        };
2649
2650        // Type check all the patterns before `slice`.
2651        for elt in before {
2652            self.check_pat(elt, element_ty, pat_info);
2653        }
2654        // Type check the `slice`, if present, against its expected type.
2655        if let Some(slice) = slice {
2656            self.check_pat(slice, opt_slice_ty.unwrap(), pat_info);
2657        }
2658        // Type check the elements after `slice`, if present.
2659        for elt in after {
2660            self.check_pat(elt, element_ty, pat_info);
2661        }
2662        inferred
2663    }
2664
2665    /// Type check the length of an array pattern.
2666    ///
2667    /// Returns both the type of the variable length pattern (or `None`), and the potentially
2668    /// inferred array type. We only return `None` for the slice type if `slice.is_none()`.
2669    fn check_array_pat_len(
2670        &self,
2671        span: Span,
2672        element_ty: Ty<'tcx>,
2673        arr_ty: Ty<'tcx>,
2674        slice: Option<&'tcx Pat<'tcx>>,
2675        len: ty::Const<'tcx>,
2676        min_len: u64,
2677    ) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
2678        let len = self.try_structurally_resolve_const(span, len).try_to_target_usize(self.tcx);
2679
2680        let guar = if let Some(len) = len {
2681            // Now we know the length...
2682            if slice.is_none() {
2683                // ...and since there is no variable-length pattern,
2684                // we require an exact match between the number of elements
2685                // in the array pattern and as provided by the matched type.
2686                if min_len == len {
2687                    return (None, arr_ty);
2688                }
2689
2690                self.error_scrutinee_inconsistent_length(span, min_len, len)
2691            } else if let Some(pat_len) = len.checked_sub(min_len) {
2692                // The variable-length pattern was there,
2693                // so it has an array type with the remaining elements left as its size...
2694                return (Some(Ty::new_array(self.tcx, element_ty, pat_len)), arr_ty);
2695            } else {
2696                // ...however, in this case, there were no remaining elements.
2697                // That is, the slice pattern requires more than the array type offers.
2698                self.error_scrutinee_with_rest_inconsistent_length(span, min_len, len)
2699            }
2700        } else if slice.is_none() {
2701            // We have a pattern with a fixed length,
2702            // which we can use to infer the length of the array.
2703            let updated_arr_ty = Ty::new_array(self.tcx, element_ty, min_len);
2704            self.demand_eqtype(span, updated_arr_ty, arr_ty);
2705            return (None, updated_arr_ty);
2706        } else {
2707            // We have a variable-length pattern and don't know the array length.
2708            // This happens if we have e.g.,
2709            // `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
2710            self.error_scrutinee_unfixed_length(span)
2711        };
2712
2713        // If we get here, we must have emitted an error.
2714        (Some(Ty::new_error(self.tcx, guar)), arr_ty)
2715    }
2716
2717    fn error_scrutinee_inconsistent_length(
2718        &self,
2719        span: Span,
2720        min_len: u64,
2721        size: u64,
2722    ) -> ErrorGuaranteed {
2723        struct_span_code_err!(
2724            self.dcx(),
2725            span,
2726            E0527,
2727            "pattern requires {} element{} but array has {}",
2728            min_len,
2729            pluralize!(min_len),
2730            size,
2731        )
2732        .with_span_label(span, format!("expected {} element{}", size, pluralize!(size)))
2733        .emit()
2734    }
2735
2736    fn error_scrutinee_with_rest_inconsistent_length(
2737        &self,
2738        span: Span,
2739        min_len: u64,
2740        size: u64,
2741    ) -> ErrorGuaranteed {
2742        struct_span_code_err!(
2743            self.dcx(),
2744            span,
2745            E0528,
2746            "pattern requires at least {} element{} but array has {}",
2747            min_len,
2748            pluralize!(min_len),
2749            size,
2750        )
2751        .with_span_label(
2752            span,
2753            format!("pattern cannot match array of {} element{}", size, pluralize!(size),),
2754        )
2755        .emit()
2756    }
2757
2758    fn error_scrutinee_unfixed_length(&self, span: Span) -> ErrorGuaranteed {
2759        struct_span_code_err!(
2760            self.dcx(),
2761            span,
2762            E0730,
2763            "cannot pattern-match on an array without a fixed length",
2764        )
2765        .emit()
2766    }
2767
2768    fn error_expected_array_or_slice(
2769        &self,
2770        span: Span,
2771        expected_ty: Ty<'tcx>,
2772        pat_info: PatInfo<'tcx>,
2773    ) -> ErrorGuaranteed {
2774        let PatInfo { top_info: ti, current_depth, .. } = pat_info;
2775
2776        let mut slice_pat_semantics = false;
2777        let mut as_deref = None;
2778        let mut slicing = None;
2779        if let ty::Ref(_, ty, _) = expected_ty.kind()
2780            && let ty::Array(..) | ty::Slice(..) = ty.kind()
2781        {
2782            slice_pat_semantics = true;
2783        } else if self
2784            .autoderef(span, expected_ty)
2785            .silence_errors()
2786            .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
2787            && let Some(span) = ti.span
2788            && let Some(_) = ti.origin_expr
2789        {
2790            let resolved_ty = self.resolve_vars_if_possible(ti.expected);
2791            let (is_slice_or_array_or_vector, resolved_ty) =
2792                self.is_slice_or_array_or_vector(resolved_ty);
2793            match resolved_ty.kind() {
2794                ty::Adt(adt_def, _)
2795                    if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
2796                        || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
2797                {
2798                    // Slicing won't work here, but `.as_deref()` might (issue #91328).
2799                    as_deref = Some(errors::AsDerefSuggestion { span: span.shrink_to_hi() });
2800                }
2801                _ => (),
2802            }
2803
2804            let is_top_level = current_depth <= 1;
2805            if is_slice_or_array_or_vector && is_top_level {
2806                slicing = Some(errors::SlicingSuggestion { span: span.shrink_to_hi() });
2807            }
2808        }
2809        self.dcx().emit_err(errors::ExpectedArrayOrSlice {
2810            span,
2811            ty: expected_ty,
2812            slice_pat_semantics,
2813            as_deref,
2814            slicing,
2815        })
2816    }
2817
2818    fn is_slice_or_array_or_vector(&self, ty: Ty<'tcx>) -> (bool, Ty<'tcx>) {
2819        match ty.kind() {
2820            ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did()) => {
2821                (true, ty)
2822            }
2823            ty::Ref(_, ty, _) => self.is_slice_or_array_or_vector(*ty),
2824            ty::Slice(..) | ty::Array(..) => (true, ty),
2825            _ => (false, ty),
2826        }
2827    }
2828
2829    /// Record a pattern that's invalid under Rust 2024 match ergonomics, along with a problematic
2830    /// span, so that the pattern migration lint can desugar it during THIR construction.
2831    fn add_rust_2024_migration_desugared_pat(
2832        &self,
2833        pat_id: HirId,
2834        subpat: &'tcx Pat<'tcx>,
2835        final_char: char,
2836        def_br_mutbl: Mutability,
2837    ) {
2838        // Try to trim the span we're labeling to just the `&` or binding mode that's an issue.
2839        let from_expansion = subpat.span.from_expansion();
2840        let trimmed_span = if from_expansion {
2841            // If the subpattern is from an expansion, highlight the whole macro call instead.
2842            subpat.span
2843        } else {
2844            let trimmed = self.tcx.sess.source_map().span_through_char(subpat.span, final_char);
2845            // The edition of the trimmed span should be the same as `subpat.span`; this will be a
2846            // a hard error if the subpattern is of edition >= 2024. We set it manually to be sure:
2847            trimmed.with_ctxt(subpat.span.ctxt())
2848        };
2849
2850        let mut typeck_results = self.typeck_results.borrow_mut();
2851        let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
2852        // FIXME(ref_pat_eat_one_layer_2024): The migration diagnostic doesn't know how to track the
2853        // default binding mode in the presence of Rule 3 or Rule 5. As a consequence, the labels it
2854        // gives for default binding modes are wrong, as well as suggestions based on the default
2855        // binding mode. This keeps it from making those suggestions, as doing so could panic.
2856        let info = table.entry(pat_id).or_insert_with(|| ty::Rust2024IncompatiblePatInfo {
2857            primary_labels: Vec::new(),
2858            bad_modifiers: false,
2859            bad_ref_pats: false,
2860            suggest_eliding_modes: !self.tcx.features().ref_pat_eat_one_layer_2024()
2861                && !self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
2862        });
2863
2864        let pat_kind = if let PatKind::Binding(user_bind_annot, _, _, _) = subpat.kind {
2865            info.bad_modifiers = true;
2866            // If the user-provided binding modifier doesn't match the default binding mode, we'll
2867            // need to suggest reference patterns, which can affect other bindings.
2868            // For simplicity, we opt to suggest making the pattern fully explicit.
2869            info.suggest_eliding_modes &=
2870                user_bind_annot == BindingMode(ByRef::Yes(def_br_mutbl), Mutability::Not);
2871            "binding modifier"
2872        } else {
2873            info.bad_ref_pats = true;
2874            // For simplicity, we don't try to suggest eliding reference patterns. Thus, we'll
2875            // suggest adding them instead, which can affect the types assigned to bindings.
2876            // As such, we opt to suggest making the pattern fully explicit.
2877            info.suggest_eliding_modes = false;
2878            "reference pattern"
2879        };
2880        // Only provide a detailed label if the problematic subpattern isn't from an expansion.
2881        // In the case that it's from a macro, we'll add a more detailed note in the emitter.
2882        let primary_label = if from_expansion {
2883            // We can't suggest eliding modifiers within expansions.
2884            info.suggest_eliding_modes = false;
2885            // NB: This wording assumes the only expansions that can produce problematic reference
2886            // patterns and bindings are macros. If a desugaring or AST pass is added that can do
2887            // so, we may want to inspect the span's source callee or macro backtrace.
2888            "occurs within macro expansion".to_owned()
2889        } else {
2890            let dbm_str = match def_br_mutbl {
2891                Mutability::Not => "ref",
2892                Mutability::Mut => "ref mut",
2893            };
2894            format!("{pat_kind} not allowed under `{dbm_str}` default binding mode")
2895        };
2896        info.primary_labels.push((trimmed_span, primary_label));
2897    }
2898}