use std::mem::take;
use std::ops::{Deref, DerefMut};

use ast::token::IdentIsRaw;
use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind};
use rustc_ast::util::parser::AssocOp;
use rustc_ast::{
    self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode,
    Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind,
    MgcaDisambiguation, Param, Pat, PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{
    Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, PResult, Subdiagnostic, Suggestions,
    inline_fluent, pluralize,
};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::used_keywords;
use rustc_span::{BytePos, DUMMY_SP, Ident, Span, SpanSnippetError, Symbol, kw, sym};
use thin_vec::{ThinVec, thin_vec};
use tracing::{debug, trace};

use super::pat::Expected;
use super::{
    BlockMode, CommaRecoveryMode, ExpTokenPair, Parser, PathStyle, Restrictions, SemiColonMode,
    SeqSep, TokenType,
};
use crate::errors::{
    AddParen, AmbiguousPlus, AsyncMoveBlockIn2015, AsyncUseBlockIn2015, AttributeOnParamType,
    AwaitSuggestion, BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi,
    ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg,
    DocCommentDoesNotDocumentAnything, DocCommentOnParamType, DoubleColonInBound,
    ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets,
    GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, HelpUseLatestEdition,
    InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse,
    MisspelledKw, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg,
    SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg,
    SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator,
    TernaryOperatorSuggestion, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
    UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType,
};
use crate::exp;
use crate::parser::FnContext;
use crate::parser::attr::InnerAttrPolicy;
use crate::parser::item::IsDotDotDot;

/// Creates a placeholder argument.
pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param {
    let pat = Box::new(Pat {
        id: ast::DUMMY_NODE_ID,
        kind: PatKind::Ident(BindingMode::NONE, ident, None),
        span: ident.span,
        tokens: None,
    });
    let ty = Ty { kind: TyKind::Err(guar), span: ident.span, id: ast::DUMMY_NODE_ID, tokens: None };
    Param {
        attrs: AttrVec::default(),
        id: ast::DUMMY_NODE_ID,
        pat,
        span: ident.span,
        ty: Box::new(ty),
        is_placeholder: false,
    }
}

pub(super) trait RecoverQPath: Sized + 'static {
    const PATH_STYLE: PathStyle = PathStyle::Expr;
    fn to_ty(&self) -> Option<Box<Ty>>;
    fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self;
}

impl<T: RecoverQPath> RecoverQPath for Box<T> {
    const PATH_STYLE: PathStyle = T::PATH_STYLE;
    fn to_ty(&self) -> Option<Box<Ty>> {
        T::to_ty(self)
    }
    fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self {
        Box::new(T::recovered(qself, path))
    }
}

impl RecoverQPath for Ty {
    const PATH_STYLE: PathStyle = PathStyle::Type;
    fn to_ty(&self) -> Option<Box<Ty>> {
        Some(Box::new(self.clone()))
    }
    fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self {
        Self {
            span: path.span,
            kind: TyKind::Path(qself, path),
            id: ast::DUMMY_NODE_ID,
            tokens: None,
        }
    }
}

impl RecoverQPath for Pat {
    const PATH_STYLE: PathStyle = PathStyle::Pat;
    fn to_ty(&self) -> Option<Box<Ty>> {
        self.to_ty()
    }
    fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self {
        Self {
            span: path.span,
            kind: PatKind::Path(qself, path),
            id: ast::DUMMY_NODE_ID,
            tokens: None,
        }
    }
}

impl RecoverQPath for Expr {
    fn to_ty(&self) -> Option<Box<Ty>> {
        self.to_ty()
    }
    fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self {
        Self {
            span: path.span,
            kind: ExprKind::Path(qself, path),
            attrs: AttrVec::new(),
            id: ast::DUMMY_NODE_ID,
            tokens: None,
        }
    }
}

/// Control whether the closing delimiter should be consumed when calling `Parser::consume_block`.
pub(crate) enum ConsumeClosingDelim {
    Yes,
    No,
}

#[derive(Clone, Copy)]
pub enum AttemptLocalParseRecovery {
    Yes,
    No,
}

impl AttemptLocalParseRecovery {
    pub(super) fn yes(&self) -> bool {
        match self {
            AttemptLocalParseRecovery::Yes => true,
            AttemptLocalParseRecovery::No => false,
        }
    }

    pub(super) fn no(&self) -> bool {
        match self {
            AttemptLocalParseRecovery::Yes => false,
            AttemptLocalParseRecovery::No => true,
        }
    }
}

/// Information for emitting suggestions and recovering from
/// C-style `i++`, `--i`, etc.
#[derive(Debug, Copy, Clone)]
struct IncDecRecovery {
    /// Is this increment/decrement its own statement?
    standalone: IsStandalone,
    /// Is this an increment or decrement?
    op: IncOrDec,
    /// Is this pre- or postfix?
    fixity: UnaryFixity,
}

/// Is an increment or decrement expression its own statement?
#[derive(Debug, Copy, Clone)]
enum IsStandalone {
    /// It's standalone, i.e., its own statement.
    Standalone,
    /// It's a subexpression, i.e., *not* standalone.
    Subexpr,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum IncOrDec {
    Inc,
    Dec,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum UnaryFixity {
    Pre,
    Post,
}

impl IncOrDec {
    fn chr(&self) -> char {
        match self {
            Self::Inc => '+',
            Self::Dec => '-',
        }
    }

    fn name(&self) -> &'static str {
        match self {
            Self::Inc => "increment",
            Self::Dec => "decrement",
        }
    }
}

impl std::fmt::Display for UnaryFixity {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Pre => write!(f, "prefix"),
            Self::Post => write!(f, "postfix"),
        }
    }
}

/// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`.
///
/// This is a specialized version of [`Symbol::find_similar`] that constructs an error when a
/// candidate is found.
fn find_similar_kw(lookup: Ident, candidates: &[Symbol]) -> Option<MisspelledKw> {
    lookup.name.find_similar(candidates).map(|(similar_kw, is_incorrect_case)| MisspelledKw {
        similar_kw: similar_kw.to_string(),
        is_incorrect_case,
        span: lookup.span,
    })
}

struct MultiSugg {
    msg: String,
    patches: Vec<(Span, String)>,
    applicability: Applicability,
}

impl MultiSugg {
    fn emit(self, err: &mut Diag<'_>) {
        err.multipart_suggestion(self.msg, self.patches, self.applicability);
    }

    fn emit_verbose(self, err: &mut Diag<'_>) {
        err.multipart_suggestion_verbose(self.msg, self.patches, self.applicability);
    }
}

/// SnapshotParser is used to create a snapshot of the parser
/// without causing duplicate errors being emitted when the `Parser`
/// is dropped.
pub struct SnapshotParser<'a> {
    parser: Parser<'a>,
}

impl<'a> Deref for SnapshotParser<'a> {
    type Target = Parser<'a>;

    fn deref(&self) -> &Self::Target {
        &self.parser
    }
}

impl<'a> DerefMut for SnapshotParser<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.parser
    }
}

