pub mod attr;
mod attr_wrapper;
mod diagnostics;
mod expr;
mod generics;
mod item;
mod nonterminal;
mod pat;
mod path;
mod stmt;
pub mod token_type;
mod ty;

// Parsers for non-functionlike builtin macros are defined in rustc_parse so they can be used by
// both rustc_builtin_macros and rustfmt.
pub mod asm;
pub mod cfg_select;

use std::{debug_assert_matches, fmt, mem, slice};

use attr_wrapper::{AttrWrapper, UsePreAttrPos};
pub use diagnostics::AttemptLocalParseRecovery;
// Public to use it for custom `if` expressions in rustfmt forks like https://github.com/tucant/rustfmt
pub use expr::LetChainsPolicy;
pub(crate) use item::{FnContext, FnParseMode};
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
pub use path::PathStyle;
use rustc_ast::token::{
    self, IdentIsRaw, InvisibleOrigin, MetaVarKind, NtExprKind, NtPatKind, Token, TokenKind,
};
use rustc_ast::tokenstream::{
    ParserRange, ParserReplacement, Spacing, TokenCursor, TokenStream, TokenTree, TokenTreeCursor,
    WithTokens,
};
use rustc_ast::util::case::Case;
use rustc_ast::util::classify;
use rustc_ast::{
    self as ast, AnonConst, AttrArgs, AttrId, BinOpKind, ByRef, Const, CoroutineKind,
    DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, Extern, HasTokens, ImplRestriction, MutRestriction,
    Mutability, Recovered, RestrictionKind, Safety, StrLit, Visibility, VisibilityKind,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Applicability, Diag, FatalError, MultiSpan, PResult};
use rustc_index::interval::IntervalSet;
use rustc_session::parse::ParseSess;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
use thin_vec::ThinVec;
use token_type::TokenTypeSet;
pub use token_type::{ExpKeywordPair, ExpTokenPair, TokenType};
use tracing::debug;

use crate::diagnostics::{
    IncorrectImplRestriction, IncorrectMutRestriction, IncorrectVisibilityRestriction,
    NonStringAbiLiteral, TokenDescription,
};
use crate::exp;

#[cfg(test)]
mod tests;

// Ideally, these tests would be in `rustc_ast`. But they depend on having a
// parser, so they are here.
#[cfg(test)]
mod tokenstream {
    mod tests;
}

bitflags::bitflags! {
    /// Restrictions applied while parsing.
    ///
    /// The parser maintains a bitset of restrictions it will honor while
    /// parsing. This is essentially used as a way of tracking state of what
    /// is being parsed and to change behavior based on that.
    #[derive(Clone, Copy, Debug)]
    struct Restrictions: u8 {
        /// Restricts expressions for use in statement position.
        ///
        /// When expressions are used in various places, like statements or
        /// match arms, this is used to stop parsing once certain tokens are
        /// reached.
        ///
        /// For example, `if true {} & 1` with `STMT_EXPR` in effect is parsed
        /// as two separate expression statements (`if` and a reference to 1).
        /// Otherwise it is parsed as a bitwise AND where `if` is on the left
        /// and 1 is on the right.
        const STMT_EXPR         = 1 << 0;
        /// Do not allow struct literals.
        ///
        /// There are several places in the grammar where we don't want to
        /// allow struct literals because they can require lookahead, or
        /// otherwise could be ambiguous or cause confusion. For example,
        /// `if Foo {} {}` isn't clear if it is `Foo{}` struct literal, or
        /// just `Foo` is the condition, followed by a consequent block,
        /// followed by an empty block.
        ///
        /// See [RFC 92](https://rust-lang.github.io/rfcs/0092-struct-grammar.html).
        const NO_STRUCT_LITERAL = 1 << 1;
        /// Used to provide better error messages for const generic arguments.
        ///
        /// An un-braced const generic argument is limited to a very small
        /// subset of expressions. This is used to detect the situation where
        /// an expression outside of that subset is used, and to suggest to
        /// wrap the expression in braces.
        const CONST_EXPR        = 1 << 2;
        /// Allows `let` expressions.
        ///
        /// `let pattern = scrutinee` is parsed as an expression, but it is
        /// only allowed in let chains (`if` and `while` conditions).
        /// Otherwise it is not an expression (note that `let` in statement
        /// positions is treated as a `StmtKind::Let` statement, which has a
        /// slightly different grammar).
        const ALLOW_LET         = 1 << 3;
        /// Used to detect a missing `=>` in a match guard.
        ///
        /// This is used for error handling in a match guard to give a better
        /// error message if the `=>` is missing. It is set when parsing the
        /// guard expression.
        const IN_IF_GUARD       = 1 << 4;
        /// Used to detect the incorrect use of expressions in patterns.
        ///
        /// This is used for error handling while parsing a pattern. During
        /// error recovery, this will be set to try to parse the pattern as an
        /// expression, but halts parsing the expression when reaching certain
        /// tokens like `=`.
        const IS_PAT            = 1 << 5;
    }
}

#[derive(Clone, Copy, PartialEq, Debug)]
enum SemiColonMode {
    Break,
    Ignore,
    Comma,
}

#[derive(Clone, Copy, PartialEq, Debug)]
enum BlockMode {
    Break,
    Ignore,
}

/// Whether or not we should force collection of tokens for an AST node,
/// regardless of whether or not it has attributes
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ForceCollect {
    Yes,
    No,
}

/// Whether to accept `const { ... }` as a shorthand for `const _: () = const { ... }`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AllowConstBlockItems {
    Yes,
    No,
    DoesNotMatter,
}

/// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`.
#[macro_export]
macro_rules! maybe_recover_from_interpolated_ty_qpath {
    ($self: expr, $allow_qpath_recovery: expr) => {
        if $allow_qpath_recovery
            && $self.may_recover()
            && let Some(mv_kind) = $self.token.is_metavar_seq()
            && let token::MetaVarKind::Ty { .. } = mv_kind
            && $self.check_noexpect_past_close_delim(&token::PathSep)
        {
            // Reparse the type, then move to recovery.
            let ty = $self
                .eat_metavar_seq(mv_kind, |this| this.parse_ty_no_question_mark_recover())
                .expect("metavar seq ty");

            return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_token.span, ty);
        }
    };
}

#[derive(Clone, Copy, Debug)]
pub enum Recovery {
    Allowed,
    Forbidden,
}

#[derive(Clone)]
pub struct Parser<'a> {
    pub psess: &'a ParseSess,
    /// The current token.
    pub token: Token = Token::dummy(),
    /// The spacing for the current token.
    token_spacing: Spacing = Spacing::Alone,
    /// The previous token.
    pub prev_token: Token = Token::dummy(),
    pub capture_cfg: bool = false,
    restrictions: Restrictions = Restrictions::empty(),
    expected_token_types: TokenTypeSet = TokenTypeSet::new(),
    token_cursor: TokenCursor,
    // The number of calls to `bump`, i.e. the position in the token stream.
    num_bump_calls: u32 = 0,
    // During parsing we may sometimes need to "unglue" a glued token into two
    // or three component tokens (e.g. `>>` into `>` and `>`, or `>>=` into `>`
    // and `>` and `=`), so the parser can consume them one at a time. This
    // process bypasses the normal capturing mechanism (e.g. `num_bump_calls`
    // will not be incremented), since the "unglued" tokens due not exist in
    // the original `TokenStream`.
    //
    // If we end up consuming all the component tokens, this is not an issue,
    // because we'll end up capturing the single "glued" token.
    //
    // However, sometimes we may want to capture not all of the original
    // token. For example, capturing the `Vec<u8>` in `Option<Vec<u8>>`
    // requires us to unglue the trailing `>>` token. The `break_last_token`
    // field is used to track these tokens. They get appended to the captured
    // stream when we evaluate a `LazyAttrTokenStream`.
    //
    // This value is always 0, 1, or 2. It can only reach 2 when splitting
    // `>>=` or `<<=`.
    break_last_token: u32 = 0,
    /// This field is used to keep track of how many left angle brackets we have seen. This is
    /// required in order to detect extra leading left angle brackets (`<` characters) and error
    /// appropriately.
    ///
    /// See the comments in the `parse_path_segment` function for more details.
    unmatched_angle_bracket_count: u16 = 0,
    angle_bracket_nesting: u16 = 0,
    /// Keep track of when we're within `<...>` for proper error recovery.
    parsing_generics: bool = false,

    last_unexpected_token_span: Option<Span> = None,
    /// If present, this `Parser` is not parsing Rust code but rather a macro call.
    subparser_name: Option<&'static str>,
    capture_state: CaptureState,
    /// This allows us to recover when the user forget to add braces around
    /// multiple statements in the closure body.
    current_closure: Option<ClosureSpans> = None,
    /// Whether the parser is allowed to do recovery.
    /// This is disabled when parsing macro arguments, see #103534
    recovery: Recovery = Recovery::Allowed,
    /// Whether we're parsing a function body.
    in_fn_body: bool = false,
    /// Whether we have detected a missing semicolon in function body.
    pub fn_body_missing_semi_guar: Option<ErrorGuaranteed> = None,
}

// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with
// nonterminals. Make sure it doesn't unintentionally get bigger. We only check a few arches
// though, because `TokenTypeSet(u128)` alignment varies on others, changing the total size.
#[cfg(all(target_pointer_width = "64", any(target_arch = "aarch64", target_arch = "x86_64")))]
rustc_data_structures::static_assert_size!(Parser<'_>, 288);

/// Stores span information about a closure.
#[derive(Clone, Debug)]
struct ClosureSpans {
    whole_closure: Span,
    closing_pipe: Span,
    body: Span,
}

/// Controls how we capture tokens. Capturing can be expensive,
/// so we try to avoid performing capturing in cases where
/// we will never need an `AttrTokenStream`.
#[derive(Copy, Clone, Debug)]
enum Capturing {
    /// We aren't performing any capturing - this is the default mode.
    No,
    /// We are capturing tokens
    Yes,
}

// This state is used by `Parser::collect_tokens`.
#[derive(Clone, Debug)]
struct CaptureState {
    capturing: Capturing,
    parser_replacements: Vec<ParserReplacement>,
    inner_attr_parser_ranges: FxHashMap<AttrId, ParserRange>,
    // `IntervalSet` is good for perf because attrs are mostly added to this
    // set in contiguous ranges.
    seen_attrs: IntervalSet<AttrId>,
}

/// A sequence separator.
#[derive(Debug)]
struct SeqSep {
    /// The separator token.
    sep: Option<ExpTokenPair>,
    /// `true` if a trailing separator is allowed.
    trailing_sep_allowed: bool,
}

impl SeqSep {
    fn trailing_allowed(sep: ExpTokenPair) -> SeqSep {
        SeqSep { sep: Some(sep), trailing_sep_allowed: true }
    }

    fn none() -> SeqSep {
        SeqSep { sep: None, trailing_sep_allowed: false }
    }
}

/// Whether parsing `impl` or `mut` restrictions.
#[derive(Clone, Copy, Debug)]
enum ParsingRestrictionKind {
    Impl,
    Mut,
}

#[derive(Debug)]
pub enum FollowedByType {
    Yes,
    No,
}

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

impl From<bool> for Trailing {
    fn from(b: bool) -> Trailing {
        if b { Trailing::Yes } else { Trailing::No }
    }
}

pub fn token_descr(token: &Token) -> String {
    let s = pprust::token_to_string(token).to_string();

    match (TokenDescription::from_token(token), &token.kind) {
        (Some(TokenDescription::ReservedIdentifier), _) => format!("reserved identifier `{s}`"),
        (Some(TokenDescription::Keyword), _) => format!("keyword `{s}`"),
        (Some(TokenDescription::ReservedKeyword), _) => format!("reserved keyword `{s}`"),
        (Some(TokenDescription::DocComment), _) => format!("doc comment `{s}`"),
        // Deliberately doesn't print `s`, which is empty.
        (Some(TokenDescription::MetaVar(kind)), _) => format!("`{kind}` metavariable"),
        (None, TokenKind::NtIdent(..)) => format!("identifier `{s}`"),
        (None, TokenKind::NtLifetime(..)) => format!("lifetime `{s}`"),
        (None, _) => format!("`{s}`"),
    }
}

impl<'a> Parser<'a> {
    pub fn new(
        psess: &'a ParseSess,
        stream: TokenStream,
        subparser_name: Option<&'static str>,
    ) -> Self {
        let mut parser = Parser {
            psess,
            token_cursor: TokenCursor { curr: TokenTreeCursor::new(stream), stack: Vec::new() },
            subparser_name,
            capture_state: CaptureState {
                capturing: Capturing::No,
                parser_replacements: Vec::new(),
                inner_attr_parser_ranges: Default::default(),
                seen_attrs: IntervalSet::new(u32::MAX as usize),
            },
            ..
        };

        // Make parser point to the first token.
        parser.bump();

        // Change this from 1 back to 0 after the bump. This eases debugging of
        // `Parser::collect_tokens` because 0-indexed token positions are nicer
        // than 1-indexed token positions.
        parser.num_bump_calls = 0;

        parser
    }

    #[inline]
    pub fn recovery(mut self, recovery: Recovery) -> Self {
        self.recovery = recovery;
        self
    }

    #[inline]
    fn with_recovery<T>(&mut self, recovery: Recovery, f: impl FnOnce(&mut Self) -> T) -> T {
        let old = mem::replace(&mut self.recovery, recovery);
        let res = f(self);
        self.recovery = old;
        res
    }

    /// Whether the parser is allowed to recover from broken code.
    ///
    /// If this returns false, recovering broken code into valid code (especially if this recovery does lookahead)
    /// is not allowed. All recovery done by the parser must be gated behind this check.
    ///
    /// Technically, this only needs to restrict eager recovery by doing lookahead at more tokens.
    /// But making the distinction is very subtle, and simply forbidding all recovery is a lot simpler to uphold.
    #[inline]
    fn may_recover(&self) -> bool {
        matches!(self.recovery, Recovery::Allowed)
    }

    /// Version of [`unexpected`](Parser::unexpected) that "returns" any type in the `Ok`
    /// (both those functions never return "Ok", and so can lie like that in the type).
    pub fn unexpected_any<T>(&mut self) -> PResult<'a, T> {
        match self.expect_one_of(&[], &[]) {
            Err(e) => Err(e),
            // We can get `Ok(true)` from `recover_closing_delimiter`
            // which is called in `expected_one_of_not_found`.
            Ok(_) => FatalError.raise(),
        }
    }

    pub fn unexpected(&mut self) -> PResult<'a, ()> {
        self.unexpected_any()
    }

    /// Expects and consumes the token `t`. Signals an error if the next token is not `t`.
    pub fn expect(&mut self, exp: ExpTokenPair) -> PResult<'a, Recovered> {
        if self.expected_token_types.is_empty() {
            if self.token == exp.tok {
                self.bump();
                Ok(Recovered::No)
            } else {
                Err(self.unexpected_err(&exp.tok))
            }
        } else {
            self.expect_one_of(slice::from_ref(&exp), &[])
        }
    }

    /// Expect next token to be edible or inedible token. If edible,
    /// then consume it; if inedible, then return without consuming
    /// anything. Signal a fatal error if next token is unexpected.
    fn expect_one_of(
        &mut self,
        edible: &[ExpTokenPair],
        inedible: &[ExpTokenPair],
    ) -> PResult<'a, Recovered> {
        if edible.iter().any(|exp| exp.tok == self.token.kind) {
            self.bump();
            Ok(Recovered::No)
        } else if inedible.iter().any(|exp| exp.tok == self.token.kind) {
            // leave it in the input
            Ok(Recovered::No)
        } else if self.token != token::Eof
            && self.last_unexpected_token_span == Some(self.token.span)
        {
            FatalError.raise();
        } else {
            self.expected_one_of_not_found(edible, inedible)
                .map(|error_guaranteed| Recovered::Yes(error_guaranteed))
        }
    }

    // Public for rustfmt usage.
    pub fn parse_ident(&mut self) -> PResult<'a, Ident> {
        self.parse_ident_common(self.may_recover())
    }

    pub(crate) fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, Ident> {
        let (ident, is_raw) = self.ident_or_err(recover)?;

        if is_raw == IdentIsRaw::No && ident.is_reserved() {
            let err = self.expected_ident_found_err();
            if recover {
                err.emit();
            } else {
                return Err(err);
            }
        }
        self.bump();
        Ok(ident)
    }

    fn ident_or_err(&mut self, recover: bool) -> PResult<'a, (Ident, IdentIsRaw)> {
        match self.token.ident() {
            Some(ident) => Ok(ident),
            None => self.expected_ident_found(recover),
        }
    }

    /// Checks if the next token is `tok`, and returns `true` if so.
    ///
    /// This method will automatically add `tok` to `expected_token_types` if `tok` is not
    /// encountered.
    #[inline]
    pub fn check(&mut self, exp: ExpTokenPair) -> bool {
        let is_present = self.token == exp.tok;
        if !is_present {
            self.expected_token_types.insert(exp.token_type);
        }
        is_present
    }

    #[inline]
    #[must_use]
    fn check_noexpect(&self, tok: &TokenKind) -> bool {
        self.token == *tok
    }

    // Check the first token after the delimiter that closes the current
    // delimited sequence. (Panics if used in the outermost token stream, which
    // has no delimiters.) It uses a clone of the relevant tree cursor to skip
    // past the entire `TokenTree::Delimited` in a single step, avoiding the
    // need for unbounded token lookahead.
    //
    // Primarily used when `self.token` matches `OpenInvisible(_))`, to look
    // ahead through the current metavar expansion.
    fn check_noexpect_past_close_delim(&self, tok: &TokenKind) -> bool {
        let mut tree_cursor = self.token_cursor.stack.last().unwrap().clone();
        tree_cursor.bump();
        matches!(
            tree_cursor.curr(),
            Some(TokenTree::Token(token::Token { kind, .. }, _)) if kind == tok
        )
    }

    /// Consumes a token 'tok' if it exists. Returns whether the given token was present.
    ///
    /// the main purpose of this function is to reduce the cluttering of the suggestions list
    /// which using the normal eat method could introduce in some cases.
    #[inline]
    #[must_use]
    fn eat_noexpect(&mut self, tok: &TokenKind) -> bool {
        let is_present = self.check_noexpect(tok);
        if is_present {
            self.bump()
        }
        is_present
    }

    /// Consumes a token 'tok' if it exists. Returns whether the given token was present.
    #[inline]
    #[must_use]
    pub fn eat(&mut self, exp: ExpTokenPair) -> bool {
        let is_present = self.check(exp);
        if is_present {
            self.bump()
        }
        is_present
    }

    /// If the next token is the given keyword, returns `true` without eating it.
    /// An expectation is also added for diagnostics purposes.
    #[inline]
    #[must_use]
    fn check_keyword(&mut self, exp: ExpKeywordPair) -> bool {
        let is_keyword = self.token.is_keyword(exp.kw);
        if !is_keyword {
            self.expected_token_types.insert(exp.token_type);
        }
        is_keyword
    }

    #[inline]
    #[must_use]
    fn check_keyword_case(&mut self, exp: ExpKeywordPair, case: Case) -> bool {
        if self.check_keyword(exp) {
            true
        } else if case == Case::Insensitive
            && let Some((ident, IdentIsRaw::No)) = self.token.ident()
            // Do an ASCII case-insensitive match, because all keywords are ASCII.
            && ident.as_str().eq_ignore_ascii_case(exp.kw.as_str())
        {
            true
        } else {
            false
        }
    }

    /// If the next token is the given keyword, eats it and returns `true`.
    /// Otherwise, returns `false`. An expectation is also added for diagnostics purposes.
    // Public for rustc_builtin_macros and rustfmt usage.
    #[inline]
    #[must_use]
    pub fn eat_keyword(&mut self, exp: ExpKeywordPair) -> bool {
        let is_keyword = self.check_keyword(exp);
        if is_keyword {
            self.bump();
        }
        is_keyword
    }

    /// Eats a keyword, optionally ignoring the case.
    /// If the case differs (and is ignored) an error is issued.
    /// This is useful for recovery.
    #[inline]
    #[must_use]
    fn eat_keyword_case(&mut self, exp: ExpKeywordPair, case: Case) -> bool {
        if self.eat_keyword(exp) {
            true
        } else if case == Case::Insensitive
            && let Some((ident, IdentIsRaw::No)) = self.token.ident()
            // Do an ASCII case-insensitive match, because all keywords are ASCII.
            && ident.as_str().eq_ignore_ascii_case(exp.kw.as_str())
        {
            let kw = exp.kw.as_str();
            let is_upper = kw.chars().all(char::is_uppercase);
            let is_lower = kw.chars().all(char::is_lowercase);

            let case = match (is_upper, is_lower) {
                (true, true) => {
                    unreachable!("keyword that is both fully upper- and fully lowercase")
                }
                (true, false) => crate::diagnostics::Case::Upper,
                (false, true) => crate::diagnostics::Case::Lower,
                (false, false) => crate::diagnostics::Case::Mixed,
            };

            self.dcx().emit_err(crate::diagnostics::KwBadCase { span: ident.span, kw, case });
            self.bump();
            true
        } else {
            false
        }
    }

    /// If the next token is the given keyword, eats it and returns `true`.
    /// Otherwise, returns `false`. No expectation is added.
    // Public for rustc_builtin_macros usage.
    #[inline]
    #[must_use]
    pub fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
        let is_keyword = self.token.is_keyword(kw);
        if is_keyword {
            self.bump();
        }
        is_keyword
    }

    /// If the given word is not a keyword, signals an error.
    /// If the next token is not the given word, signals an error.
    /// Otherwise, eats it.
    pub fn expect_keyword(&mut self, exp: ExpKeywordPair) -> PResult<'a, ()> {
        if !self.eat_keyword(exp) { self.unexpected() } else { Ok(()) }
    }

    /// Consume a sequence produced by a metavar expansion, if present.
    pub fn eat_metavar_seq<T>(
        &mut self,
        mv_kind: MetaVarKind,
        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
    ) -> Option<T> {
        self.eat_metavar_seq_with_matcher(|mvk| mvk == mv_kind, f)
    }

    /// A slightly more general form of `eat_metavar_seq`, for use with the
    /// `MetaVarKind` variants that have parameters, where an exact match isn't
    /// desired.
    fn eat_metavar_seq_with_matcher<T>(
        &mut self,
        match_mv_kind: impl Fn(MetaVarKind) -> bool,
        mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
    ) -> Option<T> {
        if let token::OpenInvisible(InvisibleOrigin::MetaVar(mv_kind)) = self.token.kind
            && match_mv_kind(mv_kind)
        {
            self.bump();

            // Recovery is disabled when parsing macro arguments, so it must
            // also be disabled when reparsing pasted macro arguments,
            // otherwise we get inconsistent results (e.g. #137874).
            let res = self.with_recovery(Recovery::Forbidden, |this| f(this));

            let res = match res {
                Ok(res) => res,
                Err(err) => {
                    // This can occur in unusual error cases, e.g. #139445.
                    err.delay_as_bug();
                    return None;
                }
            };

            if let token::CloseInvisible(InvisibleOrigin::MetaVar(mv_kind)) = self.token.kind
                && match_mv_kind(mv_kind)
            {
                self.bump();
                Some(res)
            } else {
                // This can occur when invalid syntax is passed to a decl macro. E.g. see #139248,
                // where the reparse attempt of an invalid expr consumed the trailing invisible
                // delimiter.
                self.dcx()
                    .span_delayed_bug(self.token.span, "no close delim with reparsing {mv_kind:?}");
                None
            }
        } else {
            None
        }
    }

    /// Is the given keyword `kw` followed by a non-reserved identifier?
    fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool {
        self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_non_reserved_ident())
    }

    #[inline]
    fn check_or_expected(&mut self, ok: bool, token_type: TokenType) -> bool {
        if !ok {
            self.expected_token_types.insert(token_type);
        }
        ok
    }

    fn check_ident(&mut self) -> bool {
        self.check_or_expected(self.token.is_ident(), TokenType::Ident)
    }

    fn check_path(&mut self) -> bool {
        self.check_or_expected(self.token.is_path_start(), TokenType::Path)
    }

    fn check_type(&mut self) -> bool {
        self.check_or_expected(self.token.can_begin_type(), TokenType::Type)
    }

    fn check_const_arg(&mut self) -> bool {
        let is_mcg_arg = self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const);
        let is_mgca_arg = self.is_keyword_ahead(0, &[kw::Const])
            && self.look_ahead(1, |t| *t == token::OpenBrace);
        is_mcg_arg || is_mgca_arg
    }

    fn check_const_closure(&self) -> bool {
        self.is_keyword_ahead(0, &[kw::Const])
            && self.look_ahead(1, |t| match &t.kind {
                // async closures do not work with const closures, so we do not parse that here.
                token::Ident(kw::Move | kw::Use | kw::Static, IdentIsRaw::No)
                | token::OrOr
                | token::Or => true,
                _ => false,
            })
    }

    fn check_inline_const(&self, dist: usize) -> bool {
        self.is_keyword_ahead(dist, &[kw::Const])
            && self.look_ahead(dist + 1, |t| match &t.kind {
                token::OpenBrace => true,
                token::OpenInvisible(InvisibleOrigin::MetaVar(MetaVarKind::Block)) => true,
                _ => false,
            })
    }

    /// Checks to see if the next token is either `+` or `+=`.
    /// Otherwise returns `false`.
    #[inline]
    fn check_plus(&mut self) -> bool {
        self.check_or_expected(self.token.is_like_plus(), TokenType::Plus)
    }

    /// Eats the expected token if it's present possibly breaking
    /// compound tokens like multi-character operators in process.
    /// Returns `true` if the token was eaten.
    fn break_and_eat(&mut self, exp: ExpTokenPair) -> bool {
        if self.token == exp.tok {
            self.bump();
            return true;
        }
        match self.token.kind.break_two_token_op(1) {
            Some((first, second)) if first == exp.tok => {
                let first_span = self.psess.source_map().start_point(self.token.span);
                let second_span = self.token.span.with_lo(first_span.hi());
                self.token = Token::new(first, first_span);
                // Keep track of this token - if we end token capturing now,
                // we'll want to append this token to the captured stream.
                //
                // If we consume any additional tokens, then this token
                // is not needed (we'll capture the entire 'glued' token),
                // and `bump` will set this field to 0.
                self.break_last_token += 1;
                // Use the spacing of the glued token as the spacing of the
                // unglued second token.
                self.bump_with((Token::new(second, second_span), self.token_spacing));
                true
            }
            _ => {
                self.expected_token_types.insert(exp.token_type);
                false
            }
        }
    }

    /// Eats `+` possibly breaking tokens like `+=` in process.
    fn eat_plus(&mut self) -> bool {
        self.break_and_eat(exp!(Plus))
    }

    /// Eats `&` possibly breaking tokens like `&&` in process.
    /// Signals an error if `&` is not eaten.
    fn expect_and(&mut self) -> PResult<'a, ()> {
        if self.break_and_eat(exp!(And)) { Ok(()) } else { self.unexpected() }
    }

    /// Eats `|` possibly breaking tokens like `||` in process.
    /// Signals an error if `|` was not eaten.
    fn expect_or(&mut self) -> PResult<'a, ()> {
        if self.break_and_eat(exp!(Or)) { Ok(()) } else { self.unexpected() }
    }

    /// Eats `<` possibly breaking tokens like `<<` in process.
    fn eat_lt(&mut self) -> bool {
        let ate = self.break_and_eat(exp!(Lt));
        if ate {
            // See doc comment for `unmatched_angle_bracket_count`.
            self.unmatched_angle_bracket_count += 1;
            debug!("eat_lt: (increment) count={:?}", self.unmatched_angle_bracket_count);
        }
        ate
    }

    /// Eats `<` possibly breaking tokens like `<<` in process.
    /// Signals an error if `<` was not eaten.
    fn expect_lt(&mut self) -> PResult<'a, ()> {
        if self.eat_lt() { Ok(()) } else { self.unexpected() }
    }

    /// Eats `>` possibly breaking tokens like `>>` in process.
    /// Signals an error if `>` was not eaten.
    fn expect_gt(&mut self) -> PResult<'a, ()> {
        if self.break_and_eat(exp!(Gt)) {
            // See doc comment for `unmatched_angle_bracket_count`.
            if self.unmatched_angle_bracket_count > 0 {
                self.unmatched_angle_bracket_count -= 1;
                debug!("expect_gt: (decrement) count={:?}", self.unmatched_angle_bracket_count);
            }
            Ok(())
        } else {
            self.unexpected()
        }
    }

    /// Checks if the next token is contained within `closes`, and returns `true` if so.
    fn expect_any_with_type(
        &mut self,
        closes_expected: &[ExpTokenPair],
        closes_not_expected: &[&TokenKind],
    ) -> bool {
        closes_expected.iter().any(|&close| self.check(close))
            || closes_not_expected.iter().any(|k| self.check_noexpect(k))
    }

    /// Parses a sequence until the specified delimiters. The function
    /// `f` must consume tokens until reaching the next separator or
    /// closing bracket.
    fn parse_seq_to_before_tokens<T>(
        &mut self,
        closes_expected: &[ExpTokenPair],
        closes_not_expected: &[&TokenKind],
        sep: SeqSep,
        mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
    ) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
        let mut first = true;
        let mut recovered = Recovered::No;
        let mut trailing = Trailing::No;
        let mut v = ThinVec::new();

        while !self.expect_any_with_type(closes_expected, closes_not_expected) {
            if self.token.kind.is_close_delim_or_eof() {
                break;
            }
            if let Some(exp) = sep.sep {
                if first {
                    // no separator for the first element
                    first = false;
                } else {
                    // check for separator
                    match self.expect(exp) {
                        Ok(Recovered::No) => {
                            self.current_closure.take();
                        }
                        Ok(Recovered::Yes(guar)) => {
                            self.current_closure.take();
                            recovered = Recovered::Yes(guar);
                            break;
                        }
                        Err(mut expect_err) => {
                            let sp = self.prev_token.span.shrink_to_hi();
                            let token_str = pprust::token_kind_to_string(&exp.tok);

                            match self.current_closure.take() {
                                Some(closure_spans) if self.token == TokenKind::Semi => {
                                    // Finding a semicolon instead of a comma
                                    // after a closure body indicates that the
                                    // closure body may be a block but the user
                                    // forgot to put braces around its
                                    // statements.

                                    self.recover_missing_braces_around_closure_body(
                                        closure_spans,
                                        expect_err,
                                    )?;

                                    continue;
                                }

                                _ => {
                                    // Attempt to keep parsing if it was a similar separator.
                                    if exp.tok.similar_tokens().contains(&self.token.kind) {
                                        self.bump();
                                    }
                                }
                            }

                            // If this was a missing `@` in a binding pattern
                            // bail with a suggestion
                            // https://github.com/rust-lang/rust/issues/72373
                            if self.prev_token.is_ident() && self.token == token::DotDot {
                                let msg = format!(
                                    "if you meant to bind the contents of the rest of the array \
                                     pattern into `{}`, use `@`",
                                    pprust::token_to_string(&self.prev_token)
                                );
                                expect_err
                                    .with_span_suggestion_verbose(
                                        self.prev_token.span.shrink_to_hi().until(self.token.span),
                                        msg,
                                        " @ ",
                                        Applicability::MaybeIncorrect,
                                    )
                                    .emit();
                                break;
                            }

                            // Attempt to keep parsing if it was an omitted separator.
                            // `&raw <expr>` already has a specific suggestion for missing
                            // `const`/`mut`, so don't recover `<expr>` as the next element in
                            // a comma-separated list.
                            if exp.token_type == TokenType::Comma && self.is_expected_raw_ref_mut()
                            {
                                return Err(expect_err);
                            }
                            self.last_unexpected_token_span = None;
                            match f(self) {
                                Ok(t) => {
                                    // Parsed successfully, therefore most probably the code only
                                    // misses a separator.
                                    expect_err
                                        .with_span_suggestion_short(
                                            sp,
                                            format!("missing `{token_str}`"),
                                            token_str,
                                            Applicability::MaybeIncorrect,
                                        )
                                        .emit();

                                    v.push(t);
                                    continue;
                                }
                                Err(e) => {
                                    // Parsing failed, therefore it must be something more serious
                                    // than just a missing separator.
                                    for xx in &e.children {
                                        // Propagate the help message from sub error `e` to main
                                        // error `expect_err`.
                                        expect_err.children.push(xx.clone());
                                    }
                                    e.cancel();
                                    if self.token == token::Colon {
                                        // We will try to recover in
                                        // `maybe_recover_struct_lit_bad_delims`.
                                        return Err(expect_err);
                                    } else if let [exp] = closes_expected
                                        && exp.token_type == TokenType::CloseParen
                                    {
                                        return Err(expect_err);
                                    } else {
                                        expect_err.emit();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if sep.trailing_sep_allowed
                && self.expect_any_with_type(closes_expected, closes_not_expected)
            {
                trailing = Trailing::Yes;
                break;
            }

            let t = f(self)?;
            v.push(t);
        }

        Ok((v, trailing, recovered))
    }

    fn recover_missing_braces_around_closure_body(
        &mut self,
        closure_spans: ClosureSpans,
        mut expect_err: Diag<'_>,
    ) -> PResult<'a, ()> {
        let initial_semicolon = self.token.span;

        while self.eat(exp!(Semi)) {
            let _ = self
                .parse_stmt_without_recovery(false, ForceCollect::No, false)
                .unwrap_or_else(|e| {
                    e.cancel();
                    None
                });
        }

        expect_err
            .primary_message("closure bodies that contain statements must be surrounded by braces");

        let preceding_pipe_span = closure_spans.closing_pipe;
        let following_token_span = self.token.span;

        let mut first_note = MultiSpan::from(vec![initial_semicolon]);
        first_note.push_span_label(
            initial_semicolon,
            "this `;` turns the preceding closure into a statement",
        );
        first_note.push_span_label(
            closure_spans.body,
            "this expression is a statement because of the trailing semicolon",
        );
        expect_err.span_note(first_note, "statement found outside of a block");

        let mut second_note = MultiSpan::from(vec![closure_spans.whole_closure]);
        second_note.push_span_label(closure_spans.whole_closure, "this is the parsed closure...");
        second_note.push_span_label(
            following_token_span,
            "...but likely you meant the closure to end here",
        );
        expect_err.span_note(second_note, "the closure body may be incorrectly delimited");

        expect_err.span(vec![preceding_pipe_span, following_token_span]);

        let opening_suggestion_str = " {".to_string();
        let closing_suggestion_str = "}".to_string();

        expect_err.multipart_suggestion(
            "try adding braces",
            vec![
                (preceding_pipe_span.shrink_to_hi(), opening_suggestion_str),
                (following_token_span.shrink_to_lo(), closing_suggestion_str),
            ],
            Applicability::MaybeIncorrect,
        );

        expect_err.emit();

        Ok(())
    }

    /// Parses a sequence, not including the delimiters. The function
    /// `f` must consume tokens until reaching the next separator or
    /// closing bracket.
    fn parse_seq_to_before_end<T>(
        &mut self,
        close: ExpTokenPair,
        sep: SeqSep,
        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
    ) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
        self.parse_seq_to_before_tokens(&[close], &[], sep, f)
    }

    /// Parses a sequence, including only the closing delimiter. The function
    /// `f` must consume tokens until reaching the next separator or
    /// closing bracket.
    fn parse_seq_to_end<T>(
        &mut self,
        close: ExpTokenPair,
        sep: SeqSep,
        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
    ) -> PResult<'a, (ThinVec<T>, Trailing)> {
        let (val, trailing, recovered) = self.parse_seq_to_before_end(close, sep, f)?;
        if matches!(recovered, Recovered::No) && !self.eat(close) {
            self.dcx().span_delayed_bug(
                self.token.span,
                "recovered but `parse_seq_to_before_end` did not give us the close token",
            );
        }
        Ok((val, trailing))
    }

    /// Parses a sequence, including both delimiters. The function
    /// `f` must consume tokens until reaching the next separator or
    /// closing bracket.
    fn parse_unspanned_seq<T>(
        &mut self,
        open: ExpTokenPair,
        close: ExpTokenPair,
        sep: SeqSep,
        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
    ) -> PResult<'a, (ThinVec<T>, Trailing)> {
        self.expect(open)?;
        self.parse_seq_to_end(close, sep, f)
    }

    /// Parses a comma-separated sequence, including both delimiters.
    /// The function `f` must consume tokens until reaching the next separator or
    /// closing bracket.
    pub fn parse_delim_comma_seq<T>(
        &mut self,
        open: ExpTokenPair,
        close: ExpTokenPair,
        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
    ) -> PResult<'a, (ThinVec<T>, Trailing)> {
        self.parse_unspanned_seq(open, close, SeqSep::trailing_allowed(exp!(Comma)), f)
    }

    /// Parses a comma-separated sequence delimited by parentheses (e.g. `(x, y)`).
    /// The function `f` must consume tokens until reaching the next separator or
    /// closing bracket.
    pub fn parse_paren_comma_seq<T>(
        &mut self,
        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
    ) -> PResult<'a, (ThinVec<T>, Trailing)> {
        self.parse_delim_comma_seq(exp!(OpenParen), exp!(CloseParen), f)
    }

    /// Advance the parser by one token using provided token as the next one.
    fn bump_with(&mut self, next: (Token, Spacing)) {
        self.inlined_bump_with(next)
    }

    /// This always-inlined version should only be used on hot code paths.
    #[inline(always)]
    fn inlined_bump_with(&mut self, (next_token, next_spacing): (Token, Spacing)) {
        // Update the current and previous tokens.
        self.prev_token = mem::replace(&mut self.token, next_token);
        self.token_spacing = next_spacing;

        // Diagnostics.
        self.expected_token_types.clear();
    }

    /// Advance the parser by one token.
    pub fn bump(&mut self) {
        // Note: destructuring here would give nicer code, but it was found in #96210 to be slower
        // than `.0`/`.1` access.
        let mut next = self.token_cursor.inlined_next();
        self.num_bump_calls += 1;
        // We got a token from the underlying cursor and no longer need to
        // worry about an unglued token. See `break_and_eat` for more details.
        self.break_last_token = 0;
        if next.0.span.is_dummy() {
            // Tweak the location for better diagnostics, but keep syntactic context intact.
            let fallback_span = self.token.span;
            next.0.span = fallback_span.with_ctxt(next.0.span.ctxt());
        }
        debug_assert!(!matches!(
            next.0.kind,
            token::OpenInvisible(origin) | token::CloseInvisible(origin) if origin.skip()
        ));
        self.inlined_bump_with(next)
    }

    /// Look-ahead `dist` tokens of `self.token` and get access to that token there.
    /// When `dist == 0` then the current token is looked at. `Eof` will be
    /// returned if the look-ahead is any distance past the end of the tokens.
    pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R {
        if dist == 0 {
            return looker(&self.token);
        }

        // Typically around 98% of the `dist > 0` cases have `dist == 1`, so we
        // have a fast special case for that.
        if dist == 1 {
            // The index is zero because the tree cursor's index always points
            // to the next token to be gotten.
            match self.token_cursor.curr.curr() {
                Some(tree) => {
                    // Indexing stayed within the current token tree.
                    match tree {
                        TokenTree::Token(token, _) => return looker(token),
                        &TokenTree::Delimited(dspan, _, delim, _) => {
                            if !delim.skip() {
                                return looker(&Token::new(delim.as_open_token_kind(), dspan.open));
                            }
                        }
                    }
                }
                None => {
                    // The tree cursor lookahead went (one) past the end of the
                    // current token tree. Try to return a close delimiter.
                    if let Some(last) = self.token_cursor.stack.last()
                        && let Some(&TokenTree::Delimited(span, _, delim, _)) = last.curr()
                        && !delim.skip()
                    {
                        // We are not in the outermost token stream, so we have
                        // delimiters. Also, those delimiters are not skipped.
                        return looker(&Token::new(delim.as_close_token_kind(), span.close));
                    }
                }
            }
        }

        // Just clone the token cursor and use `next`, skipping delimiters as
        // necessary. Slow but simple.
        let mut cursor = self.token_cursor.clone();
        let mut i = 0;
        let mut token = Token::dummy();
        while i < dist {
            token = cursor.next().0;
            if let token::OpenInvisible(origin) | token::CloseInvisible(origin) = token.kind
                && origin.skip()
            {
                continue;
            }
            i += 1;
        }
        looker(&token)
    }

    /// Like `lookahead`, but skips over token trees rather than tokens. Useful
    /// when looking past possible metavariable pasting sites.
    pub fn tree_look_ahead<R>(
        &self,
        dist: usize,
        looker: impl FnOnce(&TokenTree) -> R,
    ) -> Option<R> {
        assert_ne!(dist, 0);
        self.token_cursor.curr.look_ahead(dist - 1).map(looker)
    }

    /// Returns whether any of the given keywords are `dist` tokens ahead of the current one.
    pub(crate) fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool {
        self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw)))
    }

    /// Parses asyncness: `async` or nothing.
    fn parse_coroutine_kind(&mut self, case: Case) -> Option<CoroutineKind> {
        let span = self.token_uninterpolated_span();
        if self.eat_keyword_case(exp!(Async), case) {
            // FIXME(gen_blocks): Do we want to unconditionally parse `gen` and then
            // error if edition <= 2024, like we do with async and edition <= 2018?
            if self.token_uninterpolated_span().at_least_rust_2024()
                && self.eat_keyword_case(exp!(Gen), case)
            {
                let gen_span = self.prev_token_uninterpolated_span();
                Some(CoroutineKind::AsyncGen {
                    span: span.to(gen_span),
                    closure_id: DUMMY_NODE_ID,
                    return_impl_trait_id: DUMMY_NODE_ID,
                })
            } else {
                Some(CoroutineKind::Async {
                    span,
                    closure_id: DUMMY_NODE_ID,
                    return_impl_trait_id: DUMMY_NODE_ID,
                })
            }
        } else if self.token_uninterpolated_span().at_least_rust_2024()
            && self.eat_keyword_case(exp!(Gen), case)
        {
            Some(CoroutineKind::Gen {
                span,
                closure_id: DUMMY_NODE_ID,
                return_impl_trait_id: DUMMY_NODE_ID,
            })
        } else {
            None
        }
    }

    /// Parses fn unsafety: `unsafe`, `safe` or nothing.
    fn parse_safety(&mut self, case: Case) -> Safety {
        if self.eat_keyword_case(exp!(Unsafe), case) {
            Safety::Unsafe(self.prev_token_uninterpolated_span())
        } else if self.eat_keyword_case(exp!(Safe), case) {
            Safety::Safe(self.prev_token_uninterpolated_span())
        } else {
            Safety::Default
        }
    }

    /// Parses constness: `const` or nothing.
    fn parse_constness(&mut self, case: Case) -> Const {
        self.parse_constness_(case, false)
    }

    /// Parses constness for closures (case sensitive, feature-gated)
    fn parse_closure_constness(&mut self) -> Const {
        let constness = self.parse_constness_(Case::Sensitive, true);
        if let Const::Yes(span) = constness {
            self.psess.gated_spans.gate(sym::const_closures, span);
        }
        constness
    }

    fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
        // Avoid const blocks and const closures to be parsed as const items
        if (self.check_const_closure() == is_closure)
            && !self.look_ahead(1, |t| *t == token::OpenBrace || t.is_metavar_block())
            && self.eat_keyword_case(exp!(Const), case)
        {
            Const::Yes(self.prev_token_uninterpolated_span())
        } else {
            Const::No
        }
    }

    /// Parses inline const expressions.
    fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, Box<Expr>> {
        self.expect_keyword(exp!(Const))?;
        let (attrs, blk) = self.parse_inner_attrs_and_block(None)?;
        let anon_const = AnonConst {
            id: DUMMY_NODE_ID,
            value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
        };
        let blk_span = anon_const.value.span;
        let kind = if pat {
            let guar = self
                .dcx()
                .struct_span_err(blk_span, "const blocks cannot be used as patterns")
                .with_help(
                    "use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead",
                )
                .emit();
            ExprKind::Err(guar)
        } else {
            ExprKind::ConstBlock(anon_const)
        };
        Ok(self.mk_expr_with_attrs(span.to(blk_span), kind, attrs))
    }

    /// Parse nothing or `mut`.
    fn parse_mutability(&mut self) -> Mutability {
        if self.eat_keyword(exp!(Mut)) { Mutability::Mut } else { Mutability::Not }
    }

    /// Parse nothing or a by-reference mode.
    ///
    /// ```ebnf
    /// ByRef = "ref" PinAndMut?
    /// ```
    fn parse_byref(&mut self) -> ByRef {
        if self.eat_keyword(exp!(Ref)) {
            let (pinnedness, mutability) = self.parse_pin_and_mut();
            ByRef::Yes(pinnedness, mutability)
        } else {
            ByRef::No
        }
    }

    /// Parse nothing or "explicit" mutability.
    ///
    /// ```ebnf
    /// MutOrConst = "mut" | "const"
    /// ```
    fn parse_mut_or_const(&mut self) -> Option<Mutability> {
        if self.eat_keyword(exp!(Mut)) {
            Some(Mutability::Mut)
        } else if self.eat_keyword(exp!(Const)) {
            Some(Mutability::Not)
        } else {
            None
        }
    }

    /// Parse a field name.
    ///
    /// ```enbf
    /// FieldName = IntLit | Ident
    /// ```
    pub fn parse_field_name(&mut self) -> PResult<'a, Ident> {
        if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind
        {
            if let Some(suffix) = suffix {
                self.dcx().emit_err(crate::diagnostics::InvalidLiteralSuffixOnTupleIndex {
                    span: self.token.span,
                    suffix,
                });
            }
            self.bump();
            Ok(Ident::new(symbol, self.prev_token.span))
        } else {
            self.parse_ident_common(true)
        }
    }

    fn parse_delim_args(&mut self) -> PResult<'a, Box<DelimArgs>> {
        if let Some(args) = self.parse_delim_args_inner() {
            Ok(Box::new(args))
        } else {
            self.unexpected_any()
        }
    }

    fn parse_attr_args(&mut self) -> PResult<'a, AttrArgs> {
        Ok(if let Some(args) = self.parse_delim_args_inner() {
            AttrArgs::Delimited(args)
        } else if self.eat(exp!(Eq)) {
            let eq_span = self.prev_token.span;
            let expr = self.parse_expr_force_collect()?;
            AttrArgs::Eq { eq_span, expr }
        } else {
            AttrArgs::Empty
        })
    }

    fn parse_delim_args_inner(&mut self) -> Option<DelimArgs> {
        let delimited = self.check(exp!(OpenParen))
            || self.check(exp!(OpenBracket))
            || self.check(exp!(OpenBrace));

        delimited.then(|| {
            let TokenTree::Delimited(dspan, _, delim, tokens) = self.parse_token_tree() else {
                unreachable!()
            };
            DelimArgs { dspan, delim, tokens }
        })
    }

    /// Parses a single token tree from the input.
    pub fn parse_token_tree(&mut self) -> TokenTree {
        if self.token.kind.open_delim().is_some() {
            // Clone the `TokenTree::Delimited` that we are currently
            // within. That's what we are going to return.
            let tree = self.token_cursor.stack.last().unwrap().curr().unwrap().clone();
            debug_assert_matches!(tree, TokenTree::Delimited(..));

            // Advance the token cursor through the entire delimited
            // sequence. After getting the `OpenDelim` we are *within* the
            // delimited sequence, i.e. at depth `d`. After getting the
            // matching `CloseDelim` we are *after* the delimited sequence,
            // i.e. at depth `d - 1`.
            let target_depth = self.token_cursor.stack.len() - 1;

            if let Capturing::No = self.capture_state.capturing {
                // We are not capturing tokens, so skip to the end of the
                // delimited sequence. This is a perf win when dealing with
                // declarative macros that pass large `tt` fragments through
                // multiple rules, as seen in the uom-0.37.0 crate.
                self.token_cursor.curr.bump_to_end();
                self.bump();
                debug_assert_eq!(self.token_cursor.stack.len(), target_depth);
            } else {
                loop {
                    // Advance one token at a time, so `TokenCursor::next()`
                    // can capture these tokens if necessary.
                    self.bump();
                    if self.token_cursor.stack.len() == target_depth {
                        break;
                    }
                }
            }
            debug_assert!(self.token.kind.close_delim().is_some());

            // Consume close delimiter
            self.bump();
            tree
        } else {
            assert!(!self.token.kind.is_close_delim_or_eof());
            let prev_spacing = self.token_spacing;
            self.bump();
            TokenTree::Token(self.prev_token, prev_spacing)
        }
    }

    pub fn parse_tokens(&mut self) -> TokenStream {
        let mut result = Vec::new();
        loop {
            if self.token.kind.is_close_delim_or_eof() {
                break;
            } else {
                result.push(self.parse_token_tree());
            }
        }
        TokenStream::new(result)
    }

    /// Evaluates the closure with restrictions in place.
    ///
    /// Afters the closure is evaluated, restrictions are reset.
    fn with_res<T>(&mut self, res: Restrictions, f: impl FnOnce(&mut Self) -> T) -> T {
        let old = self.restrictions;
        self.restrictions = res;
        let res = f(self);
        self.restrictions = old;
        res
    }

    /// Parses `pub` and `pub(in path)` plus shortcuts `pub(crate)` for `pub(in crate)`, `pub(self)`
    /// for `pub(in self)` and `pub(super)` for `pub(in super)`.
    /// If the following element can't be a tuple (i.e., it's a function definition), then
    /// it's not a tuple struct field), and the contents within the parentheses aren't valid,
    /// so emit a proper diagnostic.
    // Public for rustfmt usage.
    pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> {
        if let Some(vis) = self
            .eat_metavar_seq(MetaVarKind::Vis, |this| this.parse_visibility(FollowedByType::Yes))
        {
            return Ok(vis);
        }

        if !self.eat_keyword(exp!(Pub)) {
            // We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
            // keyword to grab a span from for inherited visibility; an empty span at the
            // beginning of the current token would seem to be the "Schelling span".
            return Ok(Visibility {
                span: self.token.span.shrink_to_lo(),
                kind: VisibilityKind::Inherited,
            });
        }
        let lo = self.prev_token.span;

        if self.check(exp!(OpenParen)) {
            // We don't `self.bump()` the `(` yet because this might be a struct definition where
            // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`.
            // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so
            // by the following tokens.
            if self.is_keyword_ahead(1, &[kw::In]) {
                // Parse `pub(in path)`.
                self.bump(); // `(`
                self.bump(); // `in`
                let path = self.parse_path(PathStyle::Mod)?; // `path`
                self.expect(exp!(CloseParen))?; // `)`
                let vis = VisibilityKind::Restricted {
                    path: Box::new(path),
                    id: ast::DUMMY_NODE_ID,
                    shorthand: false,
                };
                return Ok(Visibility { span: lo.to(self.prev_token.span), kind: vis });
            } else if self.look_ahead(2, |t| t == &token::CloseParen)
                && self.is_keyword_ahead(1, &[kw::Crate, kw::Super, kw::SelfLower])
            {
                // Parse `pub(crate)`, `pub(self)`, or `pub(super)`.
                self.bump(); // `(`
                let path = self.parse_path(PathStyle::Mod)?; // `crate`/`super`/`self`
                self.expect(exp!(CloseParen))?; // `)`
                let vis = VisibilityKind::Restricted {
                    path: Box::new(path),
                    id: ast::DUMMY_NODE_ID,
                    shorthand: true,
                };
                return Ok(Visibility { span: lo.to(self.prev_token.span), kind: vis });
            } else if let FollowedByType::No = fbt {
                // Provide this diagnostic if a type cannot follow;
                // in particular, if this is not a tuple struct.
                self.recover_incorrect_vis_restriction()?;
                // Emit diagnostic, but continue with public visibility.
            }
        }

        Ok(Visibility { span: lo, kind: VisibilityKind::Public })
    }

    /// Recovery for e.g. `pub(something) fn ...` or `struct X { pub(something) y: Z }`
    fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> {
        self.bump(); // `(`
        let path = self.parse_path(PathStyle::Mod)?;
        self.expect(exp!(CloseParen))?; // `)`

        let path_str = pprust::path_to_string(&path);
        self.dcx()
            .emit_err(IncorrectVisibilityRestriction { span: path.span, inner_str: path_str });

        Ok(())
    }

    /// Parses an optional `impl` restriction.
    /// Enforces the `impl_restriction` feature gate whenever an explicit restriction is encountered.
    fn parse_impl_restriction(&mut self) -> PResult<'a, ImplRestriction> {
        if self.eat_keyword(exp!(Impl)) {
            let (kind, span, gated_span) = self.parse_restriction(ParsingRestrictionKind::Impl)?;
            self.psess.gated_spans.gate(sym::impl_restriction, gated_span);
            return Ok(ImplRestriction { kind, span });
        }
        Ok(ImplRestriction {
            kind: RestrictionKind::Unrestricted,
            span: self.token.span.shrink_to_lo(),
        })
    }

    /// Parses an optional `mut` restriction.
    /// Enforces the `mut_restriction` feature gate whenever an explicit restriction is encountered.
    fn parse_mut_restriction(&mut self) -> PResult<'a, MutRestriction> {
        if self.eat_keyword(exp!(Mut)) {
            let (kind, span, gated_span) = self.parse_restriction(ParsingRestrictionKind::Mut)?;
            self.psess.gated_spans.gate(sym::mut_restriction, gated_span);
            return Ok(MutRestriction { kind, span });
        }
        Ok(MutRestriction {
            kind: RestrictionKind::Unrestricted,
            span: self.token.span.shrink_to_lo(),
        })
    }

    /// Parses `impl` or `mut` restrictions.
    /// Returns the parsed restriction and its span, as well as the gated span.
    fn parse_restriction(
        &mut self,
        restriction_kind: ParsingRestrictionKind,
    ) -> PResult<'a, (RestrictionKind, Span, Span)> {
        let lo = self.prev_token.span;
        // No units or tuples are allowed to follow `impl` or `mut` here, so we can safely bump `(`.
        self.expect(exp!(OpenParen))?;
        if self.eat_keyword(exp!(In)) {
            let path = self.parse_path(PathStyle::Mod)?; // `in path`
            self.expect(exp!(CloseParen))?; // `)`
            let restriction = RestrictionKind::Restricted {
                path: Box::new(path),
                id: ast::DUMMY_NODE_ID,
                shorthand: false,
            };
            let span = lo.to(self.prev_token.span);
            Ok((restriction, span, span))
        } else if self.look_ahead(1, |t| t == &token::CloseParen)
            && self.is_keyword_ahead(0, &[kw::Crate, kw::Super, kw::SelfLower])
        {
            let path = self.parse_path(PathStyle::Mod)?; // `crate`/`super`/`self`
            self.expect(exp!(CloseParen))?; // `)`
            let restriction = RestrictionKind::Restricted {
                path: Box::new(path),
                id: ast::DUMMY_NODE_ID,
                shorthand: true,
            };
            let span = lo.to(self.prev_token.span);
            Ok((restriction, span, span))
        } else {
            // Emit diagnostic, but continue with no restrictions.
            // Recovery for `impl(something) trait` or `mut (something) field`.
            let path = self.parse_path(PathStyle::Mod)?;
            self.expect(exp!(CloseParen))?; // `)`
            let path_str = pprust::path_to_string(&path);
            let end = self.prev_token.span;
            match restriction_kind {
                ParsingRestrictionKind::Impl => {
                    self.dcx().emit_err(IncorrectImplRestriction {
                        span: path.span,
                        inner_str: path_str,
                    });
                }
                ParsingRestrictionKind::Mut => {
                    self.dcx()
                        .emit_err(IncorrectMutRestriction { span: path.span, inner_str: path_str });
                }
            }
            Ok((RestrictionKind::Unrestricted, self.token.span.shrink_to_lo(), lo.to(end)))
        }
    }

    /// Parses `extern string_literal?`.
    fn parse_extern(&mut self, case: Case) -> Extern {
        if self.eat_keyword_case(exp!(Extern), case) {
            let mut extern_span = self.prev_token.span;
            let abi = self.parse_abi();
            if let Some(abi) = abi {
                extern_span = extern_span.to(abi.span);
            }
            Extern::from_abi(abi, extern_span)
        } else {
            Extern::None
        }
    }

    /// Parses a string literal as an ABI spec.
    fn parse_abi(&mut self) -> Option<StrLit> {
        match self.parse_str_lit() {
            Ok(str_lit) => Some(str_lit),
            Err(Some(lit)) => match lit.kind {
                ast::LitKind::Err(_) => None,
                _ => {
                    self.dcx().emit_err(NonStringAbiLiteral { span: lit.span });
                    None
                }
            },
            Err(None) => None,
        }
    }

    fn collect_tokens_no_attrs<R: HasTokens>(
        &mut self,
        f: impl FnOnce(&mut Self) -> PResult<'a, R>,
    ) -> PResult<'a, R> {
        // The only reason to call `collect_tokens_no_attrs` is if you want tokens, so use
        // `ForceCollect::Yes`
        self.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |this, _attrs| {
            Ok((f(this)?, Trailing::No, UsePreAttrPos::No))
        })
    }

    /// Checks for `::` or, potentially, `:::` and then look ahead after it.
    fn check_path_sep_and_look_ahead(&mut self, looker: impl Fn(&Token) -> bool) -> bool {
        if self.check(exp!(PathSep)) {
            if self.may_recover() && self.look_ahead(1, |t| t.kind == token::Colon) {
                debug_assert!(!self.look_ahead(1, &looker), "Looker must not match on colon");
                self.look_ahead(2, looker)
            } else {
                self.look_ahead(1, looker)
            }
        } else {
            false
        }
    }

    /// `::{` or `::*`
    fn is_import_coupler(&mut self) -> bool {
        self.check_path_sep_and_look_ahead(|t| matches!(t.kind, token::OpenBrace | token::Star))
    }

    // Debug view of the parser's token stream, up to `{lookahead}` tokens.
    // Only used when debugging.
    #[allow(unused)]
    pub(crate) fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug {
        fmt::from_fn(move |f| {
            let mut dbg_fmt = f.debug_struct("Parser"); // or at least, one view of

            // we don't need N spans, but we want at least one, so print all of prev_token
            dbg_fmt.field("prev_token", &self.prev_token);
            let mut tokens = vec![];
            for i in 0..lookahead {
                let tok = self.look_ahead(i, |tok| tok.kind);
                let is_eof = tok == TokenKind::Eof;
                tokens.push(tok);
                if is_eof {
                    // Don't look ahead past EOF.
                    break;
                }
            }
            dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish());
            dbg_fmt.field("approx_token_stream_pos", &self.num_bump_calls);

            // some fields are interesting for certain values, as they relate to macro parsing
            if let Some(subparser) = self.subparser_name {
                dbg_fmt.field("subparser_name", &subparser);
            }
            if let Recovery::Forbidden = self.recovery {
                dbg_fmt.field("recovery", &self.recovery);
            }

            // imply there's "more to know" than this view
            dbg_fmt.finish_non_exhaustive()
        })
    }

    pub fn clear_expected_token_types(&mut self) {
        self.expected_token_types.clear();
    }

    pub fn approx_token_stream_pos(&self) -> u32 {
        self.num_bump_calls
    }

    /// For interpolated `self.token`, returns a span of the fragment to which
    /// the interpolated token refers. For all other tokens this is just a
    /// regular span. It is particularly important to use this for identifiers
    /// and lifetimes for which spans affect name resolution and edition
    /// checks. Note that keywords are also identifiers, so they should use
    /// this if they keep spans or perform edition checks.
    pub fn token_uninterpolated_span(&self) -> Span {
        match &self.token.kind {
            token::NtIdent(ident, _) | token::NtLifetime(ident, _) => ident.span,
            token::OpenInvisible(InvisibleOrigin::MetaVar(_)) => self.look_ahead(1, |t| t.span),
            _ => self.token.span,
        }
    }

    /// Like `token_uninterpolated_span`, but works on `self.prev_token`.
    pub fn prev_token_uninterpolated_span(&self) -> Span {
        match &self.prev_token.kind {
            token::NtIdent(ident, _) | token::NtLifetime(ident, _) => ident.span,
            token::OpenInvisible(InvisibleOrigin::MetaVar(_)) => self.look_ahead(0, |t| t.span),
            _ => self.prev_token.span,
        }
    }

    fn missing_semi_from_binop(
        &self,
        kind_desc: &str,
        expr: &Expr,
        decl_lo: Option<Span>,
    ) -> Option<(Span, ErrorGuaranteed)> {
        if self.token == TokenKind::Semi {
            return None;
        }
        if !self.may_recover() || expr.span.from_expansion() {
            return None;
        }
        let sm = self.psess.source_map();
        if let ExprKind::Binary(op, lhs, rhs) = &expr.kind
            && sm.is_multiline(lhs.span.shrink_to_hi().until(rhs.span.shrink_to_lo()))
            && matches!(op.node, BinOpKind::Mul | BinOpKind::BitAnd)
            && classify::expr_requires_semi_to_be_stmt(rhs)
        {
            let lhs_end_span = lhs.span.shrink_to_hi();
            let token_str = token_descr(&self.token);
            let mut err = self
                .dcx()
                .struct_span_err(lhs_end_span, format!("expected `;`, found {token_str}"));
            err.span_label(self.token.span, "unexpected token");

            // Use the declaration start if provided, otherwise fall back to lhs_end_span.
            let continuation_start = decl_lo.unwrap_or(lhs_end_span);
            let continuation_span = continuation_start.until(rhs.span.shrink_to_hi());
            err.span_label(
                continuation_span,
                format!(
                    "to finish parsing this {kind_desc}, expected this to be followed by a `;`",
                ),
            );
            let op_desc = match op.node {
                BinOpKind::BitAnd => "a bit-and",
                BinOpKind::Mul => "a multiplication",
                _ => "a binary",
            };
            let mut note_spans = MultiSpan::new();
            note_spans.push_span_label(lhs.span, "parsed as the left-hand expression");
            note_spans.push_span_label(rhs.span, "parsed as the right-hand expression");
            note_spans.push_span_label(op.span, format!("this was parsed as {op_desc}"));
            err.span_note(
                note_spans,
                format!("the {kind_desc} was parsed as having {op_desc} binary expression"),
            );

            err.span_suggestion(
                lhs_end_span,
                format!("you may have meant to write a `;` to terminate the {kind_desc} earlier"),
                ";",
                Applicability::MaybeIncorrect,
            );
            return Some((lhs.span, err.emit()));
        }
        None
    }
}

