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, 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,
    pluralize,
};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::edit_distance::find_best_match_for_name;
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,
    ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything,
    DocCommentOnParamType, DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
    GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
    HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait,
    IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, PatternMethodParamWithoutBody,
    QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
    StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma,
    TernaryOperator, TernaryOperatorSuggestion, UnexpectedConstInGenericParam,
    UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
    UseEqInstead, WrapType,
};
use crate::parser::FnContext;
use crate::parser::attr::InnerAttrPolicy;
use crate::parser::item::IsDotDotDot;
use crate::{exp, fluent_generated as fluent};

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

#[derive(Debug, rustc_macros::Subdiagnostic)]
#[suggestion(
    parse_misspelled_kw,
    applicability = "machine-applicable",
    code = "{similar_kw}",
    style = "verbose"
)]
struct MisspelledKw {
    similar_kw: String,
    #[primary_span]
    span: Span,
    is_incorrect_case: bool,
}

/// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`.
fn find_similar_kw(lookup: Ident, candidates: &[Symbol]) -> Option<MisspelledKw> {
    let lowercase = lookup.name.as_str().to_lowercase();
    let lowercase_sym = Symbol::intern(&lowercase);
    if candidates.contains(&lowercase_sym) {
        Some(MisspelledKw { similar_kw: lowercase, span: lookup.span, is_incorrect_case: true })
    } else if let Some(similar_sym) = find_best_match_for_name(candidates, lookup.name, None) {
        Some(MisspelledKw {
            similar_kw: similar_sym.to_string(),
            span: lookup.span,
            is_incorrect_case: false,
        })
    } else {
        None
    }
}

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(super) 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 matches!(&err.suggestions, Suggestions::Enabled(list) if 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(),
                            fluent::parse_sugg_turbofish_syntax,
                            "::",
                            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().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.
    }

    /// Attempt to parse a generic const argument that has not been enclosed in braces.
    /// There are a limited number of expressions that are permitted without being encoded
    /// in braces:
    /// - Literals.
    /// - Single-segment paths (i.e. standalone generic const parameters).
    /// All other expressions that can be parsed will emit an error suggesting the expression be
    /// wrapped in braces.
    pub(super) fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, Box<Expr>> {
        let start = self.token.span;
        let attrs = self.parse_outer_attributes()?;
        let (expr, _) =
            self.parse_expr_res(Restrictions::CONST_EXPR, attrs).map_err(|mut err| {
                err.span_label(
                    start.shrink_to_lo(),
                    "while parsing a const generic argument starting here",
                );
                err
            })?;
        if !self.expr_is_valid_const_arg(&expr) {
            self.dcx().emit_err(ConstGenericWithoutBraces {
                span: expr.span,
                sugg: ConstGenericWithoutBracesSugg {
                    left: expr.span.shrink_to_lo(),
                    right: expr.span.shrink_to_hi(),
                },
            });
        }
        Ok(expr)
    }

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

    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 }));
                } 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 })
    }

    /// 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 {
        (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
            && self.look_ahead(3, |tok| tok == short_kind)
    }

    fn conflict_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option<Span> {
        if self.is_vcs_conflict_marker(long_kind, short_kind) {
            let lo = self.token.span;
            for _ in 0..4 {
                self.bump();
            }
            return Some(lo.to(self.prev_token.span));
        }
        None
    }

    pub(super) fn recover_vcs_conflict_marker(&mut self) {
        // <<<<<<<
        let Some(start) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt) else {
            return;
        };
        let mut spans = Vec::with_capacity(3);
        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) {
                middlediff3 = Some(span);
            }
            if let Some(span) = self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq) {
                middle = Some(span);
            }
            if let Some(span) = self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt) {
                spans.push(span);
                end = Some(span);
                break;
            }
            self.bump();
        }

        let mut err = self.dcx().struct_span_fatal(spans, "encountered diff marker");
        match middlediff3 {
            // We're using diff3
            Some(middlediff3) => {
                err.span_label(
                    start,
                    "between this marker and `|||||||` is the code that we're merging into",
                );
                err.span_label(middlediff3, "between this marker and `=======` is the base code (what the two refs diverged from)");
            }
            None => {
                err.span_label(
                    start,
                    "between this marker and `=======` is the code that we're 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're having merge conflicts after pulling new code:\n\
             the top section is the code you already had and the bottom section is the remote code\n\
             if you're in the middle of a rebase:\n\
             the top section is the code being rebased onto and the bottom section is the code \
             coming from the current commit being rebased",
        );

        err.note(
            "for an explanation on these markers from the `git` documentation:\n\
             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(())
    }
}