impl<'a> Parser<'a> {
    pub fn dcx(&self) -> DiagCtxtHandle<'a> {
        self.psess.dcx()
    }

    /// Replace `self` with `snapshot.parser`.
    pub fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) {
        *self = snapshot.parser;
    }

    /// Create a snapshot of the `Parser`.
    pub fn create_snapshot_for_diagnostic(&self) -> SnapshotParser<'a> {
        let snapshot = self.clone();
        SnapshotParser { parser: snapshot }
    }

    pub(super) fn span_to_snippet(&self, span: Span) -> Result<String, SpanSnippetError> {
        self.psess.source_map().span_to_snippet(span)
    }

    /// Emits an error with suggestions if an identifier was expected but not found.
    ///
    /// Returns a possibly recovered identifier.
    pub(super) fn expected_ident_found(
        &mut self,
        recover: bool,
    ) -> PResult<'a, (Ident, IdentIsRaw)> {
        let valid_follow = &[
            TokenKind::Eq,
            TokenKind::Colon,
            TokenKind::Comma,
            TokenKind::Semi,
            TokenKind::PathSep,
            TokenKind::OpenBrace,
            TokenKind::OpenParen,
            TokenKind::CloseBrace,
            TokenKind::CloseParen,
        ];
        if let TokenKind::DocComment(..) = self.prev_token.kind
            && valid_follow.contains(&self.token.kind)
        {
            let err = self.dcx().create_err(DocCommentDoesNotDocumentAnything {
                span: self.prev_token.span,
                missing_comma: None,
            });
            return Err(err);
        }

        let mut recovered_ident = None;
        // we take this here so that the correct original token is retained in
        // the diagnostic, regardless of eager recovery.
        let bad_token = self.token;

        // suggest prepending a keyword in identifier position with `r#`
        let suggest_raw = if let Some((ident, IdentIsRaw::No)) = self.token.ident()
            && ident.is_raw_guess()
            && self.look_ahead(1, |t| valid_follow.contains(&t.kind))
        {
            recovered_ident = Some((ident, IdentIsRaw::Yes));

            // `Symbol::to_string()` is different from `Symbol::into_diag_arg()`,
            // which uses `Symbol::to_ident_string()` and "helpfully" adds an implicit `r#`
            let ident_name = ident.name.to_string();

            Some(SuggEscapeIdentifier { span: ident.span.shrink_to_lo(), ident_name })
        } else {
            None
        };

        let suggest_remove_comma =
            if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
                if recover {
                    self.bump();
                    recovered_ident = self.ident_or_err(false).ok();
                };

                Some(SuggRemoveComma { span: bad_token.span })
            } else {
                None
            };

        let help_cannot_start_number = self.is_lit_bad_ident().map(|(len, valid_portion)| {
            let (invalid, valid) = self.token.span.split_at(len as u32);

            recovered_ident = Some((Ident::new(valid_portion, valid), IdentIsRaw::No));

            HelpIdentifierStartsWithNumber { num_span: invalid }
        });

        let err = ExpectedIdentifier {
            span: bad_token.span,
            token: bad_token,
            suggest_raw,
            suggest_remove_comma,
            help_cannot_start_number,
        };
        let mut err = self.dcx().create_err(err);

        // if the token we have is a `<`
        // it *might* be a misplaced generic
        // FIXME: could we recover with this?
        if self.token == token::Lt {
            // all keywords that could have generic applied
            let valid_prev_keywords =
                [kw::Fn, kw::Type, kw::Struct, kw::Enum, kw::Union, kw::Trait];

            // If we've expected an identifier,
            // and the current token is a '<'
            // if the previous token is a valid keyword
            // that might use a generic, then suggest a correct
            // generic placement (later on)
            let maybe_keyword = self.prev_token;
            if valid_prev_keywords.into_iter().any(|x| maybe_keyword.is_keyword(x)) {
                // if we have a valid keyword, attempt to parse generics
                // also obtain the keywords symbol
                match self.parse_generics() {
                    Ok(generic) => {
                        if let TokenKind::Ident(symbol, _) = maybe_keyword.kind {
                            let ident_name = symbol;
                            // at this point, we've found something like
                            // `fn <T>id`
                            // and current token should be Ident with the item name (i.e. the function name)
                            // if there is a `<` after the fn name, then don't show a suggestion, show help

                            if !self.look_ahead(1, |t| *t == token::Lt)
                                && let Ok(snippet) =
                                    self.psess.source_map().span_to_snippet(generic.span)
                            {
                                err.multipart_suggestion_verbose(
                                        format!("place the generic parameter name after the {ident_name} name"),
                                        vec![
                                            (self.token.span.shrink_to_hi(), snippet),
                                            (generic.span, String::new())
                                        ],
                                        Applicability::MaybeIncorrect,
                                    );
                            } else {
                                err.help(format!(
                                    "place the generic parameter name after the {ident_name} name"
                                ));
                            }
                        }
                    }
                    Err(err) => {
                        // if there's an error parsing the generics,
                        // then don't do a misplaced generics suggestion
                        // and emit the expected ident error instead;
                        err.cancel();
                    }
                }
            }
        }

        if let Some(recovered_ident) = recovered_ident
            && recover
        {
            err.emit();
            Ok(recovered_ident)
        } else {
            Err(err)
        }
    }

    pub(super) fn expected_ident_found_err(&mut self) -> Diag<'a> {
        self.expected_ident_found(false).unwrap_err()
    }

    /// Checks if the current token is a integer or float literal and looks like
    /// it could be a invalid identifier with digits at the start.
    ///
    /// Returns the number of characters (bytes) composing the invalid portion
    /// of the identifier and the valid portion of the identifier.
    pub(super) fn is_lit_bad_ident(&mut self) -> Option<(usize, Symbol)> {
        // ensure that the integer literal is followed by a *invalid*
        // suffix: this is how we know that it is a identifier with an
        // invalid beginning.
        if let token::Literal(Lit {
            kind: token::LitKind::Integer | token::LitKind::Float,
            symbol,
            suffix: Some(suffix), // no suffix makes it a valid literal
        }) = self.token.kind
            && rustc_ast::MetaItemLit::from_token(&self.token).is_none()
        {
            Some((symbol.as_str().len(), suffix))
        } else {
            None
        }
    }

    pub(super) fn expected_one_of_not_found(
        &mut self,
        edible: &[ExpTokenPair],
        inedible: &[ExpTokenPair],
    ) -> PResult<'a, ErrorGuaranteed> {
        debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible);
        fn tokens_to_string(tokens: &[TokenType]) -> String {
            let mut i = tokens.iter();
            // This might be a sign we need a connect method on `Iterator`.
            let b = i.next().map_or_else(String::new, |t| t.to_string());
            i.enumerate().fold(b, |mut b, (i, a)| {
                if tokens.len() > 2 && i == tokens.len() - 2 {
                    b.push_str(", or ");
                } else if tokens.len() == 2 && i == tokens.len() - 2 {
                    b.push_str(" or ");
                } else {
                    b.push_str(", ");
                }
                b.push_str(&a.to_string());
                b
            })
        }

        for exp in edible.iter().chain(inedible.iter()) {
            self.expected_token_types.insert(exp.token_type);
        }
        let mut expected: Vec<_> = self.expected_token_types.iter().collect();
        expected.sort_by_cached_key(|x| x.to_string());
        expected.dedup();

        let sm = self.psess.source_map();

        // Special-case "expected `;`" errors.
        if expected.contains(&TokenType::Semi) {
            // If the user is trying to write a ternary expression, recover it and
            // return an Err to prevent a cascade of irrelevant diagnostics.
            if self.prev_token == token::Question
                && let Err(e) = self.maybe_recover_from_ternary_operator(None)
            {
                return Err(e);
            }

            if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP {
                // Likely inside a macro, can't provide meaningful suggestions.
            } else if !sm.is_multiline(self.prev_token.span.until(self.token.span)) {
                // The current token is in the same line as the prior token, not recoverable.
            } else if [token::Comma, token::Colon].contains(&self.token.kind)
                && self.prev_token == token::CloseParen
            {
                // Likely typo: The current token is on a new line and is expected to be
                // `.`, `;`, `?`, or an operator after a close delimiter token.
                //
                // let a = std::process::Command::new("echo")
                //         .arg("1")
                //         ,arg("2")
                //         ^
                // https://github.com/rust-lang/rust/issues/72253
            } else if self.look_ahead(1, |t| {
                t == &token::CloseBrace || t.can_begin_expr() && *t != token::Colon
            }) && [token::Comma, token::Colon].contains(&self.token.kind)
            {
                // Likely typo: `,` → `;` or `:` → `;`. This is triggered if the current token is
                // either `,` or `:`, and the next token could either start a new statement or is a
                // block close. For example:
                //
                //   let x = 32:
                //   let y = 42;
                let guar = self.dcx().emit_err(ExpectedSemi {
                    span: self.token.span,
                    token: self.token,
                    unexpected_token_label: None,
                    sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span),
                });
                self.bump();
                return Ok(guar);
            } else if self.look_ahead(0, |t| {
                t == &token::CloseBrace
                    || ((t.can_begin_expr() || t.can_begin_item())
                        && t != &token::Semi
                        && t != &token::Pound)
                    // Avoid triggering with too many trailing `#` in raw string.
                    || (sm.is_multiline(
                        self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo()),
                    ) && t == &token::Pound)
            }) && !expected.contains(&TokenType::Comma)
            {
                // Missing semicolon typo. This is triggered if the next token could either start a
                // new statement or is a block close. For example:
                //
                //   let x = 32
                //   let y = 42;
                let span = self.prev_token.span.shrink_to_hi();
                let guar = self.dcx().emit_err(ExpectedSemi {
                    span,
                    token: self.token,
                    unexpected_token_label: Some(self.token.span),
                    sugg: ExpectedSemiSugg::AddSemi(span),
                });
                return Ok(guar);
            }
        }

        if self.token == TokenKind::EqEq
            && self.prev_token.is_ident()
            && expected.contains(&TokenType::Eq)
        {
            // Likely typo: `=` → `==` in let expr or enum item
            return Err(self.dcx().create_err(UseEqInstead { span: self.token.span }));
        }

        if (self.token.is_keyword(kw::Move) || self.token.is_keyword(kw::Use))
            && self.prev_token.is_keyword(kw::Async)
        {
            // The 2015 edition is in use because parsing of `async move` or `async use` has failed.
            let span = self.prev_token.span.to(self.token.span);
            if self.token.is_keyword(kw::Move) {
                return Err(self.dcx().create_err(AsyncMoveBlockIn2015 { span }));
            } else {
                // kw::Use
                return Err(self.dcx().create_err(AsyncUseBlockIn2015 { span }));
            }
        }

        let expect = tokens_to_string(&expected);
        let actual = super::token_descr(&self.token);
        let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
            let fmt = format!("expected one of {expect}, found {actual}");
            let short_expect = if expected.len() > 6 {
                format!("{} possible tokens", expected.len())
            } else {
                expect
            };
            (fmt, (self.prev_token.span.shrink_to_hi(), format!("expected one of {short_expect}")))
        } else if expected.is_empty() {
            (
                format!("unexpected token: {actual}"),
                (self.prev_token.span, "unexpected token after this".to_string()),
            )
        } else {
            (
                format!("expected {expect}, found {actual}"),
                (self.prev_token.span.shrink_to_hi(), format!("expected {expect}")),
            )
        };
        self.last_unexpected_token_span = Some(self.token.span);
        // FIXME: translation requires list formatting (for `expect`)
        let mut err = self.dcx().struct_span_err(self.token.span, msg_exp);

        self.label_expected_raw_ref(&mut err);

        // Look for usages of '=>' where '>=' was probably intended
        if self.token == token::FatArrow
            && expected.iter().any(|tok| matches!(tok, TokenType::Operator | TokenType::Le))
            && !expected.iter().any(|tok| matches!(tok, TokenType::FatArrow | TokenType::Comma))
        {
            err.span_suggestion(
                self.token.span,
                "you might have meant to write a \"greater than or equal to\" comparison",
                ">=",
                Applicability::MaybeIncorrect,
            );
        }

        if let TokenKind::Ident(symbol, _) = &self.prev_token.kind {
            if ["def", "fun", "func", "function"].contains(&symbol.as_str()) {
                err.span_suggestion_short(
                    self.prev_token.span,
                    format!("write `fn` instead of `{symbol}` to declare a function"),
                    "fn",
                    Applicability::MachineApplicable,
                );
            }
        }

        if let TokenKind::Ident(prev, _) = &self.prev_token.kind
            && let TokenKind::Ident(cur, _) = &self.token.kind
        {
            let concat = Symbol::intern(&format!("{prev}{cur}"));
            let ident = Ident::new(concat, DUMMY_SP);
            if ident.is_used_keyword() || ident.is_reserved() || ident.is_raw_guess() {
                let concat_span = self.prev_token.span.to(self.token.span);
                err.span_suggestion_verbose(
                    concat_span,
                    format!("consider removing the space to spell keyword `{concat}`"),
                    concat,
                    Applicability::MachineApplicable,
                );
            }
        }

        // Try to detect an intended c-string literal while using a pre-2021 edition. The heuristic
        // here is to identify a cooked, uninterpolated `c` id immediately followed by a string, or
        // a cooked, uninterpolated `cr` id immediately followed by a string or a `#`, in an edition
        // where c-string literals are not allowed. There is the very slight possibility of a false
        // positive for a `cr#` that wasn't intended to start a c-string literal, but identifying
        // that in the parser requires unbounded lookahead, so we only add a hint to the existing
        // error rather than replacing it entirely.
        if ((self.prev_token == TokenKind::Ident(sym::c, IdentIsRaw::No)
            && matches!(&self.token.kind, TokenKind::Literal(token::Lit { kind: token::Str, .. })))
            || (self.prev_token == TokenKind::Ident(sym::cr, IdentIsRaw::No)
                && matches!(
                    &self.token.kind,
                    TokenKind::Literal(token::Lit { kind: token::Str, .. }) | token::Pound
                )))
            && self.prev_token.span.hi() == self.token.span.lo()
            && !self.token.span.at_least_rust_2021()
        {
            err.note("you may be trying to write a c-string literal");
            err.note("c-string literals require Rust 2021 or later");
            err.subdiagnostic(HelpUseLatestEdition::new());
        }

        // `pub` may be used for an item or `pub(crate)`
        if self.prev_token.is_ident_named(sym::public)
            && (self.token.can_begin_item() || self.token == TokenKind::OpenParen)
        {
            err.span_suggestion_short(
                self.prev_token.span,
                "write `pub` instead of `public` to make the item public",
                "pub",
                Applicability::MachineApplicable,
            );
        }

        if let token::DocComment(kind, style, _) = self.token.kind {
            // This is to avoid suggesting converting a doc comment to a regular comment
            // when missing a comma before the doc comment in lists (#142311):
            //
            // ```
            // enum Foo{
            //     A /// xxxxxxx
            //     B,
            // }
            // ```
            if !expected.contains(&TokenType::Comma) {
                // We have something like `expr //!val` where the user likely meant `expr // !val`
                let pos = self.token.span.lo() + BytePos(2);
                let span = self.token.span.with_lo(pos).with_hi(pos);
                err.span_suggestion_verbose(
                    span,
                    format!(
                        "add a space before {} to write a regular comment",
                        match (kind, style) {
                            (token::CommentKind::Line, ast::AttrStyle::Inner) => "`!`",
                            (token::CommentKind::Block, ast::AttrStyle::Inner) => "`!`",
                            (token::CommentKind::Line, ast::AttrStyle::Outer) => "the last `/`",
                            (token::CommentKind::Block, ast::AttrStyle::Outer) => "the last `*`",
                        },
                    ),
                    " ".to_string(),
                    Applicability::MaybeIncorrect,
                );
            }
        }

        let sp = if self.token == token::Eof {
            // This is EOF; don't want to point at the following char, but rather the last token.
            self.prev_token.span
        } else {
            label_sp
        };

        if self.check_too_many_raw_str_terminators(&mut err) {
            if expected.contains(&TokenType::Semi) && self.eat(exp!(Semi)) {
                let guar = err.emit();
                return Ok(guar);
            } else {
                return Err(err);
            }
        }

        if self.prev_token.span == DUMMY_SP {
            // Account for macro context where the previous span might not be
            // available to avoid incorrect output (#54841).
            err.span_label(self.token.span, label_exp);
        } else if !sm.is_multiline(self.token.span.shrink_to_hi().until(sp.shrink_to_lo())) {
            // When the spans are in the same line, it means that the only content between
            // them is whitespace, point at the found token in that case:
            //
            // X |     () => { syntax error };
            //   |                    ^^^^^ expected one of 8 possible tokens here
            //
            // instead of having:
            //
            // X |     () => { syntax error };
            //   |                   -^^^^^ unexpected token
            //   |                   |
            //   |                   expected one of 8 possible tokens here
            err.span_label(self.token.span, label_exp);
        } else {
            err.span_label(sp, label_exp);
            err.span_label(self.token.span, "unexpected token");
        }

        // Check for misspelled keywords if there are no suggestions added to the diagnostic.
        if let Suggestions::Enabled(list) = &err.suggestions
            && list.is_empty()
        {
            self.check_for_misspelled_kw(&mut err, &expected);
        }
        Err(err)
    }

    /// Adds a label when `&raw EXPR` was written instead of `&raw const EXPR`/`&raw mut EXPR`.
    ///
    /// Given that not all parser diagnostics flow through `expected_one_of_not_found`, this
    /// label may need added to other diagnostics emission paths as needed.
    pub(super) fn label_expected_raw_ref(&mut self, err: &mut Diag<'_>) {
        if self.prev_token.is_keyword(kw::Raw)
            && self.expected_token_types.contains(TokenType::KwMut)
            && self.expected_token_types.contains(TokenType::KwConst)
            && self.token.can_begin_expr()
        {
            err.span_suggestions(
                self.prev_token.span.shrink_to_hi(),
                "`&raw` must be followed by `const` or `mut` to be a raw reference expression",
                [" const".to_string(), " mut".to_string()],
                Applicability::MaybeIncorrect,
            );
        }
    }

    /// Checks if the current token or the previous token are misspelled keywords
    /// and adds a helpful suggestion.
    fn check_for_misspelled_kw(&self, err: &mut Diag<'_>, expected: &[TokenType]) {
        let Some((curr_ident, _)) = self.token.ident() else {
            return;
        };
        let expected_token_types: &[TokenType] =
            expected.len().checked_sub(10).map_or(&expected, |index| &expected[index..]);
        let expected_keywords: Vec<Symbol> =
            expected_token_types.iter().filter_map(|token| token.is_keyword()).collect();

        // When there are a few keywords in the last ten elements of `self.expected_token_types`
        // and the current token is an identifier, it's probably a misspelled keyword. This handles
        // code like `async Move {}`, misspelled `if` in match guard, misspelled `else` in
        // `if`-`else` and misspelled `where` in a where clause.
        if !expected_keywords.is_empty()
            && !curr_ident.is_used_keyword()
            && let Some(misspelled_kw) = find_similar_kw(curr_ident, &expected_keywords)
        {
            err.subdiagnostic(misspelled_kw);
            // We don't want other suggestions to be added as they are most likely meaningless
            // when there is a misspelled keyword.
            err.seal_suggestions();
        } else if let Some((prev_ident, _)) = self.prev_token.ident()
            && !prev_ident.is_used_keyword()
        {
            // We generate a list of all keywords at runtime rather than at compile time
            // so that it gets generated only when the diagnostic needs it.
            // Also, it is unlikely that this list is generated multiple times because the
            // parser halts after execution hits this path.
            let all_keywords = used_keywords(|| prev_ident.span.edition());

            // Otherwise, check the previous token with all the keywords as possible candidates.
            // This handles code like `Struct Human;` and `While a < b {}`.
            // We check the previous token only when the current token is an identifier to avoid
            // false positives like suggesting keyword `for` for `extern crate foo {}`.
            if let Some(misspelled_kw) = find_similar_kw(prev_ident, &all_keywords) {
                err.subdiagnostic(misspelled_kw);
                // We don't want other suggestions to be added as they are most likely meaningless
                // when there is a misspelled keyword.
                err.seal_suggestions();
            }
        }
    }

    /// The user has written `#[attr] expr` which is unsupported. (#106020)
    pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) -> ErrorGuaranteed {
        // Missing semicolon typo error.
        let span = self.prev_token.span.shrink_to_hi();
        let mut err = self.dcx().create_err(ExpectedSemi {
            span,
            token: self.token,
            unexpected_token_label: Some(self.token.span),
            sugg: ExpectedSemiSugg::AddSemi(span),
        });
        let attr_span = match &expr.attrs[..] {
            [] => unreachable!(),
            [only] => only.span,
            [first, rest @ ..] => {
                for attr in rest {
                    err.span_label(attr.span, "");
                }
                first.span
            }
        };
        err.span_label(
            attr_span,
            format!(
                "only `;` terminated statements or tail expressions are allowed after {}",
                if expr.attrs.len() == 1 { "this attribute" } else { "these attributes" },
            ),
        );
        if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
            // We have
            // #[attr]
            // expr
            // #[not_attr]
            // other_expr
            err.span_label(span, "expected `;` here");
            err.multipart_suggestion(
                "alternatively, consider surrounding the expression with a block",
                vec![
                    (expr.span.shrink_to_lo(), "{ ".to_string()),
                    (expr.span.shrink_to_hi(), " }".to_string()),
                ],
                Applicability::MachineApplicable,
            );

            // Special handling for `#[cfg(...)]` chains
            let mut snapshot = self.create_snapshot_for_diagnostic();
            if let [attr] = &expr.attrs[..]
                && let ast::AttrKind::Normal(attr_kind) = &attr.kind
                && let [segment] = &attr_kind.item.path.segments[..]
                && segment.ident.name == sym::cfg
                && let Some(args_span) = attr_kind.item.args.span()
                && let next_attr = match snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None))
                {
                    Ok(next_attr) => next_attr,
                    Err(inner_err) => {
                        inner_err.cancel();
                        return err.emit();
                    }
                }
                && let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind
                && let Some(next_attr_args_span) = next_attr_kind.item.args.span()
                && let [next_segment] = &next_attr_kind.item.path.segments[..]
                && segment.ident.name == sym::cfg
            {
                let next_expr = match snapshot.parse_expr() {
                    Ok(next_expr) => next_expr,
                    Err(inner_err) => {
                        inner_err.cancel();
                        return err.emit();
                    }
                };
                // We have for sure
                // #[cfg(..)]
                // expr
                // #[cfg(..)]
                // other_expr
                // So we suggest using `if cfg!(..) { expr } else if cfg!(..) { other_expr }`.
                let margin = self.psess.source_map().span_to_margin(next_expr.span).unwrap_or(0);
                let sugg = vec![
                    (attr.span.with_hi(segment.span().hi()), "if cfg!".to_string()),
                    (args_span.shrink_to_hi().with_hi(attr.span.hi()), " {".to_string()),
                    (expr.span.shrink_to_lo(), "    ".to_string()),
                    (
                        next_attr.span.with_hi(next_segment.span().hi()),
                        "} else if cfg!".to_string(),
                    ),
                    (
                        next_attr_args_span.shrink_to_hi().with_hi(next_attr.span.hi()),
                        " {".to_string(),
                    ),
                    (next_expr.span.shrink_to_lo(), "    ".to_string()),
                    (next_expr.span.shrink_to_hi(), format!("\n{}}}", " ".repeat(margin))),
                ];
                err.multipart_suggestion(
                    "it seems like you are trying to provide different expressions depending on \
                     `cfg`, consider using `if cfg!(..)`",
                    sugg,
                    Applicability::MachineApplicable,
                );
            }
        }

        err.emit()
    }

    fn check_too_many_raw_str_terminators(&mut self, err: &mut Diag<'_>) -> bool {
        let sm = self.psess.source_map();
        match (&self.prev_token.kind, &self.token.kind) {
            (
                TokenKind::Literal(Lit {
                    kind: LitKind::StrRaw(n_hashes) | LitKind::ByteStrRaw(n_hashes),
                    ..
                }),
                TokenKind::Pound,
            ) if !sm.is_multiline(
                self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo()),
            ) =>
            {
                let n_hashes: u8 = *n_hashes;
                err.primary_message("too many `#` when terminating raw string");
                let str_span = self.prev_token.span;
                let mut span = self.token.span;
                let mut count = 0;
                while self.token == TokenKind::Pound
                    && !sm.is_multiline(span.shrink_to_hi().until(self.token.span.shrink_to_lo()))
                {
                    span = span.with_hi(self.token.span.hi());
                    self.bump();
                    count += 1;
                }
                err.span(span);
                err.span_suggestion(
                    span,
                    format!("remove the extra `#`{}", pluralize!(count)),
                    "",
                    Applicability::MachineApplicable,
                );
                err.span_label(
                    str_span,
                    format!("this raw string started with {n_hashes} `#`{}", pluralize!(n_hashes)),
                );
                true
            }
            _ => false,
        }
    }

    pub(super) fn maybe_suggest_struct_literal(
        &mut self,
        lo: Span,
        s: BlockCheckMode,
        maybe_struct_name: token::Token,
    ) -> Option<PResult<'a, Box<Block>>> {
        if self.token.is_ident() && self.look_ahead(1, |t| t == &token::Colon) {
            // We might be having a struct literal where people forgot to include the path:
            // fn foo() -> Foo {
            //     field: value,
            // }
            debug!(?maybe_struct_name, ?self.token);
            let mut snapshot = self.create_snapshot_for_diagnostic();
            let path = Path {
                segments: ThinVec::new(),
                span: self.prev_token.span.shrink_to_lo(),
                tokens: None,
            };
            let struct_expr = snapshot.parse_expr_struct(None, path, false);
            let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
            return Some(match (struct_expr, block_tail) {
                (Ok(expr), Err(err)) => {
                    // We have encountered the following:
                    // fn foo() -> Foo {
                    //     field: value,
                    // }
                    // Suggest:
                    // fn foo() -> Foo { Path {
                    //     field: value,
                    // } }
                    err.cancel();
                    self.restore_snapshot(snapshot);
                    let guar = self.dcx().emit_err(StructLiteralBodyWithoutPath {
                        span: expr.span,
                        sugg: StructLiteralBodyWithoutPathSugg {
                            before: expr.span.shrink_to_lo(),
                            after: expr.span.shrink_to_hi(),
                        },
                    });
                    Ok(self.mk_block(
                        thin_vec![self.mk_stmt_err(expr.span, guar)],
                        s,
                        lo.to(self.prev_token.span),
                    ))
                }
                (Err(err), Ok(tail)) => {
                    // We have a block tail that contains a somehow valid expr.
                    err.cancel();
                    Ok(tail)
                }
                (Err(snapshot_err), Err(err)) => {
                    // We don't know what went wrong, emit the normal error.
                    snapshot_err.cancel();
                    self.consume_block(exp!(OpenBrace), exp!(CloseBrace), ConsumeClosingDelim::Yes);
                    Err(err)
                }
                (Ok(_), Ok(tail)) => Ok(tail),
            });
        }
        None
    }

    pub(super) fn recover_closure_body(
        &mut self,
        mut err: Diag<'a>,
        before: token::Token,
        prev: token::Token,
        token: token::Token,
        lo: Span,
        decl_hi: Span,
    ) -> PResult<'a, Box<Expr>> {
        err.span_label(lo.to(decl_hi), "while parsing the body of this closure");
        let guar = match before.kind {
            token::OpenBrace if token.kind != token::OpenBrace => {
                // `{ || () }` should have been `|| { () }`
                err.multipart_suggestion(
                    "you might have meant to open the body of the closure, instead of enclosing \
                     the closure in a block",
                    vec![
                        (before.span, String::new()),
                        (prev.span.shrink_to_hi(), " {".to_string()),
                    ],
                    Applicability::MaybeIncorrect,
                );
                let guar = err.emit();
                self.eat_to_tokens(&[exp!(CloseBrace)]);
                guar
            }
            token::OpenParen if token.kind != token::OpenBrace => {
                // We are within a function call or tuple, we can emit the error
                // and recover.
                self.eat_to_tokens(&[exp!(CloseParen), exp!(Comma)]);

                err.multipart_suggestion_verbose(
                    "you might have meant to open the body of the closure",
                    vec![
                        (prev.span.shrink_to_hi(), " {".to_string()),
                        (self.token.span.shrink_to_lo(), "}".to_string()),
                    ],
                    Applicability::MaybeIncorrect,
                );
                err.emit()
            }
            _ if token.kind != token::OpenBrace => {
                // We don't have a heuristic to correctly identify where the block
                // should be closed.
                err.multipart_suggestion_verbose(
                    "you might have meant to open the body of the closure",
                    vec![(prev.span.shrink_to_hi(), " {".to_string())],
                    Applicability::HasPlaceholders,
                );
                return Err(err);
            }
            _ => return Err(err),
        };
        Ok(self.mk_expr_err(lo.to(self.token.span), guar))
    }

    /// Eats and discards tokens until one of `closes` is encountered. Respects token trees,
    /// passes through any errors encountered. Used for error recovery.
    pub(super) fn eat_to_tokens(&mut self, closes: &[ExpTokenPair]) {
        if let Err(err) = self
            .parse_seq_to_before_tokens(closes, &[], SeqSep::none(), |p| Ok(p.parse_token_tree()))
        {
            err.cancel();
        }
    }

    /// This function checks if there are trailing angle brackets and produces
    /// a diagnostic to suggest removing them.
    ///
    /// ```ignore (diagnostic)
    /// let _ = [1, 2, 3].into_iter().collect::<Vec<usize>>>>();
    ///                                                    ^^ help: remove extra angle brackets
    /// ```
    ///
    /// If `true` is returned, then trailing brackets were recovered, tokens were consumed
    /// up until one of the tokens in 'end' was encountered, and an error was emitted.
    pub(super) fn check_trailing_angle_brackets(
        &mut self,
        segment: &PathSegment,
        end: &[ExpTokenPair],
    ) -> Option<ErrorGuaranteed> {
        if !self.may_recover() {
            return None;
        }

        // This function is intended to be invoked after parsing a path segment where there are two
        // cases:
        //
        // 1. A specific token is expected after the path segment.
        //    eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call),
        //        `Foo::`, or `Foo::<Bar>::` (mod sep - continued path).
        // 2. No specific token is expected after the path segment.
        //    eg. `x.foo` (field access)
        //
        // This function is called after parsing `.foo` and before parsing the token `end` (if
        // present). This includes any angle bracket arguments, such as `.foo::<u32>` or
        // `Foo::<Bar>`.

        // We only care about trailing angle brackets if we previously parsed angle bracket
        // arguments. This helps stop us incorrectly suggesting that extra angle brackets be
        // removed in this case:
        //
        // `x.foo >> (3)` (where `x.foo` is a `u32` for example)
        //
        // This case is particularly tricky as we won't notice it just looking at the tokens -
        // it will appear the same (in terms of upcoming tokens) as below (since the `::<u32>` will
        // have already been parsed):
        //
        // `x.foo::<u32>>>(3)`
        let parsed_angle_bracket_args =
            segment.args.as_ref().is_some_and(|args| args.is_angle_bracketed());

        debug!(
            "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
            parsed_angle_bracket_args,
        );
        if !parsed_angle_bracket_args {
            return None;
        }

        // Keep the span at the start so we can highlight the sequence of `>` characters to be
        // removed.
        let lo = self.token.span;

        // We need to look-ahead to see if we have `>` characters without moving the cursor forward
        // (since we might have the field access case and the characters we're eating are
        // actual operators and not trailing characters - ie `x.foo >> 3`).
        let mut position = 0;

        // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how
        // many of each (so we can correctly pluralize our error messages) and continue to
        // advance.
        let mut number_of_shr = 0;
        let mut number_of_gt = 0;
        while self.look_ahead(position, |t| {
            trace!("check_trailing_angle_brackets: t={:?}", t);
            if *t == token::Shr {
                number_of_shr += 1;
                true
            } else if *t == token::Gt {
                number_of_gt += 1;
                true
            } else {
                false
            }
        }) {
            position += 1;
        }

        // If we didn't find any trailing `>` characters, then we have nothing to error about.
        debug!(
            "check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}",
            number_of_gt, number_of_shr,
        );
        if number_of_gt < 1 && number_of_shr < 1 {
            return None;
        }

        // Finally, double check that we have our end token as otherwise this is the
        // second case.
        if self.look_ahead(position, |t| {
            trace!("check_trailing_angle_brackets: t={:?}", t);
            end.iter().any(|exp| exp.tok == t.kind)
        }) {
            // Eat from where we started until the end token so that parsing can continue
            // as if we didn't have those extra angle brackets.
            self.eat_to_tokens(end);
            let span = lo.to(self.prev_token.span);

            let num_extra_brackets = number_of_gt + number_of_shr * 2;
            return Some(self.dcx().emit_err(UnmatchedAngleBrackets { span, num_extra_brackets }));
        }
        None
    }

    /// Check if a method call with an intended turbofish has been written without surrounding
    /// angle brackets.
    pub(super) fn check_turbofish_missing_angle_brackets(&mut self, segment: &mut PathSegment) {
        if !self.may_recover() {
            return;
        }

        if self.token == token::PathSep && segment.args.is_none() {
            let snapshot = self.create_snapshot_for_diagnostic();
            self.bump();
            let lo = self.token.span;
            match self.parse_angle_args(None) {
                Ok(args) => {
                    let span = lo.to(self.prev_token.span);
                    // Detect trailing `>` like in `x.collect::Vec<_>>()`.
                    let mut trailing_span = self.prev_token.span.shrink_to_hi();
                    while self.token == token::Shr || self.token == token::Gt {
                        trailing_span = trailing_span.to(self.token.span);
                        self.bump();
                    }
                    if self.token == token::OpenParen {
                        // Recover from bad turbofish: `foo.collect::Vec<_>()`.
                        segment.args = Some(AngleBracketedArgs { args, span }.into());

                        self.dcx().emit_err(GenericParamsWithoutAngleBrackets {
                            span,
                            sugg: GenericParamsWithoutAngleBracketsSugg {
                                left: span.shrink_to_lo(),
                                right: trailing_span,
                            },
                        });
                    } else {
                        // This doesn't look like an invalid turbofish, can't recover parse state.
                        self.restore_snapshot(snapshot);
                    }
                }
                Err(err) => {
                    // We couldn't parse generic parameters, unlikely to be a turbofish. Rely on
                    // generic parse error instead.
                    err.cancel();
                    self.restore_snapshot(snapshot);
                }
            }
        }
    }

    /// When writing a turbofish with multiple type parameters missing the leading `::`, we will
    /// encounter a parse error when encountering the first `,`.
    pub(super) fn check_mistyped_turbofish_with_multiple_type_params(
        &mut self,
        mut e: Diag<'a>,
        expr: &mut Box<Expr>,
    ) -> PResult<'a, ErrorGuaranteed> {
        if let ExprKind::Binary(binop, _, _) = &expr.kind
            && let ast::BinOpKind::Lt = binop.node
            && self.eat(exp!(Comma))
        {
            let x = self.parse_seq_to_before_end(
                exp!(Gt),
                SeqSep::trailing_allowed(exp!(Comma)),
                |p| match p.parse_generic_arg(None)? {
                    Some(arg) => Ok(arg),
                    // If we didn't eat a generic arg, then we should error.
                    None => p.unexpected_any(),
                },
            );
            match x {
                Ok((_, _, Recovered::No)) => {
                    if self.eat(exp!(Gt)) {
                        // We made sense of it. Improve the error message.
                        e.span_suggestion_verbose(
                            binop.span.shrink_to_lo(),
                            inline_fluent!("use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments"),
                            "::",
                            Applicability::MaybeIncorrect,
                        );
                        match self.parse_expr() {
                            Ok(_) => {
                                // The subsequent expression is valid. Mark
                                // `expr` as erroneous and emit `e` now, but
                                // return `Ok` so parsing can continue.
                                let guar = e.emit();
                                *expr = self.mk_expr_err(expr.span.to(self.prev_token.span), guar);
                                return Ok(guar);
                            }
                            Err(err) => {
                                err.cancel();
                            }
                        }
                    }
                }
                Ok((_, _, Recovered::Yes(_))) => {}
                Err(err) => {
                    err.cancel();
                }
            }
        }
        Err(e)
    }

    /// Suggest add the missing `let` before the identifier in stmt
    /// `a: Ty = 1` -> `let a: Ty = 1`
    pub(super) fn suggest_add_missing_let_for_stmt(&mut self, err: &mut Diag<'a>) {
        if self.token == token::Colon {
            let prev_span = self.prev_token.span.shrink_to_lo();
            let snapshot = self.create_snapshot_for_diagnostic();
            self.bump();
            match self.parse_ty() {
                Ok(_) => {
                    if self.token == token::Eq {
                        let sugg = SuggAddMissingLetStmt { span: prev_span };
                        sugg.add_to_diag(err);
                    }
                }
                Err(e) => {
                    e.cancel();
                }
            }
            self.restore_snapshot(snapshot);
        }
    }

    /// Check to see if a pair of chained operators looks like an attempt at chained comparison,
    /// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or
    /// parenthesising the leftmost comparison. The return value indicates if recovery happened.
    fn attempt_chained_comparison_suggestion(
        &mut self,
        err: &mut ComparisonOperatorsCannotBeChained,
        inner_op: &Expr,
        outer_op: &Spanned<AssocOp>,
    ) -> bool {
        if let ExprKind::Binary(op, l1, r1) = &inner_op.kind {
            if let ExprKind::Field(_, ident) = l1.kind
                && !ident.is_numeric()
                && !matches!(r1.kind, ExprKind::Lit(_))
            {
                // The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
                // suggestion being the only one to apply is high.
                return false;
            }
            return match (op.node, &outer_op.node) {
                // `x == y == z`
                (BinOpKind::Eq, AssocOp::Binary(BinOpKind::Eq)) |
                // `x < y < z` and friends.
                (BinOpKind::Lt, AssocOp::Binary(BinOpKind::Lt | BinOpKind::Le)) |
                (BinOpKind::Le, AssocOp::Binary(BinOpKind::Lt | BinOpKind::Le)) |
                // `x > y > z` and friends.
                (BinOpKind::Gt, AssocOp::Binary(BinOpKind::Gt | BinOpKind::Ge)) |
                (BinOpKind::Ge, AssocOp::Binary(BinOpKind::Gt | BinOpKind::Ge)) => {
                    let expr_to_str = |e: &Expr| {
                        self.span_to_snippet(e.span)
                            .unwrap_or_else(|_| pprust::expr_to_string(e))
                    };
                    err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::SplitComparison {
                        span: inner_op.span.shrink_to_hi(),
                        middle_term: expr_to_str(r1),
                    });
                    false // Keep the current parse behavior, where the AST is `(x < y) < z`.
                }
                // `x == y < z`
                (
                    BinOpKind::Eq,
                    AssocOp::Binary(BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge)
                ) => {
                    // Consume `z`/outer-op-rhs.
                    let snapshot = self.create_snapshot_for_diagnostic();
                    match self.parse_expr() {
                        Ok(r2) => {
                            // We are sure that outer-op-rhs could be consumed, the suggestion is
                            // likely correct.
                            err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize {
                                left: r1.span.shrink_to_lo(),
                                right: r2.span.shrink_to_hi(),
                            });
                            true
                        }
                        Err(expr_err) => {
                            expr_err.cancel();
                            self.restore_snapshot(snapshot);
                            true
                        }
                    }
                }
                // `x > y == z`
                (
                    BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge,
                    AssocOp::Binary(BinOpKind::Eq)
                ) => {
                    let snapshot = self.create_snapshot_for_diagnostic();
                    // At this point it is always valid to enclose the lhs in parentheses, no
                    // further checks are necessary.
                    match self.parse_expr() {
                        Ok(_) => {
                            err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize {
                                left: l1.span.shrink_to_lo(),
                                right: r1.span.shrink_to_hi(),
                            });
                            true
                        }
                        Err(expr_err) => {
                            expr_err.cancel();
                            self.restore_snapshot(snapshot);
                            false
                        }
                    }
                }
                _ => false
            };
        }
        false
    }

    /// Produces an error if comparison operators are chained (RFC #558).
    /// We only need to check the LHS, not the RHS, because all comparison ops have same
    /// precedence (see `fn precedence`) and are left-associative (see `fn fixity`).
    ///
    /// This can also be hit if someone incorrectly writes `foo<bar>()` when they should have used
    /// the turbofish (`foo::<bar>()`) syntax. We attempt some heuristic recovery if that is the
    /// case.
    ///
    /// Keep in mind that given that `outer_op.is_comparison()` holds and comparison ops are left
    /// associative we can infer that we have:
    ///
    /// ```text
    ///           outer_op
    ///           /   \
    ///     inner_op   r2
    ///        /  \
    ///      l1    r1
    /// ```
    pub(super) fn check_no_chained_comparison(
        &mut self,
        inner_op: &Expr,
        outer_op: &Spanned<AssocOp>,
    ) -> PResult<'a, Option<Box<Expr>>> {
        debug_assert!(
            outer_op.node.is_comparison(),
            "check_no_chained_comparison: {:?} is not comparison",
            outer_op.node,
        );

        let mk_err_expr =
            |this: &Self, span, guar| Ok(Some(this.mk_expr(span, ExprKind::Err(guar))));

        match &inner_op.kind {
            ExprKind::Binary(op, l1, r1) if op.node.is_comparison() => {
                let mut err = ComparisonOperatorsCannotBeChained {
                    span: vec![op.span, self.prev_token.span],
                    suggest_turbofish: None,
                    help_turbofish: false,
                    chaining_sugg: None,
                };

                // Include `<` to provide this recommendation even in a case like
                // `Foo<Bar<Baz<Qux, ()>>>`
                if op.node == BinOpKind::Lt && outer_op.node == AssocOp::Binary(BinOpKind::Lt)
                    || outer_op.node == AssocOp::Binary(BinOpKind::Gt)
                {
                    if outer_op.node == AssocOp::Binary(BinOpKind::Lt) {
                        let snapshot = self.create_snapshot_for_diagnostic();
                        self.bump();
                        // So far we have parsed `foo<bar<`, consume the rest of the type args.
                        let modifiers = [(token::Lt, 1), (token::Gt, -1), (token::Shr, -2)];
                        self.consume_tts(1, &modifiers);

                        if !matches!(self.token.kind, token::OpenParen | token::PathSep) {
                            // We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the
                            // parser and bail out.
                            self.restore_snapshot(snapshot);
                        }
                    }
                    return if self.token == token::PathSep {
                        // We have some certainty that this was a bad turbofish at this point.
                        // `foo< bar >::`
                        if let ExprKind::Binary(o, ..) = inner_op.kind
                            && o.node == BinOpKind::Lt
                        {
                            err.suggest_turbofish = Some(op.span.shrink_to_lo());
                        } else {
                            err.help_turbofish = true;
                        }

                        let snapshot = self.create_snapshot_for_diagnostic();
                        self.bump(); // `::`

                        // Consume the rest of the likely `foo<bar>::new()` or return at `foo<bar>`.
                        match self.parse_expr() {
                            Ok(_) => {
                                // 99% certain that the suggestion is correct, continue parsing.
                                let guar = self.dcx().emit_err(err);
                                // FIXME: actually check that the two expressions in the binop are
                                // paths and resynthesize new fn call expression instead of using
                                // `ExprKind::Err` placeholder.
                                mk_err_expr(self, inner_op.span.to(self.prev_token.span), guar)
                            }
                            Err(expr_err) => {
                                expr_err.cancel();
                                // Not entirely sure now, but we bubble the error up with the
                                // suggestion.
                                self.restore_snapshot(snapshot);
                                Err(self.dcx().create_err(err))
                            }
                        }
                    } else if self.token == token::OpenParen {
                        // We have high certainty that this was a bad turbofish at this point.
                        // `foo< bar >(`
                        if let ExprKind::Binary(o, ..) = inner_op.kind
                            && o.node == BinOpKind::Lt
                        {
                            err.suggest_turbofish = Some(op.span.shrink_to_lo());
                        } else {
                            err.help_turbofish = true;
                        }
                        // Consume the fn call arguments.
                        match self.consume_fn_args() {
                            Err(()) => Err(self.dcx().create_err(err)),
                            Ok(()) => {
                                let guar = self.dcx().emit_err(err);
                                // FIXME: actually check that the two expressions in the binop are
                                // paths and resynthesize new fn call expression instead of using
                                // `ExprKind::Err` placeholder.
                                mk_err_expr(self, inner_op.span.to(self.prev_token.span), guar)
                            }
                        }
                    } else {
                        if !matches!(l1.kind, ExprKind::Lit(_))
                            && !matches!(r1.kind, ExprKind::Lit(_))
                        {
                            // All we know is that this is `foo < bar >` and *nothing* else. Try to
                            // be helpful, but don't attempt to recover.
                            err.help_turbofish = true;
                        }

                        // If it looks like a genuine attempt to chain operators (as opposed to a
                        // misformatted turbofish, for instance), suggest a correct form.
                        let recovered = self
                            .attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op);
                        if recovered {
                            let guar = self.dcx().emit_err(err);
                            mk_err_expr(self, inner_op.span.to(self.prev_token.span), guar)
                        } else {
                            // These cases cause too many knock-down errors, bail out (#61329).
                            Err(self.dcx().create_err(err))
                        }
                    };
                }
                let recovered =
                    self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op);
                let guar = self.dcx().emit_err(err);
                if recovered {
                    return mk_err_expr(self, inner_op.span.to(self.prev_token.span), guar);
                }
            }
            _ => {}
        }
        Ok(None)
    }

    fn consume_fn_args(&mut self) -> Result<(), ()> {
        let snapshot = self.create_snapshot_for_diagnostic();
        self.bump(); // `(`

        // Consume the fn call arguments.
        let modifiers = [(token::OpenParen, 1), (token::CloseParen, -1)];
        self.consume_tts(1, &modifiers);

        if self.token == token::Eof {
            // Not entirely sure that what we consumed were fn arguments, rollback.
            self.restore_snapshot(snapshot);
            Err(())
        } else {
            // 99% certain that the suggestion is correct, continue parsing.
            Ok(())
        }
    }

    pub(super) fn maybe_report_ambiguous_plus(&mut self, impl_dyn_multi: bool, ty: &Ty) {
        if impl_dyn_multi {
            self.dcx().emit_err(AmbiguousPlus {
                span: ty.span,
                suggestion: AddParen { lo: ty.span.shrink_to_lo(), hi: ty.span.shrink_to_hi() },
            });
        }
    }

    /// Swift lets users write `Ty?` to mean `Option<Ty>`. Parse the construct and recover from it.
    pub(super) fn maybe_recover_from_question_mark(&mut self, ty: Box<Ty>) -> Box<Ty> {
        if self.token == token::Question {
            self.bump();
            let guar = self.dcx().emit_err(QuestionMarkInType {
                span: self.prev_token.span,
                sugg: QuestionMarkInTypeSugg {
                    left: ty.span.shrink_to_lo(),
                    right: self.prev_token.span,
                },
            });
            self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err(guar))
        } else {
            ty
        }
    }

    /// Rust has no ternary operator (`cond ? then : else`). Parse it and try
    /// to recover from it if `then` and `else` are valid expressions. Returns
    /// an err if this appears to be a ternary expression.
    /// If we have the span of the condition, we can provide a better error span
    /// and code suggestion.
    pub(super) fn maybe_recover_from_ternary_operator(
        &mut self,
        cond: Option<Span>,
    ) -> PResult<'a, ()> {
        if self.prev_token != token::Question {
            return PResult::Ok(());
        }

        let question = self.prev_token.span;
        let lo = cond.unwrap_or(question).lo();
        let snapshot = self.create_snapshot_for_diagnostic();

        if match self.parse_expr() {
            Ok(_) => true,
            Err(err) => {
                err.cancel();
                // The colon can sometimes be mistaken for type
                // ascription. Catch when this happens and continue.
                self.token == token::Colon
            }
        } {
            if self.eat_noexpect(&token::Colon) {
                let colon = self.prev_token.span;
                match self.parse_expr() {
                    Ok(expr) => {
                        let sugg = cond.map(|cond| TernaryOperatorSuggestion {
                            before_cond: cond.shrink_to_lo(),
                            question,
                            colon,
                            end: expr.span.shrink_to_hi(),
                        });
                        return Err(self.dcx().create_err(TernaryOperator {
                            span: self.prev_token.span.with_lo(lo),
                            sugg,
                            no_sugg: sugg.is_none(),
                        }));
                    }
                    Err(err) => {
                        err.cancel();
                    }
                };
            }
        }
        self.restore_snapshot(snapshot);
        Ok(())
    }

    pub(super) fn maybe_recover_from_bad_type_plus(&mut self, ty: &Ty) -> PResult<'a, ()> {
        // Do not add `+` to expected tokens.
        if !self.token.is_like_plus() {
            return Ok(());
        }

        self.bump(); // `+`
        let _bounds = self.parse_generic_bounds()?;
        let sub = match &ty.kind {
            TyKind::Ref(_lifetime, mut_ty) => {
                let lo = mut_ty.ty.span.shrink_to_lo();
                let hi = self.prev_token.span.shrink_to_hi();
                BadTypePlusSub::AddParen { suggestion: AddParen { lo, hi } }
            }
            TyKind::Ptr(..) | TyKind::FnPtr(..) => {
                BadTypePlusSub::ForgotParen { span: ty.span.to(self.prev_token.span) }
            }
            _ => BadTypePlusSub::ExpectPath { span: ty.span },
        };

        self.dcx().emit_err(BadTypePlus { span: ty.span, sub });

        Ok(())
    }

    pub(super) fn recover_from_prefix_increment(
        &mut self,
        operand_expr: Box<Expr>,
        op_span: Span,
        start_stmt: bool,
    ) -> PResult<'a, Box<Expr>> {
        let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr };
        let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre };
        self.recover_from_inc_dec(operand_expr, kind, op_span)
    }

    pub(super) fn recover_from_postfix_increment(
        &mut self,
        operand_expr: Box<Expr>,
        op_span: Span,
        start_stmt: bool,
    ) -> PResult<'a, Box<Expr>> {
        let kind = IncDecRecovery {
            standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
            op: IncOrDec::Inc,
            fixity: UnaryFixity::Post,
        };
        self.recover_from_inc_dec(operand_expr, kind, op_span)
    }

    pub(super) fn recover_from_postfix_decrement(
        &mut self,
        operand_expr: Box<Expr>,
        op_span: Span,
        start_stmt: bool,
    ) -> PResult<'a, Box<Expr>> {
        let kind = IncDecRecovery {
            standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
            op: IncOrDec::Dec,
            fixity: UnaryFixity::Post,
        };
        self.recover_from_inc_dec(operand_expr, kind, op_span)
    }

    fn recover_from_inc_dec(
        &mut self,
        base: Box<Expr>,
        kind: IncDecRecovery,
        op_span: Span,
    ) -> PResult<'a, Box<Expr>> {
        let mut err = self.dcx().struct_span_err(
            op_span,
            format!("Rust has no {} {} operator", kind.fixity, kind.op.name()),
        );
        err.span_label(op_span, format!("not a valid {} operator", kind.fixity));

        let help_base_case = |mut err: Diag<'_, _>, base| {
            err.help(format!("use `{}= 1` instead", kind.op.chr()));
            err.emit();
            Ok(base)
        };

        // (pre, post)
        let spans = match kind.fixity {
            UnaryFixity::Pre => (op_span, base.span.shrink_to_hi()),
            UnaryFixity::Post => (base.span.shrink_to_lo(), op_span),
        };

        match kind.standalone {
            IsStandalone::Standalone => {
                self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err)
            }
            IsStandalone::Subexpr => {
                let Ok(base_src) = self.span_to_snippet(base.span) else {
                    return help_base_case(err, base);
                };
                match kind.fixity {
                    UnaryFixity::Pre => {
                        self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
                    }
                    UnaryFixity::Post => {
                        // won't suggest since we can not handle the precedences
                        // for example: `a + b++` has been parsed (a + b)++ and we can not suggest here
                        if !matches!(base.kind, ExprKind::Binary(_, _, _)) {
                            self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
                        }
                    }
                }
            }
        }
        Err(err)
    }

    fn prefix_inc_dec_suggest(
        &mut self,
        base_src: String,
        kind: IncDecRecovery,
        (pre_span, post_span): (Span, Span),
    ) -> MultiSugg {
        MultiSugg {
            msg: format!("use `{}= 1` instead", kind.op.chr()),
            patches: vec![
                (pre_span, "{ ".to_string()),
                (post_span, format!(" {}= 1; {} }}", kind.op.chr(), base_src)),
            ],
            applicability: Applicability::MachineApplicable,
        }
    }

    fn postfix_inc_dec_suggest(
        &mut self,
        base_src: String,
        kind: IncDecRecovery,
        (pre_span, post_span): (Span, Span),
    ) -> MultiSugg {
        let tmp_var = if base_src.trim() == "tmp" { "tmp_" } else { "tmp" };
        MultiSugg {
            msg: format!("use `{}= 1` instead", kind.op.chr()),
            patches: vec![
                (pre_span, format!("{{ let {tmp_var} = ")),
                (post_span, format!("; {} {}= 1; {} }}", base_src, kind.op.chr(), tmp_var)),
            ],
            applicability: Applicability::HasPlaceholders,
        }
    }

    fn inc_dec_standalone_suggest(
        &mut self,
        kind: IncDecRecovery,
        (pre_span, post_span): (Span, Span),
    ) -> MultiSugg {
        let mut patches = Vec::new();

        if !pre_span.is_empty() {
            patches.push((pre_span, String::new()));
        }

        patches.push((post_span, format!(" {}= 1", kind.op.chr())));
        MultiSugg {
            msg: format!("use `{}= 1` instead", kind.op.chr()),
            patches,
            applicability: Applicability::MachineApplicable,
        }
    }

    /// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.
    /// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem`
    /// tail, and combines them into a `<Ty>::AssocItem` expression/pattern/type.
    pub(super) fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
        &mut self,
        base: T,
    ) -> PResult<'a, T> {
        // Do not add `::` to expected tokens.
        if self.may_recover() && self.token == token::PathSep {
            return self.recover_from_bad_qpath(base);
        }
        Ok(base)
    }

    #[cold]
    fn recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: T) -> PResult<'a, T> {
        if let Some(ty) = base.to_ty() {
            return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
        }
        Ok(base)
    }

    /// Given an already parsed `Ty`, parses the `::AssocItem` tail and
    /// combines them into a `<Ty>::AssocItem` expression/pattern/type.
    pub(super) fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(
        &mut self,
        ty_span: Span,
        ty: Box<Ty>,
    ) -> PResult<'a, T> {
        self.expect(exp!(PathSep))?;

        let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None };
        self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?;
        path.span = ty_span.to(self.prev_token.span);

        self.dcx().emit_err(BadQPathStage2 {
            span: ty_span,
            wrap: WrapType { lo: ty_span.shrink_to_lo(), hi: ty_span.shrink_to_hi() },
        });

        let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`.
        Ok(T::recovered(Some(Box::new(QSelf { ty, path_span, position: 0 })), path))
    }

    /// This function gets called in places where a semicolon is NOT expected and if there's a
    /// semicolon it emits the appropriate error and returns true.
    pub fn maybe_consume_incorrect_semicolon(&mut self, previous_item: Option<&Item>) -> bool {
        if self.token != TokenKind::Semi {
            return false;
        }

        // Check previous item to add it to the diagnostic, for example to say
        // `enum declarations are not followed by a semicolon`
        let err = match previous_item {
            Some(previous_item) => {
                let name = match previous_item.kind {
                    // Say "braced struct" because tuple-structs and
                    // braceless-empty-struct declarations do take a semicolon.
                    ItemKind::Struct(..) => "braced struct",
                    _ => previous_item.kind.descr(),
                };
                IncorrectSemicolon { span: self.token.span, name, show_help: true }
            }
            None => IncorrectSemicolon { span: self.token.span, name: "", show_help: false },
        };
        self.dcx().emit_err(err);

        self.bump();
        true
    }

    /// Creates a `Diag` for an unexpected token `t` and tries to recover if it is a
    /// closing delimiter.
    pub(super) fn unexpected_try_recover(&mut self, t: &TokenKind) -> PResult<'a, Recovered> {
        let token_str = pprust::token_kind_to_string(t);
        let this_token_str = super::token_descr(&self.token);
        let (prev_sp, sp) = match (&self.token.kind, self.subparser_name) {
            // Point at the end of the macro call when reaching end of macro arguments.
            (token::Eof, Some(_)) => {
                let sp = self.prev_token.span.shrink_to_hi();
                (sp, sp)
            }
            // We don't want to point at the following span after DUMMY_SP.
            // This happens when the parser finds an empty TokenStream.
            _ if self.prev_token.span == DUMMY_SP => (self.token.span, self.token.span),
            // EOF, don't want to point at the following char, but rather the last token.
            (token::Eof, None) => (self.prev_token.span, self.token.span),
            _ => (self.prev_token.span.shrink_to_hi(), self.token.span),
        };
        let msg = format!(
            "expected `{}`, found {}",
            token_str,
            match (&self.token.kind, self.subparser_name) {
                (token::Eof, Some(origin)) => format!("end of {origin}"),
                _ => this_token_str,
            },
        );
        let mut err = self.dcx().struct_span_err(sp, msg);
        let label_exp = format!("expected `{token_str}`");
        let sm = self.psess.source_map();
        if !sm.is_multiline(prev_sp.until(sp)) {
            // When the spans are in the same line, it means that the only content
            // between them is whitespace, point only at the found token.
            err.span_label(sp, label_exp);
        } else {
            err.span_label(prev_sp, label_exp);
            err.span_label(sp, "unexpected token");
        }
        Err(err)
    }

    pub(super) fn expect_semi(&mut self) -> PResult<'a, ()> {
        if self.eat(exp!(Semi)) || self.recover_colon_as_semi() {
            return Ok(());
        }
        self.expect(exp!(Semi)).map(drop) // Error unconditionally
    }

    pub(super) fn recover_colon_as_semi(&mut self) -> bool {
        let line_idx = |span: Span| {
            self.psess
                .source_map()
                .span_to_lines(span)
                .ok()
                .and_then(|lines| Some(lines.lines.get(0)?.line_index))
        };

        if self.may_recover()
            && self.token == token::Colon
            && self.look_ahead(1, |next| line_idx(self.token.span) < line_idx(next.span))
        {
            self.dcx().emit_err(ColonAsSemi { span: self.token.span });
            self.bump();
            return true;
        }

        false
    }

    /// Consumes alternative await syntaxes like `await!(<expr>)`, `await <expr>`,
    /// `await? <expr>`, `await(<expr>)`, and `await { <expr> }`.
    pub(super) fn recover_incorrect_await_syntax(
        &mut self,
        await_sp: Span,
    ) -> PResult<'a, Box<Expr>> {
        let (hi, expr, is_question) = if self.token == token::Bang {
            // Handle `await!(<expr>)`.
            self.recover_await_macro()?
        } else {
            self.recover_await_prefix(await_sp)?
        };
        let (sp, guar) = self.error_on_incorrect_await(await_sp, hi, &expr, is_question);
        let expr = self.mk_expr_err(await_sp.to(sp), guar);
        self.maybe_recover_from_bad_qpath(expr)
    }

    fn recover_await_macro(&mut self) -> PResult<'a, (Span, Box<Expr>, bool)> {
        self.expect(exp!(Bang))?;
        self.expect(exp!(OpenParen))?;
        let expr = self.parse_expr()?;
        self.expect(exp!(CloseParen))?;
        Ok((self.prev_token.span, expr, false))
    }

    fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, Box<Expr>, bool)> {
        let is_question = self.eat(exp!(Question)); // Handle `await? <expr>`.
        let expr = if self.token == token::OpenBrace {
            // Handle `await { <expr> }`.
            // This needs to be handled separately from the next arm to avoid
            // interpreting `await { <expr> }?` as `<expr>?.await`.
            self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)
        } else {
            self.parse_expr()
        }
        .map_err(|mut err| {
            err.span_label(await_sp, format!("while parsing this incorrect await expression"));
            err
        })?;
        Ok((expr.span, expr, is_question))
    }

    fn error_on_incorrect_await(
        &self,
        lo: Span,
        hi: Span,
        expr: &Expr,
        is_question: bool,
    ) -> (Span, ErrorGuaranteed) {
        let span = lo.to(hi);
        let guar = self.dcx().emit_err(IncorrectAwait {
            span,
            suggestion: AwaitSuggestion {
                removal: lo.until(expr.span),
                dot_await: expr.span.shrink_to_hi(),
                question_mark: if is_question { "?" } else { "" },
            },
        });
        (span, guar)
    }

    /// If encountering `future.await()`, consumes and emits an error.
    pub(super) fn recover_from_await_method_call(&mut self) {
        if self.token == token::OpenParen && self.look_ahead(1, |t| t == &token::CloseParen) {
            // future.await()
            let lo = self.token.span;
            self.bump(); // (
            let span = lo.to(self.token.span);
            self.bump(); // )

            self.dcx().emit_err(IncorrectUseOfAwait { span });
        }
    }
    ///
    /// If encountering `x.use()`, consumes and emits an error.
    pub(super) fn recover_from_use(&mut self) {
        if self.token == token::OpenParen && self.look_ahead(1, |t| t == &token::CloseParen) {
            // var.use()
            let lo = self.token.span;
            self.bump(); // (
            let span = lo.to(self.token.span);
            self.bump(); // )

            self.dcx().emit_err(IncorrectUseOfUse { span });
        }
    }

    pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, Box<Expr>> {
        let is_try = self.token.is_keyword(kw::Try);
        let is_questionmark = self.look_ahead(1, |t| t == &token::Bang); //check for !
        let is_open = self.look_ahead(2, |t| t == &token::OpenParen); //check for (

        if is_try && is_questionmark && is_open {
            let lo = self.token.span;
            self.bump(); //remove try
            self.bump(); //remove !
            let try_span = lo.to(self.token.span); //we take the try!( span
            self.bump(); //remove (
            let is_empty = self.token == token::CloseParen; //check if the block is empty
            self.consume_block(exp!(OpenParen), exp!(CloseParen), ConsumeClosingDelim::No); //eat the block
            let hi = self.token.span;
            self.bump(); //remove )
            let mut err = self.dcx().struct_span_err(lo.to(hi), "use of deprecated `try` macro");
            err.note("in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated");
            let prefix = if is_empty { "" } else { "alternatively, " };
            if !is_empty {
                err.multipart_suggestion(
                    "you can use the `?` operator instead",
                    vec![(try_span, "".to_owned()), (hi, "?".to_owned())],
                    Applicability::MachineApplicable,
                );
            }
            err.span_suggestion(lo.shrink_to_lo(), format!("{prefix}you can still access the deprecated `try!()` macro using the \"raw identifier\" syntax"), "r#", Applicability::MachineApplicable);
            let guar = err.emit();
            Ok(self.mk_expr_err(lo.to(hi), guar))
        } else {
            Err(self.expected_expression_found()) // The user isn't trying to invoke the try! macro
        }
    }

    /// When trying to close a generics list and encountering code like
    /// ```text
    /// impl<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical {}
    ///                                          // ^ missing > here
    /// ```
    /// we provide a structured suggestion on the error from `expect_gt`.
    pub(super) fn expect_gt_or_maybe_suggest_closing_generics(
        &mut self,
        params: &[ast::GenericParam],
    ) -> PResult<'a, ()> {
        let Err(mut err) = self.expect_gt() else {
            return Ok(());
        };
        // Attempt to find places where a missing `>` might belong.
        if let [.., ast::GenericParam { bounds, .. }] = params
            && let Some(poly) = bounds
                .iter()
                .filter_map(|bound| match bound {
                    ast::GenericBound::Trait(poly) => Some(poly),
                    _ => None,
                })
                .next_back()
        {
            err.span_suggestion_verbose(
                poly.span.shrink_to_hi(),
                "you might have meant to end the type parameters here",
                ">",
                Applicability::MaybeIncorrect,
            );
        }
        Err(err)
    }

    pub(super) fn recover_seq_parse_error(
        &mut self,
        open: ExpTokenPair,
        close: ExpTokenPair,
        lo: Span,
        err: Diag<'a>,
    ) -> Box<Expr> {
        let guar = err.emit();
        // Recover from parse error, callers expect the closing delim to be consumed.
        self.consume_block(open, close, ConsumeClosingDelim::Yes);
        self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err(guar))
    }

    /// Eats tokens until we can be relatively sure we reached the end of the
    /// statement. This is something of a best-effort heuristic.
    ///
    /// We terminate when we find an unmatched `}` (without consuming it).
    pub(super) fn recover_stmt(&mut self) {
        self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore)
    }

    /// If `break_on_semi` is `Break`, then we will stop consuming tokens after
    /// finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
    /// approximate -- it can mean we break too early due to macros, but that
    /// should only lead to sub-optimal recovery, not inaccurate parsing).
    ///
    /// If `break_on_block` is `Break`, then we will stop consuming tokens
    /// after finding (and consuming) a brace-delimited block.
    pub(super) fn recover_stmt_(
        &mut self,
        break_on_semi: SemiColonMode,
        break_on_block: BlockMode,
    ) {
        let mut brace_depth = 0;
        let mut bracket_depth = 0;
        let mut in_block = false;
        debug!("recover_stmt_ enter loop (semi={:?}, block={:?})", break_on_semi, break_on_block);
        loop {
            debug!("recover_stmt_ loop {:?}", self.token);
            match self.token.kind {
                token::OpenBrace => {
                    brace_depth += 1;
                    self.bump();
                    if break_on_block == BlockMode::Break && brace_depth == 1 && bracket_depth == 0
                    {
                        in_block = true;
                    }
                }
                token::OpenBracket => {
                    bracket_depth += 1;
                    self.bump();
                }
                token::CloseBrace => {
                    if brace_depth == 0 {
                        debug!("recover_stmt_ return - close delim {:?}", self.token);
                        break;
                    }
                    brace_depth -= 1;
                    self.bump();
                    if in_block && bracket_depth == 0 && brace_depth == 0 {
                        debug!("recover_stmt_ return - block end {:?}", self.token);
                        break;
                    }
                }
                token::CloseBracket => {
                    bracket_depth -= 1;
                    if bracket_depth < 0 {
                        bracket_depth = 0;
                    }
                    self.bump();
                }
                token::Eof => {
                    debug!("recover_stmt_ return - Eof");
                    break;
                }
                token::Semi => {
                    self.bump();
                    if break_on_semi == SemiColonMode::Break
                        && brace_depth == 0
                        && bracket_depth == 0
                    {
                        debug!("recover_stmt_ return - Semi");
                        break;
                    }
                }
                token::Comma
                    if break_on_semi == SemiColonMode::Comma
                        && brace_depth == 0
                        && bracket_depth == 0 =>
                {
                    break;
                }
                _ => self.bump(),
            }
        }
    }

    pub(super) fn check_for_for_in_in_typo(&mut self, in_span: Span) {
        if self.eat_keyword(exp!(In)) {
            // a common typo: `for _ in in bar {}`
            self.dcx().emit_err(InInTypo {
                span: self.prev_token.span,
                sugg_span: in_span.until(self.prev_token.span),
            });
        }
    }

    pub(super) fn eat_incorrect_doc_comment_for_param_type(&mut self) {
        if let token::DocComment(..) = self.token.kind {
            self.dcx().emit_err(DocCommentOnParamType { span: self.token.span });
            self.bump();
        } else if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
            let lo = self.token.span;
            // Skip every token until next possible arg.
            while self.token != token::CloseBracket {
                self.bump();
            }
            let sp = lo.to(self.token.span);
            self.bump();
            self.dcx().emit_err(AttributeOnParamType { span: sp });
        }
    }

    pub(super) fn parameter_without_type(
        &mut self,
        err: &mut Diag<'_>,
        pat: Box<ast::Pat>,
        require_name: bool,
        first_param: bool,
        fn_parse_mode: &crate::parser::item::FnParseMode,
    ) -> Option<Ident> {
        // If we find a pattern followed by an identifier, it could be an (incorrect)
        // C-style parameter declaration.
        if self.check_ident()
            && self.look_ahead(1, |t| *t == token::Comma || *t == token::CloseParen)
        {
            // `fn foo(String s) {}`
            let ident = self.parse_ident_common(true).unwrap();
            let span = pat.span.with_hi(ident.span.hi());

            err.span_suggestion(
                span,
                "declare the type after the parameter binding",
                "<identifier>: <type>",
                Applicability::HasPlaceholders,
            );
            return Some(ident);
        } else if require_name
            && (self.token == token::Comma
                || self.token == token::Lt
                || self.token == token::CloseParen)
        {
            let maybe_emit_anon_params_note = |this: &mut Self, err: &mut Diag<'_>| {
                let ed = this.token.span.with_neighbor(this.prev_token.span).edition();
                if matches!(fn_parse_mode.context, crate::parser::item::FnContext::Trait)
                    && (fn_parse_mode.req_name)(ed, IsDotDotDot::No)
                {
                    err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
                }
            };

            let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) =
                match pat.kind {
                    PatKind::Ident(_, ident, _) => (
                        ident,
                        "self: ",
                        ": TypeName".to_string(),
                        "_: ",
                        pat.span.shrink_to_lo(),
                        pat.span.shrink_to_hi(),
                        pat.span.shrink_to_lo(),
                    ),
                    PatKind::Ref(ref inner_pat, _, _)
                    // Fix suggestions for multi-reference `self` parameters (e.g. `&&&self`)
                    // cc: https://github.com/rust-lang/rust/pull/146305
                        if let PatKind::Ref(_, _, _) = &inner_pat.kind
                            && let PatKind::Path(_, path) = &pat.peel_refs().kind
                            && let [a, ..] = path.segments.as_slice()
                            && a.ident.name == kw::SelfLower =>
                    {
                        let mut inner = inner_pat;
                        let mut span_vec = vec![pat.span];

                        while let PatKind::Ref(ref inner_type, _, _) = inner.kind {
                            inner = inner_type;
                            span_vec.push(inner.span.shrink_to_lo());
                        }

                        let span = match span_vec.len() {
                            // Should be unreachable: match guard ensures at least 2 references
                            0 | 1 => unreachable!(),
                            2 => span_vec[0].until(inner_pat.span.shrink_to_lo()),
                            _ => span_vec[0].until(span_vec[span_vec.len() - 2].shrink_to_lo()),
                        };

                        err.span_suggestion_verbose(
                            span,
                            "`self` should be `self`, `&self` or `&mut self`, consider removing extra references",
                            "".to_string(),
                            Applicability::MachineApplicable,
                        );

                        return None;
                    }
                    // Also catches `fn foo(&a)`.
                    PatKind::Ref(ref inner_pat, pinned, mutab)
                        if let PatKind::Ident(_, ident, _) = inner_pat.clone().kind =>
                    {
                        let mutab = pinned.prefix_str(mutab);
                        (
                            ident,
                            "self: ",
                            format!("{ident}: &{mutab}TypeName"),
                            "_: ",
                            pat.span.shrink_to_lo(),
                            pat.span,
                            pat.span.shrink_to_lo(),
                        )
                    }
                    _ => {
                        // Otherwise, try to get a type and emit a suggestion.
                        if let Some(_) = pat.to_ty() {
                            err.span_suggestion_verbose(
                                pat.span.shrink_to_lo(),
                                "explicitly ignore the parameter name",
                                "_: ".to_string(),
                                Applicability::MachineApplicable,
                            );
                            maybe_emit_anon_params_note(self, err);
                        }

                        return None;
                    }
                };

            // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
            if first_param
                // Only when the fn is a method, we emit this suggestion.
                && matches!(
                    fn_parse_mode.context,
                    FnContext::Trait | FnContext::Impl
                )
            {
                err.span_suggestion_verbose(
                    self_span,
                    "if this is a `self` type, give it a parameter name",
                    self_sugg,
                    Applicability::MaybeIncorrect,
                );
            }
            // Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to
            // `fn foo(HashMap: TypeName<u32>)`.
            if self.token != token::Lt {
                err.span_suggestion_verbose(
                    param_span,
                    "if this is a parameter name, give it a type",
                    param_sugg,
                    Applicability::HasPlaceholders,
                );
            }
            err.span_suggestion_verbose(
                type_span,
                "if this is a type, explicitly ignore the parameter name",
                type_sugg,
                Applicability::MachineApplicable,
            );
            maybe_emit_anon_params_note(self, err);

            // Don't attempt to recover by using the `X` in `X<Y>` as the parameter name.
            return if self.token == token::Lt { None } else { Some(ident) };
        }
        None
    }

    #[cold]
    pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (Box<ast::Pat>, Box<ast::Ty>)> {
        let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?;
        self.expect(exp!(Colon))?;
        let ty = self.parse_ty()?;

        self.dcx().emit_err(PatternMethodParamWithoutBody { span: pat.span });

        // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
        let pat = Box::new(Pat {
            kind: PatKind::Wild,
            span: pat.span,
            id: ast::DUMMY_NODE_ID,
            tokens: None,
        });
        Ok((pat, ty))
    }

    pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> {
        let span = param.pat.span;
        let guar = self.dcx().emit_err(SelfParamNotFirst { span });
        param.ty.kind = TyKind::Err(guar);
        Ok(param)
    }

    pub(super) fn consume_block(
        &mut self,
        open: ExpTokenPair,
        close: ExpTokenPair,
        consume_close: ConsumeClosingDelim,
    ) {
        let mut brace_depth = 0;
        loop {
            if self.eat(open) {
                brace_depth += 1;
            } else if self.check(close) {
                if brace_depth == 0 {
                    if let ConsumeClosingDelim::Yes = consume_close {
                        // Some of the callers of this method expect to be able to parse the
                        // closing delimiter themselves, so we leave it alone. Otherwise we advance
                        // the parser.
                        self.bump();
                    }
                    return;
                } else {
                    self.bump();
                    brace_depth -= 1;
                    continue;
                }
            } else if self.token == token::Eof {
                return;
            } else {
                self.bump();
            }
        }
    }

    pub(super) fn expected_expression_found(&self) -> Diag<'a> {
        let (span, msg) = match (&self.token.kind, self.subparser_name) {
            (&token::Eof, Some(origin)) => {
                let sp = self.prev_token.span.shrink_to_hi();
                (sp, format!("expected expression, found end of {origin}"))
            }
            _ => (
                self.token.span,
                format!("expected expression, found {}", super::token_descr(&self.token)),
            ),
        };
        let mut err = self.dcx().struct_span_err(span, msg);
        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.span_label(span, "expected expression");
        err
    }

    fn consume_tts(
        &mut self,
        mut acc: i64, // `i64` because malformed code can have more closing delims than opening.
        // Not using `FxHashMap` due to `token::TokenKind: !Eq + !Hash`.
        modifier: &[(token::TokenKind, i64)],
    ) {
        while acc > 0 {
            if let Some((_, val)) = modifier.iter().find(|(t, _)| self.token == *t) {
                acc += *val;
            }
            if self.token == token::Eof {
                break;
            }
            self.bump();
        }
    }

    /// Replace duplicated recovered parameters with `_` pattern to avoid unnecessary errors.
    ///
    /// This is necessary because at this point we don't know whether we parsed a function with
    /// anonymous parameters or a function with names but no types. In order to minimize
    /// unnecessary errors, we assume the parameters are in the shape of `fn foo(a, b, c)` where
    /// the parameters are *names* (so we don't emit errors about not being able to find `b` in
    /// the local scope), but if we find the same name multiple times, like in `fn foo(i8, i8)`,
    /// we deduplicate them to not complain about duplicated parameter names.
    pub(super) fn deduplicate_recovered_params_names(&self, fn_inputs: &mut ThinVec<Param>) {
        let mut seen_inputs = FxHashSet::default();
        for input in fn_inputs.iter_mut() {
            let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err(_)) =
                (&input.pat.kind, &input.ty.kind)
            {
                Some(*ident)
            } else {
                None
            };
            if let Some(ident) = opt_ident {
                if seen_inputs.contains(&ident) {
                    input.pat.kind = PatKind::Wild;
                }
                seen_inputs.insert(ident);
            }
        }
    }

    /// Handle encountering a symbol in a generic argument list that is not a `,` or `>`. In this
    /// case, we emit an error and try to suggest enclosing a const argument in braces if it looks
    /// like the user has forgotten them.
    pub(super) fn handle_ambiguous_unbraced_const_arg(
        &mut self,
        args: &mut ThinVec<AngleBracketedArg>,
    ) -> PResult<'a, bool> {
        // If we haven't encountered a closing `>`, then the argument is malformed.
        // It's likely that the user has written a const expression without enclosing it
        // in braces, so we try to recover here.
        let arg = args.pop().unwrap();
        // FIXME: for some reason using `unexpected` or `expected_one_of_not_found` has
        // adverse side-effects to subsequent errors and seems to advance the parser.
        // We are causing this error here exclusively in case that a `const` expression
        // could be recovered from the current parser state, even if followed by more
        // arguments after a comma.
        let mut err = self.dcx().struct_span_err(
            self.token.span,
            format!("expected one of `,` or `>`, found {}", super::token_descr(&self.token)),
        );
        err.span_label(self.token.span, "expected one of `,` or `>`");
        match self.recover_const_arg(arg.span(), err) {
            Ok(arg) => {
                args.push(AngleBracketedArg::Arg(arg));
                if self.eat(exp!(Comma)) {
                    return Ok(true); // Continue
                }
            }
            Err(err) => {
                args.push(arg);
                // We will emit a more generic error later.
                err.delay_as_bug();
            }
        }
        Ok(false) // Don't continue.
    }

    fn recover_const_param_decl(&mut self, ty_generics: Option<&Generics>) -> Option<GenericArg> {
        let snapshot = self.create_snapshot_for_diagnostic();
        let param = match self.parse_const_param(AttrVec::new()) {
            Ok(param) => param,
            Err(err) => {
                err.cancel();
                self.restore_snapshot(snapshot);
                return None;
            }
        };

        let ident = param.ident.to_string();
        let sugg = match (ty_generics, self.psess.source_map().span_to_snippet(param.span())) {
            (Some(Generics { params, span: impl_generics, .. }), Ok(snippet)) => {
                Some(match &params[..] {
                    [] => UnexpectedConstParamDeclarationSugg::AddParam {
                        impl_generics: *impl_generics,
                        incorrect_decl: param.span(),
                        snippet,
                        ident,
                    },
                    [.., generic] => UnexpectedConstParamDeclarationSugg::AppendParam {
                        impl_generics_end: generic.span().shrink_to_hi(),
                        incorrect_decl: param.span(),
                        snippet,
                        ident,
                    },
                })
            }
            _ => None,
        };
        let guar =
            self.dcx().emit_err(UnexpectedConstParamDeclaration { span: param.span(), sugg });

        let value = self.mk_expr_err(param.span(), guar);
        Some(GenericArg::Const(AnonConst {
            id: ast::DUMMY_NODE_ID,
            value,
            mgca_disambiguation: MgcaDisambiguation::Direct,
        }))
    }

    pub(super) fn recover_const_param_declaration(
        &mut self,
        ty_generics: Option<&Generics>,
    ) -> PResult<'a, Option<GenericArg>> {
        // We have to check for a few different cases.
        if let Some(arg) = self.recover_const_param_decl(ty_generics) {
            return Ok(Some(arg));
        }

        // We haven't consumed `const` yet.
        let start = self.token.span;
        self.bump(); // `const`

        // Detect and recover from the old, pre-RFC2000 syntax for const generics.
        let mut err = UnexpectedConstInGenericParam { span: start, to_remove: None };
        if self.check_const_arg() {
            err.to_remove = Some(start.until(self.token.span));
            self.dcx().emit_err(err);
            Ok(Some(GenericArg::Const(self.parse_const_arg()?)))
        } else {
            let after_kw_const = self.token.span;
            self.recover_const_arg(after_kw_const, self.dcx().create_err(err)).map(Some)
        }
    }

    /// Try to recover from possible generic const argument without `{` and `}`.
    ///
    /// When encountering code like `foo::< bar + 3 >` or `foo::< bar - baz >` we suggest
    /// `foo::<{ bar + 3 }>` and `foo::<{ bar - baz }>`, respectively. We only provide a suggestion
    /// if we think that the resulting expression would be well formed.
    pub(super) fn recover_const_arg(
        &mut self,
        start: Span,
        mut err: Diag<'a>,
    ) -> PResult<'a, GenericArg> {
        let is_op_or_dot = AssocOp::from_token(&self.token)
            .and_then(|op| {
                if let AssocOp::Binary(
                    BinOpKind::Gt
                    | BinOpKind::Lt
                    | BinOpKind::Shr
                    | BinOpKind::Ge
                )
                // Don't recover from `foo::<bar = baz>`, because this could be an attempt to
                // assign a value to a defaulted generic parameter.
                | AssocOp::Assign
                | AssocOp::AssignOp(_) = op
                {
                    None
                } else {
                    Some(op)
                }
            })
            .is_some()
            || self.token == TokenKind::Dot;
        // This will be true when a trait object type `Foo +` or a path which was a `const fn` with
        // type params has been parsed.
        let was_op = matches!(self.prev_token.kind, token::Plus | token::Shr | token::Gt);
        if !is_op_or_dot && !was_op {
            // We perform these checks and early return to avoid taking a snapshot unnecessarily.
            return Err(err);
        }
        let snapshot = self.create_snapshot_for_diagnostic();
        if is_op_or_dot {
            self.bump();
        }
        match (|| {
            let attrs = self.parse_outer_attributes()?;
            self.parse_expr_res(Restrictions::CONST_EXPR, attrs)
        })() {
            Ok((expr, _)) => {
                // Find a mistake like `MyTrait<Assoc == S::Assoc>`.
                if snapshot.token == token::EqEq {
                    err.span_suggestion(
                        snapshot.token.span,
                        "if you meant to use an associated type binding, replace `==` with `=`",
                        "=",
                        Applicability::MaybeIncorrect,
                    );
                    let guar = err.emit();
                    let value = self.mk_expr_err(start.to(expr.span), guar);
                    return Ok(GenericArg::Const(AnonConst {
                        id: ast::DUMMY_NODE_ID,
                        value,
                        mgca_disambiguation: MgcaDisambiguation::Direct,
                    }));
                } else if snapshot.token == token::Colon
                    && expr.span.lo() == snapshot.token.span.hi()
                    && matches!(expr.kind, ExprKind::Path(..))
                {
                    // Find a mistake like "foo::var:A".
                    err.span_suggestion(
                        snapshot.token.span,
                        "write a path separator here",
                        "::",
                        Applicability::MaybeIncorrect,
                    );
                    let guar = err.emit();
                    return Ok(GenericArg::Type(
                        self.mk_ty(start.to(expr.span), TyKind::Err(guar)),
                    ));
                } else if self.token == token::Comma || self.token.kind.should_end_const_arg() {
                    // Avoid the following output by checking that we consumed a full const arg:
                    // help: expressions must be enclosed in braces to be used as const generic
                    //       arguments
                    //    |
                    // LL |     let sr: Vec<{ (u32, _, _) = vec![] };
                    //    |                 ^                      ^
                    return Ok(self.dummy_const_arg_needs_braces(err, start.to(expr.span)));
                }
            }
            Err(err) => {
                err.cancel();
            }
        }
        self.restore_snapshot(snapshot);
        Err(err)
    }

    /// Try to recover from an unbraced const argument whose first token [could begin a type][ty].
    ///
    /// [ty]: token::Token::can_begin_type
    pub(crate) fn recover_unbraced_const_arg_that_can_begin_ty(
        &mut self,
        mut snapshot: SnapshotParser<'a>,
    ) -> Option<Box<ast::Expr>> {
        match (|| {
            let attrs = self.parse_outer_attributes()?;
            snapshot.parse_expr_res(Restrictions::CONST_EXPR, attrs)
        })() {
            // Since we don't know the exact reason why we failed to parse the type or the
            // expression, employ a simple heuristic to weed out some pathological cases.
            Ok((expr, _)) if let token::Comma | token::Gt = snapshot.token.kind => {
                self.restore_snapshot(snapshot);
                Some(expr)
            }
            Ok(_) => None,
            Err(err) => {
                err.cancel();
                None
            }
        }
    }

    /// Creates a dummy const argument, and reports that the expression must be enclosed in braces
    pub(super) fn dummy_const_arg_needs_braces(&self, mut err: Diag<'a>, span: Span) -> GenericArg {
        err.multipart_suggestion(
            "expressions must be enclosed in braces to be used as const generic \
             arguments",
            vec![(span.shrink_to_lo(), "{ ".to_string()), (span.shrink_to_hi(), " }".to_string())],
            Applicability::MaybeIncorrect,
        );
        let guar = err.emit();
        let value = self.mk_expr_err(span, guar);
        GenericArg::Const(AnonConst {
            id: ast::DUMMY_NODE_ID,
            value,
            mgca_disambiguation: MgcaDisambiguation::Direct,
        })
    }

    /// Some special error handling for the "top-level" patterns in a match arm,
    /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
    #[cold]
    pub(crate) fn recover_colon_colon_in_pat_typo(
        &mut self,
        mut first_pat: Pat,
        expected: Option<Expected>,
    ) -> Pat {
        if token::Colon != self.token.kind {
            return first_pat;
        }

        // The pattern looks like it might be a path with a `::` -> `:` typo:
        // `match foo { bar:baz => {} }`
        let colon_span = self.token.span;
        // We only emit "unexpected `:`" error here if we can successfully parse the
        // whole pattern correctly in that case.
        let mut snapshot_pat = self.create_snapshot_for_diagnostic();
        let mut snapshot_type = self.create_snapshot_for_diagnostic();

        // Create error for "unexpected `:`".
        match self.expected_one_of_not_found(&[], &[]) {
            Err(mut err) => {
                // Skip the `:`.
                snapshot_pat.bump();
                snapshot_type.bump();
                match snapshot_pat.parse_pat_no_top_alt(expected, None) {
                    Err(inner_err) => {
                        inner_err.cancel();
                    }
                    Ok(mut pat) => {
                        // We've parsed the rest of the pattern.
                        let new_span = first_pat.span.to(pat.span);
                        let mut show_sugg = false;
                        // Try to construct a recovered pattern.
                        match &mut pat.kind {
                            PatKind::Struct(qself @ None, path, ..)
                            | PatKind::TupleStruct(qself @ None, path, _)
                            | PatKind::Path(qself @ None, path) => match &first_pat.kind {
                                PatKind::Ident(_, ident, _) => {
                                    path.segments.insert(0, PathSegment::from_ident(*ident));
                                    path.span = new_span;
                                    show_sugg = true;
                                    first_pat = pat;
                                }
                                PatKind::Path(old_qself, old_path) => {
                                    path.segments = old_path
                                        .segments
                                        .iter()
                                        .cloned()
                                        .chain(take(&mut path.segments))
                                        .collect();
                                    path.span = new_span;
                                    *qself = old_qself.clone();
                                    first_pat = pat;
                                    show_sugg = true;
                                }
                                _ => {}
                            },
                            PatKind::Ident(BindingMode::NONE, ident, None) => {
                                match &first_pat.kind {
                                    PatKind::Ident(_, old_ident, _) => {
                                        let path = PatKind::Path(
                                            None,
                                            Path {
                                                span: new_span,
                                                segments: thin_vec![
                                                    PathSegment::from_ident(*old_ident),
                                                    PathSegment::from_ident(*ident),
                                                ],
                                                tokens: None,
                                            },
                                        );
                                        first_pat = self.mk_pat(new_span, path);
                                        show_sugg = true;
                                    }
                                    PatKind::Path(old_qself, old_path) => {
                                        let mut segments = old_path.segments.clone();
                                        segments.push(PathSegment::from_ident(*ident));
                                        let path = PatKind::Path(
                                            old_qself.clone(),
                                            Path { span: new_span, segments, tokens: None },
                                        );
                                        first_pat = self.mk_pat(new_span, path);
                                        show_sugg = true;
                                    }
                                    _ => {}
                                }
                            }
                            _ => {}
                        }
                        if show_sugg {
                            err.span_suggestion_verbose(
                                colon_span.until(self.look_ahead(1, |t| t.span)),
                                "maybe write a path separator here",
                                "::",
                                Applicability::MaybeIncorrect,
                            );
                        } else {
                            first_pat = self.mk_pat(
                                new_span,
                                PatKind::Err(
                                    self.dcx()
                                        .span_delayed_bug(colon_span, "recovered bad path pattern"),
                                ),
                            );
                        }
                        self.restore_snapshot(snapshot_pat);
                    }
                }
                match snapshot_type.parse_ty() {
                    Err(inner_err) => {
                        inner_err.cancel();
                    }
                    Ok(ty) => {
                        err.span_label(ty.span, "specifying the type of a pattern isn't supported");
                        self.restore_snapshot(snapshot_type);
                        let new_span = first_pat.span.to(ty.span);
                        first_pat =
                            self.mk_pat(
                                new_span,
                                PatKind::Err(self.dcx().span_delayed_bug(
                                    colon_span,
                                    "recovered bad pattern with type",
                                )),
                            );
                    }
                }
                err.emit();
            }
            _ => {
                // Carry on as if we had not done anything. This should be unreachable.
            }
        };
        first_pat
    }

    /// If `loop_header` is `Some` and an unexpected block label is encountered,
    /// it is suggested to be moved just before `loop_header`, else it is suggested to be removed.
    pub(crate) fn maybe_recover_unexpected_block_label(
        &mut self,
        loop_header: Option<Span>,
    ) -> bool {
        // Check for `'a : {`
        if !(self.check_lifetime()
            && self.look_ahead(1, |t| *t == token::Colon)
            && self.look_ahead(2, |t| *t == token::OpenBrace))
        {
            return false;
        }
        let label = self.eat_label().expect("just checked if a label exists");
        self.bump(); // eat `:`
        let span = label.ident.span.to(self.prev_token.span);
        let mut diag = self
            .dcx()
            .struct_span_err(span, "block label not supported here")
            .with_span_label(span, "not supported here");
        if let Some(loop_header) = loop_header {
            diag.multipart_suggestion(
                "if you meant to label the loop, move this label before the loop",
                vec![
                    (label.ident.span.until(self.token.span), String::from("")),
                    (loop_header.shrink_to_lo(), format!("{}: ", label.ident)),
                ],
                Applicability::MachineApplicable,
            );
        } else {
            diag.tool_only_span_suggestion(
                label.ident.span.until(self.token.span),
                "remove this block label",
                "",
                Applicability::MachineApplicable,
            );
        }
        diag.emit();
        true
    }

    /// Some special error handling for the "top-level" patterns in a match arm,
    /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
    pub(crate) fn maybe_recover_unexpected_comma(
        &mut self,
        lo: Span,
        rt: CommaRecoveryMode,
    ) -> PResult<'a, ()> {
        if self.token != token::Comma {
            return Ok(());
        }
        self.recover_unexpected_comma(lo, rt)
    }

    #[cold]
    fn recover_unexpected_comma(&mut self, lo: Span, rt: CommaRecoveryMode) -> PResult<'a, ()> {
        // An unexpected comma after a top-level pattern is a clue that the
        // user (perhaps more accustomed to some other language) forgot the
        // parentheses in what should have been a tuple pattern; return a
        // suggestion-enhanced error here rather than choking on the comma later.
        let comma_span = self.token.span;
        self.bump();
        if let Err(err) = self.skip_pat_list() {
            // We didn't expect this to work anyway; we just wanted to advance to the
            // end of the comma-sequence so we know the span to suggest parenthesizing.
            err.cancel();
        }
        let seq_span = lo.to(self.prev_token.span);
        let mut err = self.dcx().struct_span_err(comma_span, "unexpected `,` in pattern");
        err.multipart_suggestion(
            format!(
                "try adding parentheses to match on a tuple{}",
                if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
            ),
            vec![
                (seq_span.shrink_to_lo(), "(".to_string()),
                (seq_span.shrink_to_hi(), ")".to_string()),
            ],
            Applicability::MachineApplicable,
        );
        if let CommaRecoveryMode::EitherTupleOrPipe = rt {
            err.span_suggestion(
                comma_span,
                "...or a vertical bar to match on alternatives",
                " |",
                Applicability::MachineApplicable,
            );
        }
        Err(err)
    }

    pub(crate) fn maybe_recover_bounds_doubled_colon(&mut self, ty: &Ty) -> PResult<'a, ()> {
        let TyKind::Path(qself, path) = &ty.kind else { return Ok(()) };
        let qself_position = qself.as_ref().map(|qself| qself.position);
        for (i, segments) in path.segments.windows(2).enumerate() {
            if qself_position.is_some_and(|pos| i < pos) {
                continue;
            }
            if let [a, b] = segments {
                let (a_span, b_span) = (a.span(), b.span());
                let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo());
                if self.span_to_snippet(between_span).as_deref() == Ok(":: ") {
                    return Err(self.dcx().create_err(DoubleColonInBound {
                        span: path.span.shrink_to_hi(),
                        between: between_span,
                    }));
                }
            }
        }
        Ok(())
    }

    /// Check for exclusive ranges written as `..<`
    pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: Diag<'a>) -> Diag<'a> {
        if maybe_lt == token::Lt
            && (self.expected_token_types.contains(TokenType::Gt)
                || matches!(self.token.kind, token::Literal(..)))
        {
            err.span_suggestion(
                maybe_lt.span,
                "remove the `<` to write an exclusive range",
                "",
                Applicability::MachineApplicable,
            );
        }
        err
    }

    /// This checks if this is a conflict marker, depending of the parameter passed.
    ///
    /// * `<<<<<<<`
    /// * `|||||||`
    /// * `=======`
    /// * `>>>>>>>`
    ///
    pub(super) fn is_vcs_conflict_marker(
        &mut self,
        long_kind: &TokenKind,
        short_kind: &TokenKind,
    ) -> bool {
        if long_kind == short_kind {
            // For conflict marker chars like `%` and `\`.
            (0..7).all(|i| self.look_ahead(i, |tok| tok == long_kind))
        } else {
            // For conflict marker chars like `<` and `|`.
            (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
                && self.look_ahead(3, |tok| tok == short_kind || tok == long_kind)
        }
    }

    fn conflict_marker(
        &mut self,
        long_kind: &TokenKind,
        short_kind: &TokenKind,
        expected: Option<usize>,
    ) -> Option<(Span, usize)> {
        if self.is_vcs_conflict_marker(long_kind, short_kind) {
            let lo = self.token.span;
            if self.psess.source_map().span_to_margin(lo) != Some(0) {
                return None;
            }
            let mut len = 0;
            while self.token.kind == *long_kind || self.token.kind == *short_kind {
                if self.token.kind.break_two_token_op(1).is_some() {
                    len += 2;
                } else {
                    len += 1;
                }
                self.bump();
                if expected == Some(len) {
                    break;
                }
            }
            if expected.is_some() && expected != Some(len) {
                return None;
            }
            return Some((lo.to(self.prev_token.span), len));
        }
        None
    }

    pub(super) fn recover_vcs_conflict_marker(&mut self) {
        // <<<<<<<
        let Some((start, len)) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt, None) else {
            return;
        };
        let mut spans = Vec::with_capacity(2);
        spans.push(start);
        // |||||||
        let mut middlediff3 = None;
        // =======
        let mut middle = None;
        // >>>>>>>
        let mut end = None;
        loop {
            if self.token == TokenKind::Eof {
                break;
            }
            if let Some((span, _)) =
                self.conflict_marker(&TokenKind::OrOr, &TokenKind::Or, Some(len))
            {
                middlediff3 = Some(span);
            }
            if let Some((span, _)) =
                self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq, Some(len))
            {
                middle = Some(span);
            }
            if let Some((span, _)) =
                self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt, Some(len))
            {
                spans.push(span);
                end = Some(span);
                break;
            }
            self.bump();
        }

        let mut err = self.dcx().struct_span_fatal(spans, "encountered diff marker");
        let middle_marker = match middlediff3 {
            // We're using diff3
            Some(middlediff3) => {
                err.span_label(
                    middlediff3,
                    "between this marker and `=======` is the base code (what the two refs \
                     diverged from)",
                );
                "|||||||"
            }
            None => "=======",
        };
        err.span_label(
            start,
            format!(
                "between this marker and `{middle_marker}` is the code that you are merging into",
            ),
        );

        if let Some(middle) = middle {
            err.span_label(middle, "between this marker and `>>>>>>>` is the incoming code");
        }
        if let Some(end) = end {
            err.span_label(end, "this marker concludes the conflict region");
        }
        err.note(
            "conflict markers indicate that a merge was started but could not be completed due \
             to merge conflicts\n\
             to resolve a conflict, keep only the code you want and then delete the lines \
             containing conflict markers",
        );
        err.help(
            "if you are in a merge, the top section is the code you already had checked out and \
             the bottom section is the new code\n\
             if you are in a rebase, the top section is the code being rebased onto and the bottom \
             section is the code you had checked out which is being rebased",
        );

        err.note(
            "for an explanation on these markers from the `git` documentation, visit \
             <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>",
        );

        err.emit();
    }

    /// Parse and throw away a parenthesized comma separated
    /// sequence of patterns until `)` is reached.
    fn skip_pat_list(&mut self) -> PResult<'a, ()> {
        while !self.check(exp!(CloseParen)) {
            self.parse_pat_no_top_alt(None, None)?;
            if !self.eat(exp!(Comma)) {
                return Ok(());
            }
        }
        Ok(())
    }
}
