use std::ops::Bound;

use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_ast::token::NtPatKind::*;
use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token};
use rustc_ast::util::parser::ExprPrecedence;
use rustc_ast::visit::{self, Visitor};
use rustc_ast::{
    self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, Guard, LocalKind, MacCall,
    Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt,
    StmtKind, Ty,
};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey};
use rustc_span::{BytePos, ErrorGuaranteed, Ident, Span, Spanned, kw, respan, sym};
use thin_vec::{ThinVec, thin_vec};

use super::{ForceCollect, Parser, PathStyle, Restrictions, Trailing, UsePreAttrPos};
use crate::diagnostics::{
    self, AmbiguousRangePattern, AtDotDotInStructPattern, AtInStructPattern,
    DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, DotDotDotRestPattern,
    EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, ExpectedCommaAfterPatternField,
    ExprParenthesesNeeded, GenericArgsInPatRequireTurbofishSyntax, InclusiveRangeExtraEquals,
    InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern, ParenRangeSuggestion,
    PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder,
    TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed,
    TrailingVertSuggestion, UnexpectedExpressionInPattern, UnexpectedExpressionInPatternSugg,
    UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
    UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens,
};
use crate::parser::expr::{DestructuredFloat, could_be_unclosed_char_literal};
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};

#[derive(PartialEq, Copy, Clone)]
pub enum Expected {
    ParameterName,
    ArgumentName,
    Identifier,
    BindingPattern,
}

impl Expected {
    // FIXME(#100717): migrate users of this to proper localization
    fn to_string_or_fallback(expected: Option<Expected>) -> &'static str {
        match expected {
            Some(Expected::ParameterName) => "parameter name",
            Some(Expected::ArgumentName) => "argument name",
            Some(Expected::Identifier) => "identifier",
            Some(Expected::BindingPattern) => "binding pattern",
            None => "pattern",
        }
    }
}

const WHILE_PARSING_OR_MSG: &str = "while parsing this or-pattern starting here";

/// Whether or not to recover a `,` when parsing or-patterns.
#[derive(PartialEq, Copy, Clone)]
pub enum RecoverComma {
    Yes,
    No,
}

/// Whether or not to recover a `:` when parsing patterns that were meant to be paths.
#[derive(PartialEq, Copy, Clone)]
pub enum RecoverColon {
    Yes,
    No,
}

/// Whether or not to recover a `a, b` when parsing patterns as `(a, b)` or that *and* `a | b`.
#[derive(PartialEq, Copy, Clone)]
pub enum CommaRecoveryMode {
    LikelyTuple,
    EitherTupleOrPipe,
}

/// The result of `eat_or_separator`. We want to distinguish which case we are in to avoid
/// emitting duplicate diagnostics.
#[derive(Debug, Clone, Copy)]
enum EatOrResult {
    /// We recovered from a trailing vert.
    TrailingVert,
    /// We ate an `|` (or `||` and recovered).
    AteOr,
    /// We did not eat anything (i.e. the current token is not `|` or `||`).
    None,
}

/// The syntax location of a given pattern. Used for diagnostics.
#[derive(Clone, Copy)]
pub enum PatternLocation {
    LetBinding,
    FunctionParameter,
}

impl<'a> Parser<'a> {
    /// Parses a pattern.
    ///
    /// Corresponds to `Pattern` in RFC 3637 and admits guard patterns at the top level.
    /// Used when parsing patterns in all cases where neither `PatternNoTopGuard` nor
    /// `PatternNoTopAlt` (see below) are used.
    pub fn parse_pat_allow_top_guard(
        &mut self,
        expected: Option<Expected>,
        rc: RecoverComma,
        ra: RecoverColon,
        rt: CommaRecoveryMode,
    ) -> PResult<'a, Pat> {
        let pat = self.parse_pat_no_top_guard(expected, rc, ra, rt)?;

