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,
};
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`
                        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::Box(subpat) | 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()?
        } 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) -> PResult<'a, PatKind> {
        let open_paren = self.token.span;

        let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
            p.parse_pat_allow_top_guard(
                None,
                RecoverComma::No,
                RecoverColon::No,
                CommaRecoveryMode::LikelyTuple,
            )
        })?;

        // 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),
        })
    }

    /// 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,
            })
        })
    }

    /// Parses `box pat`
    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.psess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
            Ok(PatKind::Box(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.iter().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 | "box"? "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 {
            let is_box = self.eat_keyword(exp!(Box));
            if is_box {
                self.psess.gated_spans.gate(sym::box_patterns, self.prev_token.span);
            }
            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::Box(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 }
    }
}