// Metavar captures of various kinds. The more complex node kinds (e.g. `Item`, `Expr`) store
// tokens in the node itself because those tokens are needed for non-terminal parsing and for other
// reasons (e.g. cfg expansion). Simpler node kinds (e.g. `Block`, `Path`) only need tokens for
// non-terminal parsing so here they store the tokens next to the node, keeping the node size
// smaller.
#[derive(Clone, Debug)]
pub enum ParseNtResult {
    Tt(TokenTree),
    Ident(Ident, IdentIsRaw),
    Lifetime(Ident, IdentIsRaw),
    Item(Box<ast::Item>),
    Block(WithTokens<Box<ast::Block>>),
    Stmt(Box<ast::Stmt>),
    Pat(WithTokens<Box<ast::Pat>>, NtPatKind),
    Expr(Box<ast::Expr>, NtExprKind),
    Literal(Box<ast::Expr>),
    Ty(WithTokens<Box<ast::Ty>>),
    // These tokens are for the attr item, e.g. just the `foo` within `#[foo]` or `#![foo]`.
    Meta(WithTokens<Box<ast::AttrItem>>),
    Path(WithTokens<Box<ast::Path>>),
    Vis(WithTokens<Box<ast::Visibility>>),
    Guard(Box<ast::Guard>),
}