        if self.eat_keyword(exp!(If)) {
            let guard = if let Some(guard) = self.eat_metavar_guard() {
                guard
            } else {
                let leading_if_span = self.prev_token.span;
                let cond = self.parse_expr()?;
                let cond_span = cond.span;
                Box::new(Guard { cond: *cond, span_with_leading_if: leading_if_span.to(cond_span) })
            };

            // Feature-gate guard patterns
            self.psess.gated_spans.gate(sym::guard_patterns, guard.span());
            let span = pat.span.to(guard.span());
            Ok(self.mk_pat(span, PatKind::Guard(Box::new(pat), guard)))
        } else {
            Ok(pat)
        }
    }

    /// Parses a pattern.
    ///
    /// Corresponds to `PatternNoTopAlt` in RFC 3637 and does not admit or-patterns
    /// or guard patterns at the top level. Used when parsing the parameters of lambda
    /// expressions, functions, function pointers, and `pat_param` macro fragments.
    pub fn parse_pat_no_top_alt(
        &mut self,
        expected: Option<Expected>,
        syntax_loc: Option<PatternLocation>,
    ) -> PResult<'a, Pat> {
        self.parse_pat_with_range_pat(true, expected, syntax_loc)
    }

    /// Parses a pattern.
    ///
    /// Corresponds to `PatternNoTopGuard` in RFC 3637 and allows or-patterns, but not
    /// guard patterns, at the top level. Used for parsing patterns in `pat` fragments (until
    /// the next edition) and `let`, `if let`, and `while let` expressions.
    ///
    /// Note that after the FCP in <https://github.com/rust-lang/rust/issues/81415>,
    /// a leading vert is allowed in nested or-patterns, too. This allows us to
    /// simplify the grammar somewhat.
    pub fn parse_pat_no_top_guard(
        &mut self,
        expected: Option<Expected>,
        rc: RecoverComma,
        ra: RecoverColon,
        rt: CommaRecoveryMode,
    ) -> PResult<'a, Pat> {
        self.parse_pat_no_top_guard_inner(expected, rc, ra, rt, None).map(|(pat, _)| pat)
    }

    /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
    /// recovered).
    fn parse_pat_no_top_guard_inner(
        &mut self,
        expected: Option<Expected>,
        rc: RecoverComma,
        ra: RecoverColon,
        rt: CommaRecoveryMode,
        syntax_loc: Option<PatternLocation>,
    ) -> PResult<'a, (Pat, bool)> {
        // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
        // suggestions (which bothers rustfix).
        //
        // Allow a '|' before the pats (RFCs 1925, 2530, and 2535).
        let (leading_vert_span, mut trailing_vert) = match self.eat_or_separator(None) {
            EatOrResult::AteOr => (Some(self.prev_token.span), false),
            EatOrResult::TrailingVert => (None, true),
            EatOrResult::None => (None, false),
        };

        // Parse the first pattern (`p_0`).
        let mut first_pat = match self.parse_pat_no_top_alt(expected, syntax_loc) {
            Ok(pat) => pat,
            Err(err)
                if self.token.is_reserved_ident()
                    && !self.token.is_keyword(kw::In)
                    && !self.token.is_keyword(kw::If) =>
            {
                err.emit();
                self.bump();
                self.mk_pat(self.token.span, PatKind::Wild)
            }
            Err(err) => return Err(err),
        };
        if rc == RecoverComma::Yes && !first_pat.could_be_never_pattern() {
            self.maybe_recover_unexpected_comma(first_pat.span, rt)?;
        }

        // If the next token is not a `|`,
        // this is not an or-pattern and we should exit here.
        if !self.check(exp!(Or)) && self.token != token::OrOr {
            // If we parsed a leading `|` which should be gated,
            // then we should really gate the leading `|`.
            // This complicated procedure is done purely for diagnostics UX.

            // Check if the user wrote `foo:bar` instead of `foo::bar`.
            if ra == RecoverColon::Yes && token::Colon == self.token.kind {
                first_pat = self.recover_colon_colon_in_pat_typo(first_pat, expected);
            }

            if let Some(leading_vert_span) = leading_vert_span {
                // If there was a leading vert, treat this as an or-pattern. This improves
                // diagnostics.
                let span = leading_vert_span.to(self.prev_token.span);
                return Ok((self.mk_pat(span, PatKind::Or(thin_vec![first_pat])), trailing_vert));
            }

            return Ok((first_pat, trailing_vert));
        }

        // Parse the patterns `p_1 | ... | p_n` where `n > 0`.
        let lo = leading_vert_span.unwrap_or(first_pat.span);
        let mut pats = thin_vec![first_pat];
        loop {
            match self.eat_or_separator(Some(lo)) {
                EatOrResult::AteOr => {}
                EatOrResult::None => break,
                EatOrResult::TrailingVert => {
                    trailing_vert = true;
                    break;
                }
            }
            let pat = self.parse_pat_no_top_alt(expected, syntax_loc).map_err(|mut err| {
                err.span_label(lo, WHILE_PARSING_OR_MSG);
                err
            })?;
            if rc == RecoverComma::Yes && !pat.could_be_never_pattern() {
                self.maybe_recover_unexpected_comma(pat.span, rt)?;
            }
            pats.push(pat);
        }
        let or_pattern_span = lo.to(self.prev_token.span);

        Ok((self.mk_pat(or_pattern_span, PatKind::Or(pats)), trailing_vert))
    }

    /// Parse a pattern and (maybe) a `Colon` in positions where a pattern may be followed by a
    /// type annotation (e.g. for `let` bindings or `fn` params).
    ///
    /// Generally, this corresponds to `pat_no_top_alt` followed by an optional `Colon`. It will
    /// eat the `Colon` token if one is present.
    ///
    /// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false`
    /// otherwise).
    pub(super) fn parse_pat_before_ty(
        &mut self,
        expected: Option<Expected>,
        rc: RecoverComma,
        syntax_loc: PatternLocation,
    ) -> PResult<'a, (Box<Pat>, bool)> {
        // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level
        // or-patterns so that we can detect when a user tries to use it. This allows us to print a
        // better error message.
        let (pat, trailing_vert) = self.parse_pat_no_top_guard_inner(
            expected,
            rc,
            RecoverColon::No,
            CommaRecoveryMode::LikelyTuple,
            Some(syntax_loc),
        )?;
        let pat = Box::new(pat);
        let colon = self.eat(exp!(Colon));

        if let PatKind::Or(pats) = &pat.kind {
            let span = pat.span;
            let sub = if let [_] = &pats[..] {
                let span = span.with_hi(span.lo() + BytePos(1));
                Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span })
            } else {
                Some(TopLevelOrPatternNotAllowedSugg::WrapInParens {
                    span,
                    suggestion: WrapInParens { lo: span.shrink_to_lo(), hi: span.shrink_to_hi() },
                })
            };

            let err = self.dcx().create_err(match syntax_loc {
                PatternLocation::LetBinding => {
                    TopLevelOrPatternNotAllowed::LetBinding { span, sub }
                }
                PatternLocation::FunctionParameter => {
                    TopLevelOrPatternNotAllowed::FunctionParameter { span, sub }
                }
            });
            if trailing_vert {
                err.delay_as_bug();
            } else {
                err.emit();
            }
        }

        Ok((pat, colon))
    }

    /// Parse the pattern for a function or function pointer parameter, followed by a colon.
    ///
    /// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false`
    /// otherwise).
    pub(super) fn parse_fn_param_pat_colon(&mut self) -> PResult<'a, (Box<Pat>, bool)> {
        // In order to get good UX, we first recover in the case of a leading vert for an illegal
        // top-level or-pat. Normally, this means recovering both `|` and `||`, but in this case,
        // a leading `||` probably doesn't indicate an or-pattern attempt, so we handle that
        // separately.
        if let token::OrOr = self.token.kind {
            self.dcx().emit_err(UnexpectedVertVertBeforeFunctionParam { span: self.token.span });
            self.bump();
        }

        self.parse_pat_before_ty(
            Some(Expected::ParameterName),
            RecoverComma::No,
            PatternLocation::FunctionParameter,
        )
    }

    /// Eat the or-pattern `|` separator.
    /// If instead a `||` token is encountered, recover and pretend we parsed `|`.
    fn eat_or_separator(&mut self, lo: Option<Span>) -> EatOrResult {
        if self.recover_trailing_vert(lo) {
            EatOrResult::TrailingVert
        } else if self.token.kind == token::OrOr {
            // Found `||`; Recover and pretend we parsed `|`.
            self.dcx().emit_err(UnexpectedVertVertInPattern { span: self.token.span, start: lo });
            self.bump();
            EatOrResult::AteOr
        } else if self.eat(exp!(Or)) {
            EatOrResult::AteOr
        } else {
            EatOrResult::None
        }
    }

    /// Recover if `|` or `||` is the current token and we have one of the
    /// tokens `=>`, `if`, `=`, `:`, `;`, `,`, `]`, `)`, or `}` ahead of us.
    ///
    /// These tokens all indicate that we reached the end of the or-pattern
    /// list and can now reliably say that the `|` was an illegal trailing vert.
    /// Note that there are more tokens such as `@` for which we know that the `|`
    /// is an illegal parse. However, the user's intent is less clear in that case.
    fn recover_trailing_vert(&mut self, lo: Option<Span>) -> bool {
        let is_end_ahead = self.look_ahead(1, |token| {
            matches!(
                &token.uninterpolate().kind,
                token::FatArrow // e.g. `a | => 0,`.
                | token::Ident(kw::If, token::IdentIsRaw::No) // e.g. `a | if expr`.
                | token::Eq // e.g. `let a | = 0`.
                | token::Semi // e.g. `let a |;`.
                | token::Colon // e.g. `let a | :`.
                | token::Comma // e.g. `let (a |,)`.
                | token::CloseBracket // e.g. `let [a | ]`.
                | token::CloseParen // e.g. `let (a | )`.
                | token::CloseBrace // e.g. `let A { f: a | }`.
            )
        });
        match (is_end_ahead, &self.token.kind) {
            (true, token::Or | token::OrOr) => {
                // A `|` or possibly `||` token shouldn't be here. Ban it.
                let token = pprust::token_to_string(&self.token);
                self.dcx().emit_err(TrailingVertNotAllowed {
                    span: self.token.span,
                    start: lo,
                    suggestion: TrailingVertSuggestion {
                        span: self.prev_token.span.shrink_to_hi().with_hi(self.token.span.hi()),
                        token: token.clone(),
                    },
                    token,
                    note_double_vert: self.token.kind == token::OrOr,
                });
                self.bump();
                true
            }
            _ => false,
        }
    }

    /// Ensures that the last parsed pattern (or pattern range bound) is not followed by an expression.
    ///
    /// `is_end_bound` indicates whether the last parsed thing was the end bound of a range pattern (see [`parse_pat_range_end`](Self::parse_pat_range_end))
    /// in order to say "expected a pattern range bound" instead of "expected a pattern";
    /// ```text
    /// 0..=1 + 2
    ///     ^^^^^
    /// ```
    /// Only the end bound is spanned in this case, and this function has no idea if there was a `..=` before `pat_span`, hence the parameter.
    ///
    /// This function returns `Some` if a trailing expression was recovered, and said expression's span.
    #[must_use = "the pattern must be discarded as `PatKind::Err` if this function returns Some"]
    fn maybe_recover_trailing_expr(
        &mut self,
        pat_span: Span,
        is_end_bound: bool,
    ) -> Option<(ErrorGuaranteed, Span)> {
        if self.prev_token.is_keyword(kw::Underscore) || !self.may_recover() {
            // Don't recover anything after an `_` or if recovery is disabled.
            return None;
        }

        // Returns `true` iff `token` is an unsuffixed integer.
        let is_one_tuple_index = |_: &Self, token: &Token| -> bool {
            use token::{Lit, LitKind};

            matches!(
                token.kind,
                token::Literal(Lit { kind: LitKind::Integer, symbol: _, suffix: None })
            )
        };

        // Returns `true` iff `token` is an unsuffixed `x.y` float.
        let is_two_tuple_indexes = |this: &Self, token: &Token| -> bool {
            use token::{Lit, LitKind};

            if let token::Literal(Lit { kind: LitKind::Float, symbol, suffix: None }) = token.kind
                && let DestructuredFloat::MiddleDot(..) = this.break_up_float(symbol, token.span)
            {
                true
            } else {
                false
            }
        };

        // Check for `.hello` or `.0`.
        let has_dot_expr = self.check_noexpect(&token::Dot) // `.`
            && self.look_ahead(1, |tok| {
                tok.is_ident() // `hello`
                || is_one_tuple_index(&self, &tok) // `0`
                || is_two_tuple_indexes(&self, &tok) // `0.0`
            });

        // Check for operators.
        // `|` is excluded as it is used in pattern alternatives and lambdas,
        // `?` is included for error propagation,
        // `[` is included for indexing operations,
        // `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`),
        // `as` is included for type casts
        let has_trailing_operator = matches!(
                self.token.kind,
                token::Plus | token::Minus | token::Star | token::Slash | token::Percent
                | token::Caret | token::And | token::Shl | token::Shr // excludes `Or`
            )
            || self.token == token::Question
            || (self.token == token::OpenBracket
                && self.look_ahead(1, |t| *t != token::CloseBracket)) // excludes `[]`
            || self.token.is_keyword(kw::As);

        if !has_dot_expr && !has_trailing_operator {
            // Nothing to recover here.
            return None;
        }

        // Let's try to parse an expression to emit a better diagnostic.
        let mut snapshot = self.create_snapshot_for_diagnostic();
        snapshot.restrictions.insert(Restrictions::IS_PAT);

        // Parse `?`, `.f`, `(arg0, arg1, ...)` or `[expr]` until they've all been eaten.
        let Ok(expr) = snapshot
            .parse_expr_dot_or_call_with(
                AttrVec::new(),
                self.mk_expr(pat_span, ExprKind::Dummy), // equivalent to transforming the parsed pattern into an `Expr`
                pat_span,
            )
            .map_err(|err| err.cancel())
        else {
            // We got a trailing method/operator, but that wasn't an expression.
            return None;
        };

        // Parse an associative expression such as `+ expr`, `% expr`, ...
        // Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
        let Ok((expr, _)) = snapshot
            .parse_expr_assoc_rest(Bound::Unbounded, false, expr)
            .map_err(|err| err.cancel())
        else {
            // We got a trailing method/operator, but that wasn't an expression.
            return None;
        };

        // We got a valid expression.
        self.restore_snapshot(snapshot);
        self.restrictions.remove(Restrictions::IS_PAT);

        let is_bound = is_end_bound
            // is_start_bound: either `..` or `)..`
            || self.token.is_range_separator()
            || self.token == token::CloseParen
                && self.look_ahead(1, Token::is_range_separator);

        let span = expr.span;
        let mut diag = self.dcx().create_err(UnexpectedExpressionInPattern { span, is_bound });
        // The unexpected expr's precedence. Not used directly in the error message, but
        // needed for the stashing of this error to work correctly. We store a `u32` rather
        // than an `ExprPrecedence` to avoid having to impl `IntoDiagArg` for
        // `ExprPrecedence`.
        diag.arg("expr_precedence", expr.precedence() as u32);

        Some((diag.stash(span, StashKey::ExprInPat).unwrap(), span))
    }

    /// Called by [`Parser::parse_stmt_without_recovery`], used to add statement-aware subdiagnostics to the errors stashed
    /// by [`Parser::maybe_recover_trailing_expr`].
    pub(super) fn maybe_augment_stashed_expr_in_pats_with_suggestions(&mut self, stmt: &Stmt) {
        if self.dcx().has_errors().is_none() {
            // No need to walk the statement if there's no stashed errors.
            return;
        }

        struct PatVisitor<'a> {
            /// `self`
            parser: &'a Parser<'a>,
            /// The freshly-parsed statement.
            stmt: &'a Stmt,
            /// The current match arm (for arm guard suggestions).
            arm: Option<&'a Arm>,
            /// The current struct field (for variable name suggestions).
            field: Option<&'a PatField>,
        }

        impl<'a> PatVisitor<'a> {
            /// Looks for stashed [`StashKey::ExprInPat`] errors in `stash_span`, and emit them with suggestions.
            /// `stash_span` is contained in `expr_span`, the latter being larger in borrow patterns;
            /// ```txt
            /// &mut x.y
            /// -----^^^ `stash_span`
            /// |
            /// `expr_span`
            /// ```
            /// `is_range_bound` is used to exclude arm guard suggestions in range pattern bounds.
            fn maybe_add_suggestions_then_emit(
                &self,
                stash_span: Span,
                expr_span: Span,
                is_range_bound: bool,
            ) {
                self.parser.dcx().try_steal_modify_and_emit_err(
                    stash_span,
                    StashKey::ExprInPat,
                    |err| {
                        // Includes pre-pats (e.g. `&mut <err>`) in the diagnostic.
                        err.span.replace(stash_span, expr_span);

                        let sm = self.parser.psess.source_map();
                        let stmt = self.stmt;
                        let line_lo = sm.span_extend_to_line(stmt.span).shrink_to_lo();
                        let indentation = sm.indentation_before(stmt.span).unwrap_or_default();
                        let Ok(expr) = self.parser.span_to_snippet(expr_span) else {
                            // FIXME: some suggestions don't actually need the snippet; see PR #123877's unresolved conversations.
                            return;
                        };

                        if let StmtKind::Let(local) = &stmt.kind {
                            match &local.kind {
                                LocalKind::Decl | LocalKind::Init(_) => {
                                    // It's kinda hard to guess what the user intended, so don't make suggestions.
                                    return;
                                }

                                LocalKind::InitElse(_, _) => {}
                            }
                        }

                        // help: use an arm guard `if val == expr`
                        // FIXME(guard_patterns): suggest this regardless of a match arm.
                        if let Some(arm) = &self.arm
                            && !is_range_bound
                        {
                            let (ident, ident_span) = match self.field {
                                Some(field) => {
                                    (field.ident.to_string(), field.ident.span.to(expr_span))
                                }
                                None => ("val".to_owned(), expr_span),
                            };

                            // Are parentheses required around `expr`?
                            // HACK: a neater way would be preferable.
                            let expr = match &err.args["expr_precedence"] {
                                DiagArgValue::Number(expr_precedence) => {
                                    if *expr_precedence <= ExprPrecedence::Compare as i32 {
                                        format!("({expr})")
                                    } else {
                                        format!("{expr}")
                                    }
                                }
                                _ => unreachable!(),
                            };

                            match &arm.guard {
                                None => {
                                    err.subdiagnostic(
                                        UnexpectedExpressionInPatternSugg::CreateGuard {
                                            ident_span,
                                            pat_hi: arm.pat.span.shrink_to_hi(),
                                            ident,
                                            expr,
                                        },
                                    );
                                }
                                Some(guard) => {
                                    // Are parentheses required around the old guard?
                                    let wrap_guard =
                                        guard.cond.precedence() <= ExprPrecedence::LAnd;

                                    err.subdiagnostic(
                                        UnexpectedExpressionInPatternSugg::UpdateGuard {
                                            ident_span,
                                            guard_lo: if wrap_guard {
                                                Some(guard.span().shrink_to_lo())
                                            } else {
                                                None
                                            },
                                            guard_hi: guard.span().shrink_to_hi(),
                                            guard_hi_paren: if wrap_guard { ")" } else { "" },
                                            ident,
                                            expr,
                                        },
                                    );
                                }
                            }
                        }

                        // help: extract the expr into a `const VAL: _ = expr`
                        if !line_lo.overlaps(expr_span) {
                            let ident = match self.field {
                                Some(field) => field.ident.as_str().to_uppercase(),
                                None => "VAL".to_owned(),
                            };
                            err.subdiagnostic(UnexpectedExpressionInPatternSugg::Const {
                                stmt_lo: line_lo,
                                ident_span: expr_span,
                                expr,
                                ident,
                                indentation,
                            });
                        }
                    },
                );
            }
        }

        impl<'a> Visitor<'a> for PatVisitor<'a> {
            fn visit_arm(&mut self, a: &'a Arm) -> Self::Result {
                self.arm = Some(a);
                visit::walk_arm(self, a);
                self.arm = None;
            }

            fn visit_pat_field(&mut self, fp: &'a PatField) -> Self::Result {
                self.field = Some(fp);
                visit::walk_pat_field(self, fp);
                self.field = None;
            }

            fn visit_pat(&mut self, p: &'a Pat) -> Self::Result {
                match &p.kind {
                    // Base expression
                    PatKind::Err(_) | PatKind::Expr(_) => {
                        self.maybe_add_suggestions_then_emit(p.span, p.span, false)
                    }

                    // Sub-patterns
                    // FIXME: this doesn't work with recursive subpats (`&mut &mut <err>`)
                    PatKind::Ref(subpat, _, _)
                        if matches!(subpat.kind, PatKind::Err(_) | PatKind::Expr(_)) =>
                    {
                        self.maybe_add_suggestions_then_emit(subpat.span, p.span, false)
                    }

                    // Sub-expressions
                    PatKind::Range(start, end, _) => {
                        if let Some(start) = start {
                            self.maybe_add_suggestions_then_emit(start.span, start.span, true);
                        }

                        if let Some(end) = end {
                            self.maybe_add_suggestions_then_emit(end.span, end.span, true);
                        }
                    }

                    // Walk continuation
                    _ => visit::walk_pat(self, p),
                }
            }
        }

        // Starts the visit.
        PatVisitor { parser: self, stmt, arm: None, field: None }.visit_stmt(stmt);
    }

    fn eat_metavar_pat(&mut self) -> Option<Pat> {
        // Must try both kinds of pattern nonterminals.
        if let Some(pat) = self.eat_metavar_seq_with_matcher(
            |mv_kind| matches!(mv_kind, MetaVarKind::Pat(PatParam { .. })),
            |this| this.parse_pat_no_top_alt(None, None),
        ) {
            Some(pat)
        } else if let Some(pat) = self.eat_metavar_seq(MetaVarKind::Pat(PatWithOr), |this| {
            this.parse_pat_no_top_guard(
                None,
                RecoverComma::No,
                RecoverColon::No,
                CommaRecoveryMode::EitherTupleOrPipe,
            )
        }) {
            Some(pat)
        } else {
            None
        }
    }

    /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
    /// allowed).
    fn parse_pat_with_range_pat(
        &mut self,
        allow_range_pat: bool,
        expected: Option<Expected>,
        syntax_loc: Option<PatternLocation>,
    ) -> PResult<'a, Pat> {
        maybe_recover_from_interpolated_ty_qpath!(self, true);

        if let Some(pat) = self.eat_metavar_pat() {
            return Ok(pat);
        }

        let mut lo = self.token.span;

        if self.token.is_keyword(kw::Let)
            && self.look_ahead(1, |tok| {
                tok.can_begin_pattern(token::NtPatKind::PatParam { inferred: false })
            })
        {
            self.bump();
            // Trim extra space after the `let`
            let span = lo.with_hi(self.token.span.lo());
            self.dcx().emit_err(RemoveLet { span: lo, suggestion: span });
            lo = self.token.span;
        }

        let pat = if self.check(exp!(And)) || self.token == token::AndAnd {
            self.parse_pat_deref(expected)?
        } else if self.check(exp!(OpenParen)) {
            self.parse_pat_tuple_or_parens(syntax_loc)?
        } else if self.check(exp!(OpenBracket)) {
            // Parse `[pat, pat,...]` as a slice pattern.
            let (pats, _) =
                self.parse_delim_comma_seq(exp!(OpenBracket), exp!(CloseBracket), |p| {
                    p.parse_pat_allow_top_guard(
                        None,
                        RecoverComma::No,
                        RecoverColon::No,
                        CommaRecoveryMode::EitherTupleOrPipe,
                    )
                })?;
            PatKind::Slice(pats)
        } else if self.check(exp!(DotDot)) && !self.is_pat_range_end_start(1) {
            // A rest pattern `..`.
            self.bump(); // `..`
            PatKind::Rest
        } else if self.check(exp!(DotDotDot)) && !self.is_pat_range_end_start(1) {
            self.recover_dotdotdot_rest_pat(lo, expected)
        } else if let Some(form) = self.parse_range_end() {
            self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`.
        } else if self.eat(exp!(Bang)) {
            // Parse `!`
            self.psess.gated_spans.gate(sym::never_patterns, self.prev_token.span);
            PatKind::Never
        } else if self.eat_keyword(exp!(Underscore)) {
            // Parse `_`
            PatKind::Wild
        } else if self.eat_keyword(exp!(Mut)) {
            self.parse_pat_ident_mut()?
        } else if self.eat_keyword(exp!(Ref)) {
            if self.check_keyword(exp!(Box)) {
                // Suggest `box ref`.
                let span = self.prev_token.span.to(self.token.span);
                self.bump();
                self.dcx().emit_err(SwitchRefBoxOrder { span });
            }
            // Parse ref ident @ pat / ref mut ident @ pat / ref pin const|mut ident @ pat
            let (pinned, mutbl) = self.parse_pin_and_mut();
            self.parse_pat_ident(
                BindingMode(ByRef::Yes(pinned, mutbl), Mutability::Not),
                syntax_loc,
            )?
        } else if self.eat_keyword(exp!(Box)) {
            self.parse_pat_box()?
        } else if self.check_inline_const(0) {
            // Parse `const pat`
            let const_expr = self.parse_const_block(lo.to(self.token.span), true)?;

            if let Some(re) = self.parse_range_end() {
                self.parse_pat_range_begin_with(const_expr, re)?
            } else {
                PatKind::Expr(const_expr)
            }
        } else if self.is_builtin() {
            self.parse_pat_builtin()?
        }
        // Don't eagerly error on semantically invalid tokens when matching
        // declarative macros, as the input to those doesn't have to be
        // semantically valid. For attribute/derive proc macros this is not the
        // case, so doing the recovery for them is fine.
        else if self.can_be_ident_pat()
            || (self.is_lit_bad_ident().is_some() && self.may_recover())
        {
            // Parse `ident @ pat`
            // This can give false positives and parse nullary enums,
            // they are dealt with later in resolve.
            self.parse_pat_ident(BindingMode::NONE, syntax_loc)?
        } else if self.is_start_of_pat_with_path() {
            // Parse pattern starting with a path
            let (qself, path) = if self.eat_lt() {
                // Parse a qualified path
                let (qself, path) = self.parse_qpath(PathStyle::Pat)?;
                (Some(qself), path)
            } else {
                // Parse an unqualified path
                (None, self.parse_path(PathStyle::Pat)?)
            };
            let span = lo.to(self.prev_token.span);

            if qself.is_none() && self.check(exp!(Bang)) {
                self.parse_pat_mac_invoc(path)?
            } else if let Some(form) = self.parse_range_end() {
                let begin = self.mk_expr(span, ExprKind::Path(qself, path));
                self.parse_pat_range_begin_with(begin, form)?
            } else if self.check(exp!(OpenBrace)) {
                self.parse_pat_struct(qself, path)?
            } else if self.check(exp!(OpenParen)) {
                self.parse_pat_tuple_struct(qself, path)?
            } else {
                match self.maybe_recover_trailing_expr(span, false) {
                    Some((guar, _)) => PatKind::Err(guar),
                    None => PatKind::Path(qself, path),
                }
            }
        } else if let Some((lt, IdentIsRaw::No)) = self.token.lifetime()
            // In pattern position, we're totally fine with using "next token isn't colon"
            // as a heuristic. We could probably just always try to recover if it's a lifetime,
            // because we never have `'a: label {}` in a pattern position anyways, but it does
            // keep us from suggesting something like `let 'a: Ty = ..` => `let 'a': Ty = ..`
            && could_be_unclosed_char_literal(lt)
            && !self.look_ahead(1, |token| token.kind == token::Colon)
        {
            // Recover a `'a` as a `'a'` literal
            let lt = self.expect_lifetime();
            let (lit, _) =
                self.recover_unclosed_char(lt.ident, Parser::mk_token_lit_char, |self_| {
                    let expected = Expected::to_string_or_fallback(expected);
                    let msg = format!(
                        "expected {}, found {}",
                        expected,
                        super::token_descr(&self_.token)
                    );

                    self_
                        .dcx()
                        .struct_span_err(self_.token.span, msg)
                        .with_span_label(self_.token.span, format!("expected {expected}"))
                });
            PatKind::Expr(self.mk_expr(lo, ExprKind::Lit(lit)))
        } else {
            // Try to parse everything else as literal with optional minus
            match self.parse_literal_maybe_minus() {
                Ok(begin) => {
                    let begin = self
                        .maybe_recover_trailing_expr(begin.span, false)
                        .map(|(guar, sp)| self.mk_expr_err(sp, guar))
                        .unwrap_or(begin);

                    match self.parse_range_end() {
                        Some(form) => self.parse_pat_range_begin_with(begin, form)?,
                        None => PatKind::Expr(begin),
                    }
                }
                Err(err) => return self.fatal_unexpected_non_pat(err, expected),
            }
        };

        let mut pat = self.mk_pat(lo.to(self.prev_token.span), pat);

        pat = self.maybe_recover_from_bad_qpath(pat)?;
        if self.eat_noexpect(&token::At) {
            pat = self.recover_intersection_pat(pat)?;
        }

        if !allow_range_pat {
            self.ban_pat_range_if_ambiguous(&pat)
        }

        Ok(pat)
    }

    /// Recover from a typoed `...` pattern that was encountered
    /// Ref: Issue #70388
    fn recover_dotdotdot_rest_pat(&mut self, lo: Span, expected: Option<Expected>) -> PatKind {
        // A typoed rest pattern `...`.
        self.bump(); // `...`

        if let Some(Expected::ParameterName) = expected {
            // We have `...` in a closure argument, likely meant to be var-arg, which aren't
            // supported in closures (#146489).
            PatKind::Err(self.dcx().emit_err(DotDotDotRestPattern {
                span: lo,
                suggestion: None,
                var_args: Some(()),
            }))
        } else {
            // The user probably mistook `...` for a rest pattern `..`.
            self.dcx().emit_err(DotDotDotRestPattern {
                span: lo,
                suggestion: Some(lo),
                var_args: None,
            });
            PatKind::Rest
        }
    }

    /// Try to recover the more general form `intersect ::= $pat_lhs @ $pat_rhs`.
    ///
    /// Allowed binding patterns generated by `binding ::= ref? mut? $ident @ $pat_rhs`
    /// should already have been parsed by now at this point,
    /// if the next token is `@` then we can try to parse the more general form.
    ///
    /// Consult `parse_pat_ident` for the `binding` grammar.
    ///
    /// The notion of intersection patterns are found in
    /// e.g. [F#][and] where they are called AND-patterns.
    ///
    /// [and]: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching
    #[cold]
    fn recover_intersection_pat(&mut self, lhs: Pat) -> PResult<'a, Pat> {
        let mut rhs = self.parse_pat_no_top_alt(None, None)?;
        let whole_span = lhs.span.to(rhs.span);

        if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind {
            // The user inverted the order, so help them fix that.
            let lhs_span = lhs.span;
            // Move the LHS into the RHS as a subpattern.
            // The RHS is now the full pattern.
            *sub = Some(Box::new(lhs));

            self.dcx().emit_err(PatternOnWrongSideOfAt {
                whole_span,
                whole_pat: pprust::pat_to_string(&rhs),
                pattern: lhs_span,
                binding: rhs.span,
            });
        } else {
            // The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`.
            rhs.kind = PatKind::Wild;
            self.dcx().emit_err(ExpectedBindingLeftOfAt {
                whole_span,
                lhs: lhs.span,
                rhs: rhs.span,
            });
        }

        rhs.span = whole_span;
        Ok(rhs)
    }

    /// Ban a range pattern if it has an ambiguous interpretation.
    fn ban_pat_range_if_ambiguous(&self, pat: &Pat) {
        match pat.kind {
            PatKind::Range(
                ..,
                Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. },
            ) => return,
            PatKind::Range(..) => {}
            _ => return,
        }

        self.dcx().emit_err(AmbiguousRangePattern {
            span: pat.span,
            suggestion: ParenRangeSuggestion {
                lo: pat.span.shrink_to_lo(),
                hi: pat.span.shrink_to_hi(),
            },
        });
    }

    /// Parse `&pat` / `&mut pat` / `&pin const pat` / `&pin mut pat`.
    fn parse_pat_deref(&mut self, expected: Option<Expected>) -> PResult<'a, PatKind> {
        self.expect_and()?;
        if let Some((lifetime, _)) = self.token.lifetime() {
            self.bump(); // `'a`

            self.dcx().emit_err(UnexpectedLifetimeInPattern {
                span: self.prev_token.span,
                symbol: lifetime.name,
                suggestion: self.prev_token.span.until(self.token.span),
            });
        }

        let (pinned, mutbl) = self.parse_pin_and_mut();
        let subpat = self.parse_pat_with_range_pat(false, expected, None)?;
        Ok(PatKind::Ref(Box::new(subpat), pinned, mutbl))
    }

    /// Parse a tuple or parenthesis pattern.
    fn parse_pat_tuple_or_parens(
        &mut self,
        syntax_loc: Option<PatternLocation>,
    ) -> PResult<'a, PatKind> {
        let open_paren = self.token.span;

        // The index, the span of the `:` and the type of every element written
        // with an inline type annotation, which is invalid syntax. This is kept
        // out of the element patterns themselves so that the happy path doesn't
        // have to allocate for it.
        let mut tys: Vec<(usize, Span, Box<Ty>)> = Vec::new();
        let mut index = 0;

        let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
            let pat = p.parse_pat_allow_top_guard(
                None,
                RecoverComma::No,
                RecoverColon::No,
                CommaRecoveryMode::LikelyTuple,
            )?;
            // Recover from an inline `: <ty>` type annotation. We only do this
            // when there is whitespace after the colon, so that `(a:b)` keeps
            // the existing "maybe write a path separator here" (`a::b`)
            // suggestion, which is the more likely intent when the two are
            // written next to each other.
            if p.may_recover()
                && p.token == token::Colon
                && let colon = p.token.span
                && p.look_ahead(1, |next| next.span.lo() > colon.hi())
            {
                p.bump(); // eat the `:`
                tys.push((index, colon, p.parse_ty()?));
            }
            index += 1;
            Ok(pat)
        })?;

        // If any element carried an inline type annotation then this is the
        // invalid `(a: bool, b: u8)` form; report it and suggest the correct
        // spelling where we can. Either way, continue on with the type
        // annotations stripped.
        if !tys.is_empty() {
            self.recover_tuple_pat_type_ascription(
                open_paren,
                &fields,
                &tys,
                trailing_comma,
                syntax_loc,
            );
        }

        // Here, `(pat,)` is a tuple pattern.
        // For backward compatibility, `(..)` is a tuple pattern as well.
        let paren_pattern =
            fields.len() == 1 && !(matches!(trailing_comma, Trailing::Yes) || fields[0].is_rest());

        let pat = if paren_pattern {
            let pat = fields.into_iter().next().unwrap();
            let close_paren = self.prev_token.span;

            match &pat.kind {
                // recover ranges with parentheses around the `(start)..`
                PatKind::Expr(begin)
                    if self.may_recover()
                        && let Some(form) = self.parse_range_end() =>
                {
                    self.dcx().emit_err(UnexpectedParenInRangePat {
                        span: vec![open_paren, close_paren],
                        sugg: UnexpectedParenInRangePatSugg {
                            start_span: open_paren,
                            end_span: close_paren,
                        },
                    });

                    self.parse_pat_range_begin_with(begin.clone(), form)?
                }
                // recover ranges with parentheses around the `(start)..`
                PatKind::Err(guar)
                    if self.may_recover()
                        && let Some(form) = self.parse_range_end() =>
                {
                    self.dcx().emit_err(UnexpectedParenInRangePat {
                        span: vec![open_paren, close_paren],
                        sugg: UnexpectedParenInRangePatSugg {
                            start_span: open_paren,
                            end_span: close_paren,
                        },
                    });

                    self.parse_pat_range_begin_with(self.mk_expr_err(pat.span, *guar), form)?
                }

                // (pat) with optional parentheses
                _ => PatKind::Paren(Box::new(pat)),
            }
        } else {
            PatKind::Tuple(fields)
        };

        Ok(match self.maybe_recover_trailing_expr(open_paren.to(self.prev_token.span), false) {
            None => pat,
            Some((guar, _)) => PatKind::Err(guar),
        })
    }

    /// Report a tuple or parenthesized pattern whose elements carry inline type
    /// annotations, e.g. `let (a: bool, b: u8) = ...;`. This is invalid syntax;
    /// the element types have to be written together as a tuple type after the
    /// pattern, i.e. `let (a, b): (bool, u8) = ...;`. `tys` are the annotations
    /// that were written, indexed into `fields`.
    fn recover_tuple_pat_type_ascription(
        &self,
        open_paren: Span,
        fields: &[Pat],
        tys: &[(usize, Span, Box<Ty>)],
        trailing_comma: Trailing,
        syntax_loc: Option<PatternLocation>,
    ) {
        let close_paren = self.prev_token.span;

        // Point at every inline type annotation.
        let ty_spans: Vec<Span> = tys.iter().map(|(_, colon, ty)| colon.to(ty.span)).collect();
        // `(a: T)` is a parenthesized pattern rather than a one element tuple.
        let paren_pattern =
            fields.len() == 1 && matches!(trailing_comma, Trailing::No) && !fields[0].is_rest();
        let mut err = self.dcx().struct_span_err(
            ty_spans.clone(),
            if paren_pattern {
                "a parenthesized pattern cannot be given a type"
            } else {
                "the elements of a tuple pattern cannot be given types individually"
            },
        );

        // Only the top level pattern of a `let` binding can be followed by a
        // type, so that's the only place where we know how the pattern should
        // have been written instead. Anywhere else (`match` arms, function
        // parameters, nested patterns) we just recover without a suggestion.
        if matches!(syntax_loc, Some(PatternLocation::LetBinding)) {
            if self.token == token::Colon {
                // The pattern is already followed by a type, as in
                // `let (a: bool, b): (_, u8) = ...;`. Merging that type with the
                // inline ones isn't always possible, so just suggest dropping
                // the inline ones.
                err.multipart_suggestion(
                    "remove the inline type annotations",
                    ty_spans.into_iter().map(|span| (span, String::new())).collect(),
                    Applicability::MaybeIncorrect,
                );
            } else if !fields.iter().any(|pat| pat.is_rest()) {
                // A rest pattern stands for any number of elements, so we can't
                // tell how many types the tuple type would have to list.
                self.suggest_tuple_pat_type(
                    &mut err,
                    open_paren,
                    close_paren,
                    fields,
                    tys,
                    paren_pattern,
                );
            }
        }
        err.emit();
    }

    /// Suggest rewriting `(a: bool, b: u8)` as `(a, b): (bool, u8)`, moving the
    /// inline type annotations into a tuple type after the pattern.
    fn suggest_tuple_pat_type(
        &self,
        err: &mut Diag<'a>,
        open_paren: Span,
        close_paren: Span,
        fields: &[Pat],
        tys: &[(usize, Span, Box<Ty>)],
        paren_pattern: bool,
    ) {
        // Build the replacement from the source snippets. Elements without an
        // annotation get an inferred `_` type.
        let mut pat_snippets = Vec::with_capacity(fields.len());
        let mut ty_snippets = Vec::with_capacity(fields.len());
        let mut tys = tys.iter().peekable();
        for (index, pat) in fields.iter().enumerate() {
            let ty_snippet = match tys.next_if(|(i, ..)| *i == index) {
                Some((_, _, ty)) => self.span_to_snippet(ty.span),
                None => Ok("_".to_string()),
            };
            let (Ok(pat_snippet), Ok(ty_snippet)) = (self.span_to_snippet(pat.span), ty_snippet)
            else {
                // We can't rebuild the pattern from source, so don't suggest anything.
                return;
            };
            pat_snippets.push(pat_snippet);
            ty_snippets.push(ty_snippet);
        }

        // The type of a parenthesized pattern isn't a tuple type. A one element
        // tuple on the other hand keeps its trailing comma on both sides.
        let (suggestion, msg) = if paren_pattern {
            (
                format!("({}): {}", pat_snippets[0], ty_snippets[0]),
                "write the type after the pattern",
            )
        } else {
            let trailing = if fields.len() == 1 { "," } else { "" };
            (
                format!(
                    "({}{trailing}): ({}{trailing})",
                    pat_snippets.join(", "),
                    ty_snippets.join(", ")
                ),
                "to annotate the types of a tuple's elements, write them as a tuple type after \
                 the pattern",
            )
        };
        err.span_suggestion_verbose(
            open_paren.to(close_paren),
            msg,
            suggestion,
            Applicability::MaybeIncorrect,
        );
    }

    /// Parse a mutable binding with the `mut` token already eaten.
    fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> {
        let mut_span = self.prev_token.span;

        self.recover_additional_muts();

        let byref = self.parse_byref();

        self.recover_additional_muts();

        // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`.
        if let Some(MetaVarKind::Pat(_)) = self.token.is_metavar_seq() {
            self.expected_ident_found_err().emit();
        }

        // Parse the pattern we hope to be an identifier.
        let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier), None)?;

        // If we don't have `mut $ident (@ pat)?`, error.
        if let PatKind::Ident(BindingMode(br @ ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind
        {
            // Don't recurse into the subpattern.
            // `mut` on the outer binding doesn't affect the inner bindings.
            *br = byref;
            *m = Mutability::Mut;
        } else {
            // Add `mut` to any binding in the parsed pattern.
            let changed_any_binding = Self::make_all_value_bindings_mutable(&mut pat);
            self.ban_mut_general_pat(mut_span, &pat, changed_any_binding);
        }

        if matches!(pat.kind, PatKind::Ident(BindingMode(ByRef::Yes(..), Mutability::Mut), ..)) {
            self.psess.gated_spans.gate(sym::mut_ref, pat.span);
        }
        Ok(pat.kind)
    }

    /// Turn all by-value immutable bindings in a pattern into mutable bindings.
    /// Returns `true` if any change was made.
    fn make_all_value_bindings_mutable(pat: &mut Pat) -> bool {
        struct AddMut(bool);
        impl MutVisitor for AddMut {
            fn visit_pat(&mut self, pat: &mut Pat) {
                if let PatKind::Ident(BindingMode(ByRef::No, m @ Mutability::Not), ..) =
                    &mut pat.kind
                {
                    self.0 = true;
                    *m = Mutability::Mut;
                }
                mut_visit::walk_pat(self, pat);
            }
        }

        let mut add_mut = AddMut(false);
        add_mut.visit_pat(pat);
        add_mut.0
    }

    /// Error on `mut $pat` where `$pat` is not an ident.
    fn ban_mut_general_pat(&self, lo: Span, pat: &Pat, changed_any_binding: bool) {
        self.dcx().emit_err(if changed_any_binding {
            InvalidMutInPattern::NestedIdent {
                span: lo.to(pat.span),
                pat: pprust::pat_to_string(pat),
            }
        } else {
            InvalidMutInPattern::NonIdent { span: lo.until(pat.span) }
        });
    }

    /// Eat any extraneous `mut`s and error + recover if we ate any.
    fn recover_additional_muts(&mut self) {
        let lo = self.token.span;
        while self.eat_keyword(exp!(Mut)) {}
        if lo == self.token.span {
            return;
        }

        let span = lo.to(self.prev_token.span);
        let suggestion = span.with_hi(self.token.span.lo());
        self.dcx().emit_err(RepeatedMutInPattern { span, suggestion });
    }

    /// Parse macro invocation
    fn parse_pat_mac_invoc(&mut self, path: Path) -> PResult<'a, PatKind> {
        self.bump();
        let args = self.parse_delim_args()?;
        let mac = Box::new(MacCall { path, args });
        Ok(PatKind::MacCall(mac))
    }

    fn fatal_unexpected_non_pat(
        &mut self,
        err: Diag<'a>,
        expected: Option<Expected>,
    ) -> PResult<'a, Pat> {
        err.cancel();

        let expected = Expected::to_string_or_fallback(expected);
        let msg = format!("expected {}, found {}", expected, super::token_descr(&self.token));

        let mut err = self.dcx().struct_span_err(self.token.span, msg);
        err.span_label(self.token.span, format!("expected {expected}"));

        let sp = self.psess.source_map().start_point(self.token.span);
        if let Some(sp) = self.psess.ambiguous_block_expr_parse.borrow().get(&sp) {
            err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
        }

        Err(err)
    }

    /// Parses the range pattern end form `".." | "..." | "..=" ;`.
    fn parse_range_end(&mut self) -> Option<Spanned<RangeEnd>> {
        let re = if self.eat(exp!(DotDotDot)) {
            RangeEnd::Included(RangeSyntax::DotDotDot)
        } else if self.eat(exp!(DotDotEq)) {
            RangeEnd::Included(RangeSyntax::DotDotEq)
        } else if self.eat(exp!(DotDot)) {
            RangeEnd::Excluded
        } else {
            return None;
        };
        Some(respan(self.prev_token.span, re))
    }

    /// Parse a range pattern `$begin $form $end?` where `$form = ".." | "..." | "..=" ;`.
    /// `$begin $form` has already been parsed.
    fn parse_pat_range_begin_with(
        &mut self,
        begin: Box<Expr>,
        re: Spanned<RangeEnd>,
    ) -> PResult<'a, PatKind> {
        let end = if self.is_pat_range_end_start(0) {
            // Parsing e.g. `X..=Y`.
            Some(self.parse_pat_range_end()?)
        } else {
            // Parsing e.g. `X..`.
            if let RangeEnd::Included(_) = re.node {
                // FIXME(Centril): Consider semantic errors instead in `ast_validation`.
                self.inclusive_range_with_incorrect_end();
            }
            None
        };
        Ok(PatKind::Range(Some(begin), end, re))
    }

    pub(super) fn inclusive_range_with_incorrect_end(&mut self) -> ErrorGuaranteed {
        let tok = &self.token;
        let span = self.prev_token.span;
        // If the user typed "..==" or "...=" instead of "..=", we want to give them
        // a specific error message telling them to use "..=".
        // If they typed "..=>", suggest they use ".. =>".
        // Otherwise, we assume that they meant to type a half open exclusive
        // range and give them an error telling them to do that instead.
        let no_space = tok.span.lo() == span.hi();
        match tok.kind {
            token::Eq if no_space => {
                let span_with_eq = span.to(tok.span);

                // Ensure the user doesn't receive unhelpful unexpected token errors
                self.bump();
                if self.is_pat_range_end_start(0) {
                    let _ = self.parse_pat_range_end().map_err(|e| e.cancel());
                }

                self.dcx().emit_err(InclusiveRangeExtraEquals { span: span_with_eq })
            }
            token::Gt if self.prev_token.kind == token::DotDotEq && no_space => {
                self.dcx().emit_err(InclusiveRangeMatchArrow { span, arrow: tok.span })
            }
            _ => self.dcx().emit_err(InclusiveRangeNoEnd { span }),
        }
    }

    /// Parse a range-to pattern, `..X` or `..=X` where `X` remains to be parsed.
    ///
    /// The form `...X` is prohibited to reduce confusion with the potential
    /// expression syntax `...expr` for splatting in expressions.
    fn parse_pat_range_to(&mut self, mut re: Spanned<RangeEnd>) -> PResult<'a, PatKind> {
        let end = self.parse_pat_range_end()?;
        if let RangeEnd::Included(syn @ RangeSyntax::DotDotDot) = &mut re.node {
            *syn = RangeSyntax::DotDotEq;
            self.dcx().emit_err(DotDotDotRangeToPatternNotAllowed { span: re.span });
        }
        Ok(PatKind::Range(None, Some(end), re))
    }

    /// Is the token `dist` away from the current suitable as the start of a range patterns end?
    fn is_pat_range_end_start(&self, dist: usize) -> bool {
        self.check_inline_const(dist)
            || self.look_ahead(dist, |t| {
                t.is_path_start() // e.g. `MY_CONST`;
                || *t == token::Dot // e.g. `.5` for recovery;
                || matches!(t.kind, token::Literal(..) | token::Minus)
                || t.is_bool_lit()
                || t.is_metavar_expr()
                || t.is_lifetime() // recover `'a` instead of `'a'`
                || (self.may_recover() // recover leading `(`
                    && *t == token::OpenParen
                    && self.look_ahead(dist + 1, |t| *t != token::OpenParen)
                    && self.is_pat_range_end_start(dist + 1))
            })
    }

    /// Parse a range pattern end bound
    fn parse_pat_range_end(&mut self) -> PResult<'a, Box<Expr>> {
        // recover leading `(`
        let open_paren = (self.may_recover() && self.eat_noexpect(&token::OpenParen))
            .then_some(self.prev_token.span);

        let bound = if self.check_inline_const(0) {
            self.parse_const_block(self.token.span, true)
        } else if self.check_path() {
            let lo = self.token.span;
            let (qself, path) = if self.eat_lt() {
                // Parse a qualified path
                let (qself, path) = self.parse_qpath(PathStyle::Pat)?;
                (Some(qself), path)
            } else {
                // Parse an unqualified path
                (None, self.parse_path(PathStyle::Pat)?)
            };
            let hi = self.prev_token.span;
            Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path)))
        } else {
            self.parse_literal_maybe_minus()
        }?;

        let recovered = self.maybe_recover_trailing_expr(bound.span, true);

        // recover trailing `)`
        if let Some(open_paren) = open_paren {
            self.expect(exp!(CloseParen))?;

            self.dcx().emit_err(UnexpectedParenInRangePat {
                span: vec![open_paren, self.prev_token.span],
                sugg: UnexpectedParenInRangePatSugg {
                    start_span: open_paren,
                    end_span: self.prev_token.span,
                },
            });
        }

        Ok(match recovered {
            Some((guar, sp)) => self.mk_expr_err(sp, guar),
            None => bound,
        })
    }

    /// Is this the start of a pattern beginning with a path?
    fn is_start_of_pat_with_path(&mut self) -> bool {
        self.check_path()
        // Just for recovery (see `can_be_ident`).
        || self.token.is_ident() && !self.token.is_bool_lit() && !self.token.is_keyword(kw::In)
    }

    /// Would `parse_pat_ident` be appropriate here?
    fn can_be_ident_pat(&mut self) -> bool {
        self.check_ident()
        && !self.token.is_bool_lit() // Avoid `true` or `false` as a binding as it is a literal.
        && !self.token.is_path_segment_keyword() // Avoid e.g. `Self` as it is a path.
        // Avoid `in`. Due to recovery in the list parser this messes with `for ( $pat in $expr )`.
        && !self.token.is_keyword(kw::In)
        // Try to do something more complex?
        && self.look_ahead(1, |t| !matches!(t.kind, token::OpenParen // A tuple struct pattern.
            | token::OpenBrace // A struct pattern.
            | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern.
            | token::PathSep // A tuple / struct variant pattern.
            | token::Bang)) // A macro expanding to a pattern.
    }

    /// Parses `ident` or `ident @ pat`.
    /// Used by the copy foo and ref foo patterns to give a good
    /// error message when parsing mistakes like `ref foo(a, b)`.
    fn parse_pat_ident(
        &mut self,
        binding_annotation: BindingMode,
        syntax_loc: Option<PatternLocation>,
    ) -> PResult<'a, PatKind> {
        let ident = self.parse_ident_common(false)?;

        if self.may_recover()
            && !matches!(syntax_loc, Some(PatternLocation::FunctionParameter))
            && self.check_noexpect(&token::Lt)
            && self.look_ahead(1, |t| t.can_begin_type())
        {
            return Err(self.dcx().create_err(GenericArgsInPatRequireTurbofishSyntax {
                span: self.token.span,
                suggest_turbofish: self.token.span.shrink_to_lo(),
            }));
        }

        let sub = if self.eat(exp!(At)) {
            Some(Box::new(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?))
        } else {
            None
        };

        // Just to be friendly, if they write something like `ref Some(i)`,
        // we end up here with `(` as the current token.
        // This shortly leads to a parse error. Note that if there is no explicit
        // binding mode then we do not end up here, because the lookahead
        // will direct us over to `parse_enum_variant()`.
        if self.token == token::OpenParen {
            return Err(self
                .dcx()
                .create_err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span }));
        }

        // Check for method calls after the `ident`,
        // but not `ident @ subpat` as `subpat` was already checked and `ident` continues with `@`.

        let pat = if sub.is_none()
            && let Some((guar, _)) = self.maybe_recover_trailing_expr(ident.span, false)
        {
            PatKind::Err(guar)
        } else {
            PatKind::Ident(binding_annotation, ident, sub)
        };
        Ok(pat)
    }

    /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
    fn parse_pat_struct(&mut self, qself: Option<Box<QSelf>>, path: Path) -> PResult<'a, PatKind> {
        if qself.is_some() {
            // Feature gate the use of qualified paths in patterns
            self.psess.gated_spans.gate(sym::more_qualified_paths, path.span);
        }
        self.bump();
        let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
            e.span_label(path.span, "while parsing the fields for this pattern");
            let guar = e.emit();
            self.recover_stmt();
            // When recovering, pretend we had `Foo { .. }`, to avoid cascading errors.
            (ThinVec::new(), PatFieldsRest::Recovered(guar))
        });
        self.bump();
        Ok(PatKind::Struct(qself, path, fields, etc))
    }

    /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
    fn parse_pat_tuple_struct(
        &mut self,
        qself: Option<Box<QSelf>>,
        path: Path,
    ) -> PResult<'a, PatKind> {
        let (fields, _) = self.parse_paren_comma_seq(|p| {
            p.parse_pat_allow_top_guard(
                None,
                RecoverComma::No,
                RecoverColon::No,
                CommaRecoveryMode::EitherTupleOrPipe,
            )
        })?;
        if qself.is_some() {
            self.psess.gated_spans.gate(sym::more_qualified_paths, path.span);
        }
        Ok(PatKind::TupleStruct(qself, path, fields))
    }

    /// Are we sure this could not possibly be the start of a pattern?
    ///
    /// Currently, this only accounts for tokens that can follow identifiers
    /// in patterns, but this can be extended as necessary.
    fn isnt_pattern_start(&self) -> bool {
        [
            token::Eq,
            token::Colon,
            token::Comma,
            token::Semi,
            token::At,
            token::OpenBrace,
            token::CloseBrace,
            token::CloseParen,
        ]
        .contains(&self.token.kind)
    }

    fn parse_pat_builtin(&mut self) -> PResult<'a, PatKind> {
        self.parse_builtin(|self_, _lo, ident| {
            Ok(match ident.name {
                // builtin#deref(PAT)
                sym::deref => {
                    Some(ast::PatKind::Deref(Box::new(self_.parse_pat_allow_top_guard(
                        None,
                        RecoverComma::Yes,
                        RecoverColon::Yes,
                        CommaRecoveryMode::LikelyTuple,
                    )?)))
                }
                _ => None,
            })
        })
    }

    // FIXME: remove this entirely eventually
    /// Parses the removed `box pat` syntax to provide a more helpful error message.
    fn parse_pat_box(&mut self) -> PResult<'a, PatKind> {
        let box_span = self.prev_token.span;

        if self.isnt_pattern_start() {
            let descr = super::token_descr(&self.token);
            self.dcx().emit_err(diagnostics::BoxNotPat {
                span: self.token.span,
                kw: box_span,
                lo: box_span.shrink_to_lo(),
                descr,
            });

            // We cannot use `parse_pat_ident()` since it will complain `box`
            // is not an identifier.
            let sub = if self.eat(exp!(At)) {
                Some(Box::new(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?))
            } else {
                None
            };

            Ok(PatKind::Ident(BindingMode::NONE, Ident::new(kw::Box, box_span), sub))
        } else {
            let pat = Box::new(self.parse_pat_with_range_pat(false, None, None)?);
            self.dcx().emit_err(diagnostics::BoxPatternsRemoved {
                span: box_span.to(self.prev_token.span),
            });
            // Treat the box pattern like a deref pattern to avoid lots of "value not found" errors.
            Ok(PatKind::Deref(pat))
        }
    }

    /// Parses the fields of a struct-like pattern.
    fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, PatFieldsRest)> {
        let mut fields: ThinVec<PatField> = ThinVec::new();
        let mut etc = PatFieldsRest::None;
        let mut ate_comma = true;
        let mut delayed_err: Option<Diag<'a>> = None;
        let mut first_etc_and_maybe_comma_span = None;
        let mut last_non_comma_dotdot_span = None;

        while self.token != token::CloseBrace {
            // check that a comma comes after every field
            if !ate_comma {
                let err = if self.token == token::At {
                    let prev_field = fields
                        .last()
                        .expect("Unreachable on first iteration, not empty otherwise")
                        .ident;
                    self.report_misplaced_at_in_struct_pat(prev_field)
                } else {
                    let mut err = self
                        .dcx()
                        .create_err(ExpectedCommaAfterPatternField { span: self.token.span });
                    self.recover_misplaced_pattern_modifiers(&fields, &mut err);
                    err
                };
                if let Some(delayed) = delayed_err {
                    delayed.emit();
                }
                return Err(err);
            }
            ate_comma = false;

            if self.check(exp!(DotDot))
                || self.check_noexpect(&token::DotDotDot)
                || self.check_keyword(exp!(Underscore))
            {
                etc = PatFieldsRest::Rest(self.token.span);
                let mut etc_sp = self.token.span;
                if first_etc_and_maybe_comma_span.is_none() {
                    if let Some(comma_tok) =
                        self.look_ahead(1, |&t| if t == token::Comma { Some(t) } else { None })
                    {
                        let nw_span = self
                            .psess
                            .source_map()
                            .span_extend_to_line(comma_tok.span)
                            .trim_start(comma_tok.span.shrink_to_lo())
                            .map(|s| self.psess.source_map().span_until_non_whitespace(s));
                        first_etc_and_maybe_comma_span = nw_span.map(|s| etc_sp.to(s));
                    } else {
                        first_etc_and_maybe_comma_span =
                            Some(self.psess.source_map().span_until_non_whitespace(etc_sp));
                    }
                }

                self.recover_bad_dot_dot();
                self.bump(); // `..` || `...` || `_`

                if self.token == token::CloseBrace {
                    break;
                }
                let token_str = super::token_descr(&self.token);
                let msg = format!("expected `}}`, found {token_str}");
                let mut err = self.dcx().struct_span_err(self.token.span, msg);

                err.span_label(self.token.span, "expected `}`");
                let mut comma_sp = None;
                if self.token == token::Comma {
                    // Issue #49257
                    let nw_span =
                        self.psess.source_map().span_until_non_whitespace(self.token.span);
                    etc_sp = etc_sp.to(nw_span);
                    err.span_label(
                        etc_sp,
                        "`..` must be at the end and cannot have a trailing comma",
                    );
                    comma_sp = Some(self.token.span);
                    self.bump();
                    ate_comma = true;
                }

                if self.token == token::CloseBrace {
                    // If the struct looks otherwise well formed, recover and continue.
                    if let Some(sp) = comma_sp {
                        err.span_suggestion_short(
                            sp,
                            "remove this comma",
                            "",
                            Applicability::MachineApplicable,
                        );
                    }
                    err.emit();
                    break;
                } else if self.token.is_ident() && ate_comma {
                    // Accept fields coming after `..,`.
                    // This way we avoid "pattern missing fields" errors afterwards.
                    // We delay this error until the end in order to have a span for a
                    // suggested fix.
                    if let Some(delayed_err) = delayed_err {
                        delayed_err.emit();
                        return Err(err);
                    } else {
                        delayed_err = Some(err);
                    }
                } else {
                    if let Some(err) = delayed_err {
                        err.emit();
                    }
                    return Err(err);
                }
            }

            let attrs = match self.parse_outer_attributes() {
                Ok(attrs) => attrs,
                Err(err) => {
                    if let Some(delayed) = delayed_err {
                        delayed.emit();
                    }
                    return Err(err);
                }
            };
            let lo = self.token.span;

            let field = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
                let field = match this.parse_pat_field(lo, attrs) {
                    Ok(field) => Ok(field),
                    Err(err) => {
                        if let Some(delayed_err) = delayed_err.take() {
                            delayed_err.emit();
                        }
                        return Err(err);
                    }
                }?;
                ate_comma = this.eat(exp!(Comma));

                last_non_comma_dotdot_span = Some(this.prev_token.span);

                // We just ate a comma, so there's no need to capture a trailing token.
                Ok((field, Trailing::No, UsePreAttrPos::No))
            })?;

            fields.push(field)
        }

        if let Some(mut err) = delayed_err {
            if let Some(first_etc_span) = first_etc_and_maybe_comma_span {
                if self.prev_token == token::DotDot {
                    // We have `.., x, ..`.
                    err.multipart_suggestion(
                        "remove the starting `..`",
                        vec![(first_etc_span, String::new())],
                        Applicability::MachineApplicable,
                    );
                } else if let Some(last_non_comma_dotdot_span) = last_non_comma_dotdot_span {
                    // We have `.., x`.
                    err.multipart_suggestion(
                        "move the `..` to the end of the field list",
                        vec![
                            (first_etc_span, String::new()),
                            (
                                self.token.span.to(last_non_comma_dotdot_span.shrink_to_hi()),
                                format!("{} .. }}", if ate_comma { "" } else { "," }),
                            ),
                        ],
                        Applicability::MachineApplicable,
                    );
                }
            }
            err.emit();
        }
        Ok((fields, etc))
    }

    fn report_misplaced_at_in_struct_pat(&self, prev_field: Ident) -> Diag<'a> {
        debug_assert_eq!(self.token, token::At);
        let span = prev_field.span.to(self.token.span);
        if let Some(dot_dot_span) =
            self.look_ahead(1, |t| if t == &token::DotDot { Some(t.span) } else { None })
        {
            self.dcx().create_err(AtDotDotInStructPattern {
                span: span.to(dot_dot_span),
                remove: span.until(dot_dot_span),
                ident: prev_field,
            })
        } else {
            self.dcx().create_err(AtInStructPattern { span })
        }
    }

    /// If the user writes `S { ref field: name }` instead of `S { field: ref name }`, we suggest
    /// the correct code.
    fn recover_misplaced_pattern_modifiers(&self, fields: &ThinVec<PatField>, err: &mut Diag<'a>) {
        if let Some(last) = fields.last()
            && last.is_shorthand
            && let PatKind::Ident(binding, ident, None) = last.pat.kind
            && binding != BindingMode::NONE
            && self.token == token::Colon
            // We found `ref mut? ident:`, try to parse a `name,` or `name }`.
            && let Some(name_span) = self.look_ahead(1, |t| t.is_ident().then(|| t.span))
            && self.look_ahead(2, |t| {
                t == &token::Comma || t == &token::CloseBrace
            })
        {
            let span = last.pat.span.with_hi(ident.span.lo());
            // We have `S { ref field: name }` instead of `S { field: ref name }`
            err.multipart_suggestion(
                "the pattern modifiers belong after the `:`",
                vec![
                    (span, String::new()),
                    (name_span.shrink_to_lo(), binding.prefix_str().to_string()),
                ],
                Applicability::MachineApplicable,
            );
        }
    }

    /// Recover on `...` or `_` as if it were `..` to avoid further errors.
    /// See issue #46718.
    fn recover_bad_dot_dot(&self) {
        if self.token == token::DotDot {
            return;
        }

        let token_str = pprust::token_to_string(&self.token);
        self.dcx().emit_err(DotDotDotForRemainingFields { span: self.token.span, token_str });
    }

    /// Parse a field in a struct pattern.
    ///
    /// ```ebnf
    /// PatField = FieldName ":" Pat | "mut"? ByRef? Ident
    /// ```
    fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> {
        let hi;
        let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
            let fieldname = self.parse_field_name()?;
            self.bump();
            let pat = self.parse_pat_allow_top_guard(
                None,
                RecoverComma::No,
                RecoverColon::No,
                CommaRecoveryMode::EitherTupleOrPipe,
            )?;
            hi = pat.span;
            (pat, fieldname, false)
        } else {
            // FIXME: remove the recovery for parsing box patterrns entirely
            let is_box = self.eat_keyword(exp!(Box));
            if is_box {
                self.dcx()
                    .create_err(diagnostics::BoxPatternsRemoved { span: self.prev_token.span })
                    .emit();
            }
            let boxed_span = self.token.span;
            let mutability = self.parse_mutability();
            let by_ref = self.parse_byref();

            let fieldname = self.parse_ident_common(false)?;
            hi = self.prev_token.span;
            let ann = BindingMode(by_ref, mutability);
            let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname);
            if matches!(
                fieldpat.kind,
                PatKind::Ident(BindingMode(ByRef::Yes(..), Mutability::Mut), ..)
            ) {
                self.psess.gated_spans.gate(sym::mut_ref, fieldpat.span);
            }
            let subpat = if is_box {
                self.mk_pat(lo.to(hi), PatKind::Deref(Box::new(fieldpat)))
            } else {
                fieldpat
            };
            (subpat, fieldname, true)
        };

        Ok(PatField {
            ident: fieldname,
            pat: Box::new(subpat),
            is_shorthand,
            attrs,
            id: ast::DUMMY_NODE_ID,
            span: lo.to(hi),
            is_placeholder: false,
        })
    }

    pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> Pat {
        self.mk_pat(span, PatKind::Ident(ann, ident, None))
    }

    pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> Pat {
        Pat { kind, span, id: ast::DUMMY_NODE_ID }
    }
}
