use std::fmt::Write;
use std::mem;

use ast::token::IdentIsRaw;
use rustc_ast as ast;
use rustc_ast::ast::*;
use rustc_ast::token::{self, Delimiter, MetaVarKind, TokenKind};
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
use rustc_ast::util::case::Case;
use rustc_ast_pretty::pprust;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, PResult, StashKey, msg, struct_span_code_err};
use rustc_span::edit_distance::edit_distance;
use rustc_span::edition::Edition;
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
use thin_vec::{ThinVec, thin_vec};
use tracing::debug;

use super::diagnostics::ConsumeClosingDelim;
use super::{
    AllowConstBlockItems, AttrWrapper, ExpTokenPair, FnContext, FnParseMode, FollowedByType,
    ForceCollect, IsDotDotDot, Parser, PathStyle, Recovered, Trailing, UsePreAttrPos,
};
use crate::diagnostics::{
    self, MacroExpandsToAdtField, UseDoubleColonSuggestion, UseRegularStructSuggestion,
};
use crate::exp;

impl<'a> Parser<'a> {
    /// Parses a source module as a crate. This is the main entry point for the parser.
    pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
        let (attrs, items, spans) = self.parse_mod(exp!(Eof))?;
        Ok(ast::Crate { attrs, items, spans, id: DUMMY_NODE_ID, is_placeholder: false })
    }

    /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
    fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
        let safety = self.parse_safety(Case::Sensitive);
        self.expect_keyword(exp!(Mod))?;
        let ident = self.parse_ident()?;
        let mod_kind = if self.eat(exp!(Semi)) {
            ModKind::Unloaded
        } else {
            self.expect(exp!(OpenBrace))?;
            let (inner_attrs, items, inner_span) = self.parse_mod(exp!(CloseBrace))?;
            attrs.extend(inner_attrs);
            ModKind::Loaded(items, Inline::Yes, inner_span)
        };
        Ok(ItemKind::Mod(safety, ident, mod_kind))
    }

    /// Parses the contents of a module (inner attributes followed by module items).
    /// We exit once we hit `term` which can be either
    /// - EOF (for files)
    /// - `}` for mod items
    pub fn parse_mod(
        &mut self,
        term: ExpTokenPair,
    ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
        let lo = self.token.span;
        let attrs = self.parse_inner_attributes()?;

        let post_attr_lo = self.token.span;
        let mut items: ThinVec<Box<_>> = ThinVec::new();

        // There shouldn't be any stray semicolons before or after items.
        // `parse_item` consumes the appropriate semicolons so any leftover is an error.
        loop {
            while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} // Eat all bad semicolons
            let Some(item) = self.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? else {
                break;
            };
            items.push(item);
        }

        if !self.eat(term) {
            let token_str = super::token_descr(&self.token);
            if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
                let is_let = self.token.is_keyword(kw::Let);
                let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));
                let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);

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

                let label = if is_let {
                    "`let` cannot be used for global variables"
                } else {
                    "expected item"
                };
                err.span_label(self.token.span, label);

                if is_let {
                    if is_let_mut {
                        err.help("consider using `static` and a `Mutex` instead of `let mut`");
                    } else if let_has_ident {
                        err.span_suggestion_short(
                            self.token.span,
                            "consider using `static` or `const` instead of `let`",
                            "static",
                            Applicability::MaybeIncorrect,
                        );
                    } else {
                        err.help("consider using `static` or `const` instead of `let`");
                    }
                }
                err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
                return Err(err);
            }
        }

        let inject_use_span = post_attr_lo.data().with_hi(post_attr_lo.lo());
        let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span };
        Ok((attrs, items, mod_spans))
    }
}

enum ReuseKind {
    Path,
    Impl,
}

impl<'a> Parser<'a> {
    pub fn parse_item(
        &mut self,
        force_collect: ForceCollect,
        allow_const_block_items: AllowConstBlockItems,
    ) -> PResult<'a, Option<Box<Item>>> {
        let fn_parse_mode =
            FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
        self.parse_item_(fn_parse_mode, force_collect, allow_const_block_items)
            .map(|i| i.map(Box::new))
    }

    fn parse_item_(
        &mut self,
        fn_parse_mode: FnParseMode,
        force_collect: ForceCollect,
        const_block_items_allowed: AllowConstBlockItems,
    ) -> PResult<'a, Option<Item>> {
        self.recover_vcs_conflict_marker();
        let attrs = self.parse_outer_attributes()?;
        self.recover_vcs_conflict_marker();
        self.parse_item_common(
            attrs,
            true,
            false,
            fn_parse_mode,
            force_collect,
            const_block_items_allowed,
        )
    }

    pub(super) fn parse_item_common(
        &mut self,
        attrs: AttrWrapper,
        mac_allowed: bool,
        attrs_allowed: bool,
        fn_parse_mode: FnParseMode,
        force_collect: ForceCollect,
        allow_const_block_items: AllowConstBlockItems,
    ) -> PResult<'a, Option<Item>> {
        if let Some(item) = self.eat_metavar_seq(MetaVarKind::Item, |this| {
            this.parse_item(ForceCollect::Yes, allow_const_block_items)
        }) {
            let mut item = item.expect("an actual item");
            attrs.prepend_to_nt_inner(&mut item.attrs);
            return Ok(Some(*item));
        }

        self.collect_tokens(None, attrs, force_collect, |this, mut attrs| {
            let lo = this.token.span;
            let vis = this.parse_visibility(FollowedByType::No)?;
            let mut def = this.parse_defaultness();
            let kind = this.parse_item_kind(
                &mut attrs,
                mac_allowed,
                allow_const_block_items,
                lo,
                &vis,
                &mut def,
                fn_parse_mode,
                Case::Sensitive,
            )?;
            if let Some(kind) = kind {
                this.error_on_unconsumed_default(def, &kind);
                let span = lo.to(this.prev_token.span);
                let id = DUMMY_NODE_ID;
                let item = Item { attrs, id, kind, vis, span, tokens: None };
                return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
            }

            // At this point, we have failed to parse an item.
            if !matches!(vis.kind, VisibilityKind::Inherited) {
                let vis_str = pprust::vis_to_string(&vis).trim_end().to_string();
                let mut err = this.dcx().create_err(diagnostics::VisibilityNotFollowedByItem {
                    span: vis.span,
                    vis: vis_str,
                });
                if let Some((ident, _)) = this.token.ident()
                    && !ident.is_used_keyword()
                    && let Some((similar_kw, is_incorrect_case)) = ident
                        .name
                        .find_similar(&rustc_span::symbol::used_keywords(|| ident.span.edition()))
                {
                    err.subdiagnostic(diagnostics::MisspelledKw {
                        similar_kw: similar_kw.to_string(),
                        span: ident.span,
                        is_incorrect_case,
                    });
                }
                err.emit();
            }

            if let Defaultness::Default(span) = def {
                this.dcx().emit_err(diagnostics::DefaultNotFollowedByItem { span });
            } else if let Defaultness::Final(span) = def {
                this.dcx().emit_err(diagnostics::FinalNotFollowedByItem { span });
            }

            if !attrs_allowed {
                this.recover_attrs_no_item(&attrs)?;
            }
            Ok((None, Trailing::No, UsePreAttrPos::No))
        })
    }

    /// Error in-case `default`/`final` was parsed in an in-appropriate context.
    fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
        match def {
            Defaultness::Default(span) => {
                self.dcx().emit_err(diagnostics::InappropriateDefault {
                    span,
                    article: kind.article(),
                    descr: kind.descr(),
                });
            }
            Defaultness::Final(span) => {
                self.dcx().emit_err(diagnostics::InappropriateFinal {
                    span,
                    article: kind.article(),
                    descr: kind.descr(),
                });
            }
            Defaultness::Implicit => (),
        }
    }

    /// Parses one of the items allowed by the flags.
    fn parse_item_kind(
        &mut self,
        attrs: &mut AttrVec,
        macros_allowed: bool,
        allow_const_block_items: AllowConstBlockItems,
        lo: Span,
        vis: &Visibility,
        def: &mut Defaultness,
        fn_parse_mode: FnParseMode,
        case: Case,
    ) -> PResult<'a, Option<ItemKind>> {
        let check_pub = def == &Defaultness::Implicit;
        let mut def_ = || mem::replace(def, Defaultness::Implicit);

        let info = if !self.is_use_closure() && self.eat_keyword_case(exp!(Use), case) {
            self.parse_use_item()?
        } else if self.check_fn_front_matter(check_pub, case) {
            // FUNCTION ITEM
            let defaultness = def_();
            if let Defaultness::Default(span) = defaultness {
                // Default functions should only require feature `min_specialization`. We remove the
                // `specialization` tag again as such spans *require* feature `specialization` to be
                // enabled. In a later stage, we make `specialization` imply `min_specialization`.
                self.psess.gated_spans.gate(sym::min_specialization, span);
                self.psess.gated_spans.ungate_last(sym::specialization, span);
            }
            let (ident, sig, generics, contract, body) =
                self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
            ItemKind::Fn(Box::new(Fn {
                defaultness,
                ident,
                sig,
                generics,
                contract,
                body,
                define_opaque: None,
                eii_impl: None,
            }))
        } else if self.eat_keyword_case(exp!(Extern), case) {
            if self.eat_keyword_case(exp!(Crate), case) {
                // EXTERN CRATE
                self.parse_item_extern_crate()?
            } else {
                // EXTERN BLOCK
                self.parse_item_foreign_mod(attrs, Safety::Default)?
            }
        } else if self.is_unsafe_foreign_mod() {
            // EXTERN BLOCK
            let safety = self.parse_safety(Case::Sensitive);
            self.expect_keyword(exp!(Extern))?;
            self.parse_item_foreign_mod(attrs, safety)?
        } else if let Some(safety) = self.parse_global_static_front_matter(case) {
            // STATIC ITEM
            let mutability = self.parse_mutability();
            self.parse_static_item(safety, mutability)?
        } else if self.check_keyword_case(exp!(Trait), case) || self.check_trait_front_matter() {
            // TRAIT ITEM
            self.parse_item_trait(attrs, lo)?
        } else if self.check_impl_frontmatter(0) {
            // IMPL ITEM
            self.parse_item_impl(attrs, def_(), false)?
        } else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =
            allow_const_block_items
            && self.check_inline_const(0)
        {
            // CONST BLOCK ITEM
            if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {
                debug!("Parsing a const block item that does not matter: {:?}", self.token.span);
            };
            ItemKind::ConstBlock(self.parse_const_block_item()?)
        } else if let Const::Yes(const_span) = self.parse_constness(case) {
            // CONST ITEM
            self.recover_const_mut(const_span);
            self.recover_missing_kw_before_item()?;
            let (ident, generics, ty, body) = self.parse_const_item(const_span)?;
            ItemKind::Const(Box::new(ConstItem {
                defaultness: def_(),
                ident,
                generics,
                ty,
                body,
                kind: ConstItemKind::Body,
                define_opaque: None,
            }))
        } else if let Some(kind) = self.is_reuse_item() {
            self.parse_item_delegation(attrs, def_(), kind)?
        } else if self.check_keyword_case(exp!(Mod), case)
            || self.check_keyword_case(exp!(Unsafe), case) && self.is_keyword_ahead(1, &[kw::Mod])
        {
            // MODULE ITEM
            self.parse_item_mod(attrs)?
        } else if self.eat_keyword_case(exp!(Type), case) {
            if let Const::Yes(const_span) = self.parse_constness(case) {
                // TYPE CONST (mgca)
                self.recover_const_mut(const_span);
                self.recover_missing_kw_before_item()?;
                let (ident, generics, ty, body) = self.parse_const_item(const_span)?;
                // Make sure this is only allowed if the feature gate is enabled.
                // #![feature(mgca_type_const_syntax)]
                self.psess.gated_spans.gate(sym::mgca_type_const_syntax, lo.to(const_span));
                ItemKind::Const(Box::new(ConstItem {
                    defaultness: def_(),
                    ident,
                    generics,
                    ty,
                    body,
                    kind: ConstItemKind::TypeConst,
                    define_opaque: None,
                }))
            } else {
                // TYPE ITEM
                self.parse_type_alias(def_())?
            }
        } else if self.eat_keyword_case(exp!(Enum), case) {
            // ENUM ITEM
            self.parse_item_enum()?
        } else if self.eat_keyword_case(exp!(Struct), case) {
            // STRUCT ITEM
            self.parse_item_struct()?
        } else if self.is_kw_followed_by_ident(kw::Union) {
            // UNION ITEM
            self.bump(); // `union`
            self.parse_item_union()?
        } else if self.is_builtin() {
            // BUILTIN# ITEM
            return self.parse_item_builtin();
        } else if self.eat_keyword_case(exp!(Macro), case) {
            // MACROS 2.0 ITEM
            self.parse_item_decl_macro(lo)?
        } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {
            // MACRO_RULES ITEM
            self.parse_item_macro_rules(vis, has_bang)?
        } else if self.isnt_macro_invocation()
            && (self.token.is_ident_named(sym::import)
                || self.token.is_ident_named(sym::using)
                || self.token.is_ident_named(sym::include)
                || self.token.is_ident_named(sym::require))
        {
            return self.recover_import_as_use();
        } else if self.isnt_macro_invocation() && vis.kind.is_pub() {
            self.recover_missing_kw_before_item()?;
            return Ok(None);
        } else if self.isnt_macro_invocation() && case == Case::Sensitive {
            _ = def_;

            // Recover wrong cased keywords
            return self.parse_item_kind(
                attrs,
                macros_allowed,
                allow_const_block_items,
                lo,
                vis,
                def,
                fn_parse_mode,
                Case::Insensitive,
            );
        } else if macros_allowed && self.check_path() {
            if self.isnt_macro_invocation() {
                self.recover_missing_kw_before_item()?;
            }
            // MACRO INVOCATION ITEM
            ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))
        } else {
            return Ok(None);
        };
        Ok(Some(info))
    }

    fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
        let span = self.token.span;
        let token_name = super::token_descr(&self.token);
        let snapshot = self.create_snapshot_for_diagnostic();
        self.bump();
        match self.parse_use_item() {
            Ok(u) => {
                self.dcx().emit_err(diagnostics::RecoverImportAsUse { span, token_name });
                Ok(Some(u))
            }
            Err(e) => {
                e.cancel();
                self.restore_snapshot(snapshot);
                Ok(None)
            }
        }
    }

    fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
        let tree = self.parse_use_tree()?;
        if let Err(mut e) = self.expect_semi() {
            match tree.kind {
                UseTreeKind::Glob(_) => {
                    e.note("the wildcard token must be last on the path");
                }
                UseTreeKind::Nested { .. } => {
                    e.note("glob-like brace syntax must be last on the path");
                }
                _ => (),
            }
            return Err(e);
        }
        Ok(ItemKind::Use(tree))
    }

    /// When parsing a statement, would the start of a path be an item?
    pub(super) fn is_path_start_item(&mut self) -> bool {
        self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }`
        || self.is_reuse_item().is_some() // yes: `reuse impl Trait for Struct { self.0 }`, yes: `reuse some_path::foo;`
        || self.check_trait_front_matter() // no: `auto::b`, yes: `auto trait X { .. }`
        || self.is_async_fn() // no(2015): `async::b`, yes: `async fn`
        || matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) // no: `macro_rules::b`, yes: `macro_rules! mac`
    }

    fn is_reuse_item(&mut self) -> Option<ReuseKind> {
        if !self.token.is_keyword(kw::Reuse) {
            return None;
        }

        // no: `reuse ::path` for compatibility reasons with macro invocations
        if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {
            Some(ReuseKind::Path)
        } else if self.check_impl_frontmatter(1) {
            Some(ReuseKind::Impl)
        } else {
            None
        }
    }

    /// Are we sure this could not possibly be a macro invocation?
    fn isnt_macro_invocation(&mut self) -> bool {
        self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)
    }

    /// Recover on encountering a struct, enum, or method definition where the user
    /// forgot to add the `struct`, `enum`, or `fn` keyword
    fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
        let is_pub = self.prev_token.is_keyword(kw::Pub);
        let is_const = self.prev_token.is_keyword(kw::Const);
        let ident_span = self.token.span;
        let span = if is_pub { self.prev_token.span.to(ident_span) } else { ident_span };
        let insert_span = ident_span.shrink_to_lo();

        let ident = if self.token.is_ident()
            && (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
            && self.look_ahead(1, |t| {
                matches!(t.kind, token::Lt | token::OpenBrace | token::OpenParen)
            }) {
            self.parse_ident_common(true).unwrap()
        } else {
            return Ok(());
        };

        let mut found_generics = false;
        if self.check(exp!(Lt)) {
            found_generics = true;
            self.eat_to_tokens(&[exp!(Gt)]);
            self.bump(); // `>`
        }

        let err = if self.check(exp!(OpenBrace)) {
            // possible struct or enum definition where `struct` or `enum` was forgotten
            if self.look_ahead(1, |t| *t == token::CloseBrace) {
                // `S {}` could be unit enum or struct
                Some(diagnostics::MissingKeywordForItemDefinition::EnumOrStruct { span })
            } else if self.look_ahead(2, |t| *t == token::Colon)
                || self.look_ahead(3, |t| *t == token::Colon)
            {
                // `S { f:` or `S { pub f:`
                Some(diagnostics::MissingKeywordForItemDefinition::Struct {
                    span,
                    insert_span,
                    ident,
                })
            } else {
                Some(diagnostics::MissingKeywordForItemDefinition::Enum {
                    span,
                    insert_span,
                    ident,
                })
            }
        } else if self.check(exp!(OpenParen)) {
            // possible function or tuple struct definition where `fn` or `struct` was forgotten
            self.bump(); // `(`
            let is_method = self.recover_self_param();

            self.consume_block(exp!(OpenParen), exp!(CloseParen), ConsumeClosingDelim::Yes);

            let err = if self.check(exp!(RArrow)) || self.check(exp!(OpenBrace)) {
                self.eat_to_tokens(&[exp!(OpenBrace)]);
                self.bump(); // `{`
                self.consume_block(exp!(OpenBrace), exp!(CloseBrace), ConsumeClosingDelim::Yes);
                if is_method {
                    diagnostics::MissingKeywordForItemDefinition::Method {
                        span,
                        insert_span,
                        ident,
                    }
                } else {
                    diagnostics::MissingKeywordForItemDefinition::Function {
                        span,
                        insert_span,
                        ident,
                    }
                }
            } else if is_pub && self.check(exp!(Semi)) {
                diagnostics::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }
            } else {
                diagnostics::MissingKeywordForItemDefinition::Ambiguous {
                    span,
                    subdiag: if found_generics {
                        None
                    } else if let Ok(snippet) = self.span_to_snippet(ident_span) {
                        Some(diagnostics::AmbiguousMissingKwForItemSub::SuggestMacro {
                            span: ident_span,
                            snippet,
                        })
                    } else {
                        Some(diagnostics::AmbiguousMissingKwForItemSub::HelpMacro)
                    },
                }
            };
            Some(err)
        } else if found_generics {
            Some(diagnostics::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })
        } else {
            None
        };

        if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
    }

    fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
        // To be expanded
        Ok(None)
    }

    /// Parses an item macro, e.g., `item!();`.
    fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
        let path = self.parse_path(PathStyle::Mod)?; // `foo::bar`
        self.expect(exp!(Bang))?; // `!`
        match self.parse_delim_args() {
            // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
            Ok(args) => {
                self.eat_semi_for_macro_if_needed(&args, Some(&path));
                self.complain_if_pub_macro(vis, false);
                Ok(MacCall { path, args })
            }

            Err(mut err) => {
                // Maybe the user misspelled `macro_rules` (issue #91227)
                if self.token.is_ident()
                    && let [segment] = path.segments.as_slice()
                    && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
                {
                    err.span_suggestion_verbose(
                        path.span,
                        "perhaps you meant to define a macro",
                        "macro_rules",
                        Applicability::MachineApplicable,
                    );
                }
                Err(err)
            }
        }
    }

    /// Recover if we parsed attributes and expected an item but there was none.
    fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
        let ([start @ end] | [start, .., end]) = attrs else {
            return Ok(());
        };
        let msg = if end.is_doc_comment() {
            "expected item after doc comment"
        } else {
            "expected item after attributes"
        };
        let mut err = self.dcx().struct_span_err(end.span, msg);
        if end.is_doc_comment() {
            err.span_label(end.span, "this doc comment doesn't document anything");
        } else {
            err.span_label(end.span, "expected an item after this");
            if self.token == TokenKind::Semi {
                err.span_suggestion_verbose(
                    self.token.span,
                    "remove the semicolon after the attribute",
                    "",
                    Applicability::MaybeIncorrect,
                );
            }
        }
        if let [.., penultimate, _] = attrs {
            err.span_label(start.span.to(penultimate.span), "other attributes here");
        }
        Err(err)
    }

    fn is_async_fn(&self) -> bool {
        self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
    }

    fn parse_polarity(&mut self) -> ast::ImplPolarity {
        // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
        if self.check(exp!(Bang)) && self.look_ahead(1, |t| t.can_begin_type()) {
            self.psess.gated_spans.gate(sym::negative_impls, self.token.span);
            self.bump(); // `!`
            ast::ImplPolarity::Negative(self.prev_token.span)
        } else {
            ast::ImplPolarity::Positive
        }
    }

    /// Parses an implementation item.
    ///
    /// ```ignore (illustrative)
    /// impl<'a, T> TYPE { /* impl items */ }
    /// impl<'a, T> TRAIT for TYPE { /* impl items */ }
    /// impl<'a, T> !TRAIT for TYPE { /* impl items */ }
    /// impl<'a, T> const TRAIT for TYPE { /* impl items */ }
    /// ```
    ///
    /// We actually parse slightly more relaxed grammar for better error reporting and recovery.
    /// ```ebnf
    /// "impl" GENERICS "const"? "!"? TYPE "for"? (TYPE | "..") ("where" PREDICATES)? "{" BODY "}"
    /// "impl" GENERICS "const"? "!"? TYPE ("where" PREDICATES)? "{" BODY "}"
    /// ```
    fn parse_item_impl(
        &mut self,
        attrs: &mut AttrVec,
        defaultness: Defaultness,
        is_reuse: bool,
    ) -> PResult<'a, ItemKind> {
        let constness = self.parse_constness(Case::Sensitive);
        let safety = self.parse_safety(Case::Sensitive);
        self.expect_keyword(exp!(Impl))?;
        let mut generics_snapshot = None;
        // First, parse generic parameters if necessary.
        let mut generics = if self.choose_generics_over_qpath(0) {
            self.parse_generics()?
        } else {
            // We might be mistakenly trying to use a generic type as a generic parameter.
            // impl<X<T>> Trait for Y<T> { ... }
            if self.look_ahead(0, |t| t == &token::Lt)
                && self.look_ahead(1, |t| t.is_ident())
                && self.look_ahead(2, |t| t == &token::Lt)
            {
                generics_snapshot = Some(self.create_snapshot_for_diagnostic());
            }

            let mut generics = Generics::default();
            // impl A for B {}
            //    /\ this is where `generics.span` should point when there are no type params.
            generics.span = self.prev_token.span.shrink_to_hi();
            generics
        };

        if let Const::Yes(span) = constness {
            self.psess.gated_spans.gate(sym::const_trait_impl, span);
        }

        // Parse stray `impl async Trait`
        if (self.token_uninterpolated_span().at_least_rust_2018()
            && self.token.is_keyword(kw::Async))
            || self.is_kw_followed_by_ident(kw::Async)
        {
            self.bump();
            self.dcx().emit_err(diagnostics::AsyncImpl { span: self.prev_token.span });
        }

        let polarity = self.parse_polarity();

        // Parse both types and traits as a type, then reinterpret if necessary.
        let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
        {
            let span = self.prev_token.span.between(self.token.span);
            return Err(self.dcx().create_err(diagnostics::MissingTraitInTraitImpl {
                span,
                for_span: span.to(self.token.span),
            }));
        } else {
            self.parse_ty_with_generics_recovery(&generics).map_err(|e| {
                let Some(mut snapshot) = generics_snapshot else {
                    return e;
                };
                snapshot.maybe_type_in_generic_parameter(e)
            })?
        };
        // If `for` is missing we try to recover.
        let has_for = self.eat_keyword(exp!(For));
        let missing_for_span = self.prev_token.span.between(self.token.span);

        let ty_second = if self.token == token::DotDot {
            // We need to report this error after `cfg` expansion for compatibility reasons
            self.bump(); // `..`, do not add it to expected tokens

            // AST validation later detects this `TyKind::Dummy` and emits an
            // error. (#121072 will hopefully remove all this special handling
            // of the obsolete `impl Trait for ..` and then this can go away.)
            Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))
        } else if has_for || self.token.can_begin_type() {
            Some(self.parse_ty()?)
        } else {
            None
        };

        generics.where_clause = self.parse_where_clause()?;

        let impl_items = if is_reuse {
            Default::default()
        } else {
            self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
        };

        let (of_trait, self_ty) = match ty_second {
            Some(ty_second) => {
                // impl Trait for Type
                if !has_for {
                    self.dcx()
                        .emit_err(diagnostics::MissingForInTraitImpl { span: missing_for_span });
                }

                let ty_first = *ty_first;
                let path = match ty_first.kind {
                    // This notably includes paths passed through `ty` macro fragments (#46438).
                    TyKind::Path(None, path) => path,
                    other => {
                        if let TyKind::ImplTrait(_, bounds) = other
                            && let [bound] = bounds.as_slice()
                            && let GenericBound::Trait(poly_trait_ref) = bound
                        {
                            // Suggest removing extra `impl` keyword:
                            // `impl<T: Default> impl Default for Wrapper<T>`
                            //                   ^^^^^
                            let extra_impl_kw = ty_first.span.until(bound.span());
                            self.dcx().emit_err(diagnostics::ExtraImplKeywordInTraitImpl {
                                extra_impl_kw,
                                impl_trait_span: ty_first.span,
                            });
                            poly_trait_ref.trait_ref.path.clone()
                        } else {
                            return Err(self.dcx().create_err(
                                diagnostics::ExpectedTraitInTraitImplFoundType {
                                    span: ty_first.span,
                                },
                            ));
                        }
                    }
                };
                let trait_ref = TraitRef { path, ref_id: ty_first.id };

                let of_trait =
                    Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));
                (of_trait, ty_second)
            }
            None => {
                let self_ty = ty_first;
                let error = |modifier, modifier_name, modifier_span| {
                    self.dcx().create_err(diagnostics::TraitImplModifierInInherentImpl {
                        span: self_ty.span,
                        modifier,
                        modifier_name,
                        modifier_span,
                        self_ty: self_ty.span,
                    })
                };

                if let Safety::Unsafe(span) = safety {
                    error("unsafe", "unsafe", span).with_code(E0197).emit();
                }
                if let ImplPolarity::Negative(span) = polarity {
                    error("!", "negative", span).emit();
                }
                if let Defaultness::Default(def_span) = defaultness {
                    error("default", "default", def_span).emit();
                }
                if let Const::Yes(span) = constness {
                    self.psess.gated_spans.gate(sym::const_trait_impl, span);
                }
                (None, self_ty)
            }
        };

        Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
    }

    fn parse_item_delegation(
        &mut self,
        attrs: &mut AttrVec,
        defaultness: Defaultness,
        kind: ReuseKind,
    ) -> PResult<'a, ItemKind> {
        let span = self.token.span;
        self.expect_keyword(exp!(Reuse))?;

        let item_kind = match kind {
            ReuseKind::Path => self.parse_path_like_delegation(),
            ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
        }?;

        self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));

        Ok(item_kind)
    }

    fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
        Ok(if self.check(exp!(OpenBrace)) {
            Some(self.parse_block()?)
        } else {
            self.expect(exp!(Semi))?;
            None
        })
    }

    fn parse_impl_delegation(
        &mut self,
        span: Span,
        attrs: &mut AttrVec,
        defaultness: Defaultness,
    ) -> PResult<'a, ItemKind> {
        let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
        let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { unreachable!() };

        let until_expr_span = span.to(self.prev_token.span);

        let Some(of_trait) = of_trait else {
            return Err(self
                .dcx()
                .create_err(diagnostics::ImplReuseInherentImpl { span: until_expr_span }));
        };

        let body = self.parse_delegation_body()?;
        let whole_reuse_span = span.to(self.prev_token.span);

        items.push(Box::new(AssocItem {
            id: DUMMY_NODE_ID,
            attrs: Default::default(),
            span: whole_reuse_span,
            tokens: None,
            vis: Visibility { kind: VisibilityKind::Inherited, span: whole_reuse_span },
            kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
                qself: None,
                prefix: of_trait.trait_ref.path.clone(),
                suffixes: DelegationSuffixes::Glob(whole_reuse_span),
                body,
            })),
        }));

        Ok(impl_item)
    }

    fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
        let (qself, path) = if self.eat_lt() {
            let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
            (Some(qself), path)
        } else {
            (None, self.parse_path(PathStyle::Expr)?)
        };

        let rename = |this: &mut Self| {
            Ok(if this.eat_keyword(exp!(As)) { Some(this.parse_ident()?) } else { None })
        };

        Ok(if self.eat_path_sep() {
            let suffixes = if self.eat(exp!(Star)) {
                DelegationSuffixes::Glob(self.prev_token.span)
            } else {
                let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
                DelegationSuffixes::List(
                    self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0,
                )
            };

            ItemKind::DelegationMac(Box::new(DelegationMac {
                qself,
                prefix: path,
                suffixes,
                body: self.parse_delegation_body()?,
            }))
        } else {
            let rename = rename(self)?;
            let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);

            ItemKind::Delegation(Box::new(Delegation {
                id: DUMMY_NODE_ID,
                qself,
                path,
                ident,
                rename,
                body: self.parse_delegation_body()?,
                source: DelegationSource::Single,
            }))
        })
    }

    fn parse_item_list<T>(
        &mut self,
        attrs: &mut AttrVec,
        mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
    ) -> PResult<'a, ThinVec<T>> {
        let open_brace_span = self.token.span;

        // Recover `impl Ty;` instead of `impl Ty {}`
        if self.token == TokenKind::Semi {
            self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
            self.bump();
            return Ok(ThinVec::new());
        }

        self.expect(exp!(OpenBrace))?;
        attrs.extend(self.parse_inner_attributes()?);

        let mut items = ThinVec::new();
        while !self.eat(exp!(CloseBrace)) {
            if self.recover_doc_comment_before_brace() {
                continue;
            }
            self.recover_vcs_conflict_marker();
            match parse_item(self) {
                Ok(None) => {
                    let mut is_unnecessary_semicolon = (self.token == token::Semi
                        && self.prev_token == token::Semi)
                        || !items.is_empty()
                        // When the close delim is `)` in a case like the following, `token.kind`
                        // is expected to be `token::CloseParen`, but the actual `token.kind` is
                        // `token::CloseBrace`. This is because the `token.kind` of the close delim
                        // is treated as the same as that of the open delim in
                        // `TokenTreesReader::parse_token_tree`, even if the delimiters of them are
                        // different. Therefore, `token.kind` should not be compared here.
                        //
                        // issue-60075.rs
                        // ```
                        // trait T {
                        //     fn qux() -> Option<usize> {
                        //         let _ = if true {
                        //         });
                        //          ^ this close delim
                        //         Some(4)
                        //     }
                        // ```
                        && self
                            .span_to_snippet(self.prev_token.span)
                            .is_ok_and(|snippet| snippet == "}")
                        && self.token == token::Semi;
                    let mut semicolon_span = self.token.span;
                    if !is_unnecessary_semicolon {
                        // #105369, Detect spurious `;` before assoc fn body
                        is_unnecessary_semicolon =
                            self.token == token::OpenBrace && self.prev_token == token::Semi;
                        semicolon_span = self.prev_token.span;
                    }
                    // We have to bail or we'll potentially never make progress.
                    let non_item_span = self.token.span;
                    let is_let = self.token.is_keyword(kw::Let);

                    let mut err =
                        self.dcx().struct_span_err(non_item_span, "non-item in item list");
                    self.consume_block(exp!(OpenBrace), exp!(CloseBrace), ConsumeClosingDelim::Yes);
                    if is_let {
                        err.span_suggestion_verbose(
                            non_item_span,
                            "consider using `const` instead of `let` for associated const",
                            "const",
                            Applicability::MachineApplicable,
                        );
                    } else {
                        err.span_label(open_brace_span, "item list starts here")
                            .span_label(non_item_span, "non-item starts here")
                            .span_label(self.prev_token.span, "item list ends here");
                    }
                    if is_unnecessary_semicolon {
                        err.span_suggestion_verbose(
                            semicolon_span,
                            "consider removing this semicolon",
                            "",
                            Applicability::MaybeIncorrect,
                        );
                    }
                    err.emit();
                    break;
                }
                Ok(Some(item)) => items.extend(item),
                Err(err) => {
                    self.consume_block(exp!(OpenBrace), exp!(CloseBrace), ConsumeClosingDelim::Yes);
                    err.with_span_label(
                        open_brace_span,
                        "while parsing this item list starting here",
                    )
                    .with_span_label(self.prev_token.span, "the item list ends here")
                    .emit();
                    break;
                }
            }
        }
        Ok(items)
    }

    /// Recover on a doc comment before `}`.
    fn recover_doc_comment_before_brace(&mut self) -> bool {
        if let token::DocComment(..) = self.token.kind {
            if self.look_ahead(1, |tok| tok == &token::CloseBrace) {
                // FIXME: merge with `DocCommentDoesNotDocumentAnything` (E0585)
                struct_span_code_err!(
                    self.dcx(),
                    self.token.span,
                    E0584,
                    "found a documentation comment that doesn't document anything",
                )
                .with_span_label(self.token.span, "this doc comment doesn't document anything")
                .with_help(
                    "doc comments must come before what they document, if a comment was \
                    intended use `//`",
                )
                .emit();
                self.bump();
                return true;
            }
        }
        false
    }

    /// Parses defaultness (i.e., `default` or nothing).
    fn parse_defaultness(&mut self) -> Defaultness {
        // We are interested in `default` followed by another identifier.
        // However, we must avoid keywords that occur as binary operators.
        // Currently, the only applicable keyword is `as` (`default as Ty`).
        if self.check_keyword(exp!(Default))
            && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
        {
            self.psess.gated_spans.gate(sym::specialization, self.token.span);
            self.bump(); // `default`
            Defaultness::Default(self.prev_token_uninterpolated_span())
        } else if self.eat_keyword(exp!(Final)) {
            self.psess.gated_spans.gate(sym::final_associated_functions, self.prev_token.span);
            Defaultness::Final(self.prev_token_uninterpolated_span())
        } else {
            Defaultness::Implicit
        }
    }

    /// Is this an `[impl(in? path)]? const? unsafe? auto? trait` item?
    fn check_trait_front_matter(&mut self) -> bool {
        const SUFFIXES: &[&[Symbol]] = &[
            &[kw::Trait],
            &[kw::Auto, kw::Trait],
            &[kw::Unsafe, kw::Trait],
            &[kw::Unsafe, kw::Auto, kw::Trait],
            &[kw::Const, kw::Trait],
            &[kw::Const, kw::Auto, kw::Trait],
            &[kw::Const, kw::Unsafe, kw::Trait],
            &[kw::Const, kw::Unsafe, kw::Auto, kw::Trait],
        ];
        // `impl(`
        if self.check_keyword(exp!(Impl)) && self.look_ahead(1, |t| t == &token::OpenParen) {
            // `impl(in` unambiguously introduces an `impl` restriction
            if self.is_keyword_ahead(2, &[kw::In]) {
                return true;
            }
            // `impl(crate | self | super)` + SUFFIX
            if self.is_keyword_ahead(2, &[kw::Crate, kw::SelfLower, kw::Super])
                && self.look_ahead(3, |t| t == &token::CloseParen)
                && SUFFIXES.iter().any(|suffix| {
                    suffix.iter().enumerate().all(|(i, kw)| self.is_keyword_ahead(i + 4, &[*kw]))
                })
            {
                return true;
            }
            // Recover cases like `impl(path::to::module)` + SUFFIX to suggest inserting `in`.
            SUFFIXES.iter().any(|suffix| {
                suffix.iter().enumerate().all(|(i, kw)| {
                    self.tree_look_ahead(i + 2, |t| {
                        if let TokenTree::Token(token, _) = t {
                            token.is_keyword(*kw)
                        } else {
                            false
                        }
                    })
                    .unwrap_or(false)
                })
            })
        } else {
            SUFFIXES.iter().any(|suffix| {
                suffix.iter().enumerate().all(|(i, kw)| {
                    // We use `check_keyword` for the first token to include it in the expected tokens.
                    if i == 0 {
                        match *kw {
                            kw::Const => self.check_keyword(exp!(Const)),
                            kw::Unsafe => self.check_keyword(exp!(Unsafe)),
                            kw::Auto => self.check_keyword(exp!(Auto)),
                            kw::Trait => self.check_keyword(exp!(Trait)),
                            _ => unreachable!(),
                        }
                    } else {
                        self.is_keyword_ahead(i, &[*kw])
                    }
                })
            })
        }
    }

    /// Parses `[impl(in? path)]? const? unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`.
    fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
        let impl_restriction = self.parse_impl_restriction()?;
        let constness = self.parse_constness(Case::Sensitive);
        if let Const::Yes(span) = constness {
            self.psess.gated_spans.gate(sym::const_trait_impl, span);
        }
        let safety = self.parse_safety(Case::Sensitive);
        // Parse optional `auto` prefix.
        let is_auto = if self.eat_keyword(exp!(Auto)) {
            self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
            IsAuto::Yes
        } else {
            IsAuto::No
        };

        self.expect_keyword(exp!(Trait))?;
        let ident = self.parse_ident()?;
        let mut generics = self.parse_generics()?;

        // Parse optional colon and supertrait bounds.
        let had_colon = self.eat(exp!(Colon));
        let span_at_colon = self.prev_token.span;
        let bounds = if had_colon { self.parse_generic_bounds()? } else { ThinVec::new() };

        let span_before_eq = self.prev_token.span;
        if self.eat(exp!(Eq)) {
            // It's a trait alias.
            if had_colon {
                let span = span_at_colon.to(span_before_eq);
                self.dcx().emit_err(diagnostics::BoundsNotAllowedOnTraitAliases { span });
            }

            let bounds = self.parse_generic_bounds()?;
            generics.where_clause = self.parse_where_clause()?;
            self.expect_semi()?;

            let whole_span = lo.to(self.prev_token.span);
            if is_auto == IsAuto::Yes {
                self.dcx().emit_err(diagnostics::TraitAliasCannotBeAuto { span: whole_span });
            }
            if let Safety::Unsafe(_) = safety {
                self.dcx().emit_err(diagnostics::TraitAliasCannotBeUnsafe { span: whole_span });
            }
            if let RestrictionKind::Restricted { .. } = impl_restriction.kind {
                self.dcx()
                    .emit_err(diagnostics::TraitAliasCannotBeImplRestricted { span: whole_span });
            }

            self.psess.gated_spans.gate(sym::trait_alias, whole_span);

            Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
        } else {
            // It's a normal trait.
            generics.where_clause = self.parse_where_clause()?;
            let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
            Ok(ItemKind::Trait(Box::new(Trait {
                impl_restriction,
                constness,
                is_auto,
                safety,
                ident,
                generics,
                bounds,
                items,
            })))
        }
    }

    pub fn parse_impl_item(
        &mut self,
        force_collect: ForceCollect,
    ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
        let fn_parse_mode =
            FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };
        self.parse_assoc_item(fn_parse_mode, force_collect)
    }

    pub fn parse_trait_item(
        &mut self,
        force_collect: ForceCollect,
    ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
        let fn_parse_mode = FnParseMode {
            req_name: |edition, _| edition >= Edition::Edition2018,
            context: FnContext::Trait,
            req_body: false,
        };
        self.parse_assoc_item(fn_parse_mode, force_collect)
    }

    /// Parses associated items.
    fn parse_assoc_item(
        &mut self,
        fn_parse_mode: FnParseMode,
        force_collect: ForceCollect,
    ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
        Ok(self
            .parse_item_(
                fn_parse_mode,
                force_collect,
                AllowConstBlockItems::DoesNotMatter, // due to `AssocItemKind::try_from` below
            )?
            .map(|Item { attrs, id, span, vis, kind, tokens }| {
                let kind = match AssocItemKind::try_from(kind) {
                    Ok(kind) => kind,
                    Err(kind) => match kind {
                        ItemKind::Static(StaticItem {
                            ident,
                            ty,
                            safety: _,
                            mutability: _,
                            expr,
                            define_opaque,
                            eii_impl: _,
                        }) => {
                            self.dcx()
                                .emit_err(diagnostics::AssociatedStaticItemNotAllowed { span });
                            AssocItemKind::Const(Box::new(ConstItem {
                                defaultness: Defaultness::Implicit,
                                ident,
                                generics: Generics::default(),
                                ty,
                                body: expr,
                                kind: ConstItemKind::Body,
                                define_opaque,
                            }))
                        }
                        _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
                    },
                };
                Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
            }))
    }

    /// Parses a `type` alias with the following grammar:
    /// ```ebnf
    /// TypeAlias = "type" Ident Generics (":" GenericBounds)? WhereClause ("=" Ty)? WhereClause ";" ;
    /// ```
    /// The `"type"` has already been eaten.
    fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
        let ident = self.parse_ident()?;
        let mut generics = self.parse_generics()?;

        // Parse optional colon and param bounds.
        let bounds =
            if self.eat(exp!(Colon)) { self.parse_generic_bounds()? } else { ThinVec::new() };
        generics.where_clause = self.parse_where_clause()?;

        let ty = if self.eat(exp!(Eq)) { Some(self.parse_ty()?) } else { None };

        let after_where_clause = self.parse_where_clause()?;

        self.expect_semi()?;

        Ok(ItemKind::TyAlias(Box::new(TyAlias {
            defaultness,
            ident,
            generics,
            after_where_clause,
            bounds,
            ty,
        })))
    }

    /// Parses a `UseTree`.
    ///
    /// ```text
    /// USE_TREE = [`::`] `*` |
    ///            [`::`] `{` USE_TREE_LIST `}` |
    ///            PATH `::` `*` |
    ///            PATH `::` `{` USE_TREE_LIST `}` |
    ///            PATH [`as` IDENT]
    /// ```
    fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
        let lo = self.token.span;

        let mut prefix = ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo() };
        let kind =
            if self.check(exp!(OpenBrace)) || self.check(exp!(Star)) || self.is_import_coupler() {
                // `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
                let mod_sep_ctxt = self.token.span.ctxt();
                if self.eat_path_sep() {
                    prefix
                        .segments
                        .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
                }

                self.parse_use_tree_glob_or_nested()?
            } else {
                // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
                prefix = self.parse_path(PathStyle::Mod)?;

                if self.eat_path_sep() {
                    self.parse_use_tree_glob_or_nested()?
                } else {
                    // Recover from using a colon as path separator.
                    while self.eat_noexpect(&token::Colon) {
                        self.dcx().emit_err(diagnostics::SingleColonImportPath {
                            span: self.prev_token.span,
                        });

                        // We parse the rest of the path and append it to the original prefix.
                        self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
                        prefix.span = lo.to(self.prev_token.span);
                    }

                    UseTreeKind::Simple(self.parse_rename()?)
                }
            };

        Ok(UseTree { prefix, kind })
    }

    /// Parses `*` or `{...}`.
    fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
        Ok(if self.eat(exp!(Star)) {
            UseTreeKind::Glob(self.prev_token.span)
        } else {
            let lo = self.token.span;
            UseTreeKind::Nested {
                items: self.parse_use_tree_list()?,
                span: lo.to(self.prev_token.span),
            }
        })
    }

    /// Parses a `UseTreeKind::Nested(list)`.
    ///
    /// ```text
    /// USE_TREE_LIST = ∅ | (USE_TREE `,`)* USE_TREE [`,`]
    /// ```
    fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
        self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), |p| {
            p.recover_vcs_conflict_marker();
            Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
        })
        .map(|(r, _)| r)
    }

    fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
        if self.eat_keyword(exp!(As)) {
            self.parse_ident_or_underscore().map(Some)
        } else {
            Ok(None)
        }
    }

    fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
        match self.token.ident() {
            Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {
                self.bump();
                Ok(ident)
            }
            _ => self.parse_ident(),
        }
    }

    /// Parses `extern crate` links.
    ///
    /// # Examples
    ///
    /// ```ignore (illustrative)
    /// extern crate foo;
    /// extern crate bar as foo;
    /// ```
    fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
        // Accept `extern crate name-like-this` for better diagnostics
        let orig_ident = self.parse_crate_name_with_dashes()?;
        let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
            (Some(orig_ident.name), rename)
        } else {
            (None, orig_ident)
        };
        self.expect_semi()?;
        Ok(ItemKind::ExternCrate(orig_name, item_ident))
    }

    fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
        let ident = if self.token.is_keyword(kw::SelfLower) {
            self.parse_path_segment_ident()
        } else {
            self.parse_ident()
        }?;

        let dash = exp!(Minus);
        if self.token != dash.tok {
            return Ok(ident);
        }

        // Accept `extern crate name-like-this` for better diagnostics.
        let mut dashes = vec![];
        let mut idents = vec![];
        while self.eat(dash) {
            dashes.push(self.prev_token.span);
            idents.push(self.parse_ident()?);
        }

        let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
        let mut fixed_name = ident.name.to_string();
        for part in idents {
            write!(fixed_name, "_{}", part.name).unwrap();
        }

        self.dcx().emit_err(diagnostics::ExternCrateNameWithDashes {
            span: fixed_name_sp,
            sugg: diagnostics::ExternCrateNameWithDashesSugg { dashes },
        });

        Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
    }

    /// Parses `extern` for foreign ABIs modules.
    ///
    /// `extern` is expected to have been consumed before calling this method.
    ///
    /// # Examples
    ///
    /// ```ignore (only-for-syntax-highlight)
    /// extern "C" {}
    /// extern {}
    /// ```
    fn parse_item_foreign_mod(
        &mut self,
        attrs: &mut AttrVec,
        mut safety: Safety,
    ) -> PResult<'a, ItemKind> {
        let extern_span = self.prev_token_uninterpolated_span();
        let abi = self.parse_abi(); // ABI?
        // FIXME: This recovery should be tested better.
        if safety == Safety::Default
            && self.token.is_keyword(kw::Unsafe)
            && self.look_ahead(1, |t| *t == token::OpenBrace)
        {
            self.expect(exp!(OpenBrace)).unwrap_err().emit();
            safety = Safety::Unsafe(self.token.span);
            let _ = self.eat_keyword(exp!(Unsafe));
        }
        Ok(ItemKind::ForeignMod(ast::ForeignMod {
            extern_span,
            safety,
            abi,
            items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
        }))
    }

    /// Parses a foreign item (one in an `extern { ... }` block).
    pub fn parse_foreign_item(
        &mut self,
        force_collect: ForceCollect,
    ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
        let fn_parse_mode = FnParseMode {
            req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
            context: FnContext::Free,
            req_body: false,
        };
        Ok(self
            .parse_item_(
                fn_parse_mode,
                force_collect,
                AllowConstBlockItems::DoesNotMatter, // due to `ForeignItemKind::try_from` below
            )?
            .map(|Item { attrs, id, span, vis, kind, tokens }| {
                let kind = match ForeignItemKind::try_from(kind) {
                    Ok(kind) => kind,
                    Err(kind) => match kind {
                        ItemKind::Const(ConstItem { ident, ty, body, .. }) => {
                            let const_span = Some(span.with_hi(ident.span.lo()))
                                .filter(|span| span.can_be_used_for_suggestions());
                            self.dcx().emit_err(diagnostics::ExternItemCannotBeConst {
                                ident_span: ident.span,
                                const_span,
                            });
                            ForeignItemKind::Static(Box::new(StaticItem {
                                ident,
                                ty,
                                mutability: Mutability::Not,
                                expr: body,
                                safety: Safety::Default,
                                define_opaque: None,
                                eii_impl: None,
                            }))
                        }
                        _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
                    },
                };
                Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
            }))
    }

    fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
        // FIXME(#100717): needs variant for each `ItemKind` (instead of using `ItemKind::descr()`)
        let span = self.psess.source_map().guess_head_span(span);
        let descr = kind.descr();
        let help = match kind {
            ItemKind::DelegationMac(DelegationMac {
                suffixes: DelegationSuffixes::Glob(_),
                ..
            }) => false,
            _ => true,
        };
        self.dcx().emit_err(diagnostics::BadItemKind { span, descr, ctx, help });
        None
    }

    fn is_use_closure(&self) -> bool {
        if self.token.is_keyword(kw::Use) {
            // Check if this could be a closure.
            self.look_ahead(1, |token| {
                // Move or Async here would be an error but still we're parsing a closure
                let dist =
                    if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };

                self.look_ahead(dist, |token| matches!(token.kind, token::Or | token::OrOr))
            })
        } else {
            false
        }
    }

    pub(super) fn is_unsafe_foreign_mod(&self) -> bool {
        // Look for `unsafe`.
        if !self.token.is_keyword(kw::Unsafe) {
            return false;
        }
        // Look for `extern`.
        if !self.is_keyword_ahead(1, &[kw::Extern]) {
            return false;
        }

        // Look for the optional ABI string literal.
        let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };

        // Look for the `{`. Use `tree_look_ahead` because the ABI (if present)
        // might be a metavariable i.e. an invisible-delimited sequence, and
        // `tree_look_ahead` will consider that a single element when looking
        // ahead.
        self.tree_look_ahead(n, |t| matches!(t, TokenTree::Delimited(_, _, Delimiter::Brace, _)))
            == Some(true)
    }

    fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
        let is_global_static = if self.check_keyword_case(exp!(Static), case) {
            // Check if this could be a closure.
            !self.look_ahead(1, |token| {
                if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
                    return true;
                }
                matches!(token.kind, token::Or | token::OrOr)
            })
        } else {
            // `$qual static`
            (self.check_keyword_case(exp!(Unsafe), case)
                || self.check_keyword_case(exp!(Safe), case))
                && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
        };

        if is_global_static {
            let safety = self.parse_safety(case);
            let _ = self.eat_keyword_case(exp!(Static), case);
            Some(safety)
        } else {
            None
        }
    }

    /// Recover on `const mut` with `const` already eaten.
    fn recover_const_mut(&mut self, const_span: Span) {
        if self.eat_keyword(exp!(Mut)) {
            let span = self.prev_token.span;
            self.dcx()
                .emit_err(diagnostics::ConstGlobalCannotBeMutable { ident_span: span, const_span });
        } else if self.eat_keyword(exp!(Let)) {
            let span = self.prev_token.span;
            self.dcx()
                .emit_err(diagnostics::ConstLetMutuallyExclusive { span: const_span.to(span) });
        }
    }

    fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
        self.expect_keyword(exp!(Const))?;
        let const_span = self.prev_token.span;
        self.psess.gated_spans.gate(sym::const_block_items, const_span);
        let block = self.parse_block()?;
        Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
    }

    /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in
    /// `mutability`.
    ///
    /// ```ebnf
    /// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ;
    /// ```
    fn parse_static_item(
        &mut self,
        safety: Safety,
        mutability: Mutability,
    ) -> PResult<'a, ItemKind> {
        let ident = self.parse_ident()?;

        if self.token == TokenKind::Lt && self.may_recover() {
            let generics = self.parse_generics()?;
            self.dcx().emit_err(diagnostics::StaticWithGenerics { span: generics.span });
        }

        // Parse the type of a static item. That is, the `":" $ty` fragment.
        // FIXME: This could maybe benefit from `.may_recover()`?
        let ty = match (self.eat(exp!(Colon)), self.check(exp!(Eq)) | self.check(exp!(Semi))) {
            (true, false) => self.parse_ty()?,
            // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing
            // type.
            (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
        };

        let expr = if self.eat(exp!(Eq)) { Some(self.parse_expr()?) } else { None };

        self.expect_semi()?;

        let item =
            StaticItem { ident, ty, safety, mutability, expr, define_opaque: None, eii_impl: None };
        Ok(ItemKind::Static(Box::new(item)))
    }

    /// Parse a constant item with the prefix `"const"` already parsed.
    ///
    /// If `const_arg` is true, any expression assigned to the const will be parsed
    /// as a const_arg instead of a body expression.
    ///
    /// ```ebnf
    /// Const = "const" ($ident | "_") Generics ":" $ty (= $expr)? WhereClause ";" ;
    /// ```
    fn parse_const_item(
        &mut self,
        const_span: Span,
    ) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<Box<Expr>>)> {
        let ident = self.parse_ident_or_underscore()?;

        let mut generics = self.parse_generics()?;

        // Check the span for emptiness instead of the list of parameters in order to correctly
        // recognize and subsequently flag empty parameter lists (`<>`) as unstable.
        if !generics.span.is_empty() {
            self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
        }

        // Parse the type of a constant item. That is, the `":" $ty` fragment.
        // FIXME: This could maybe benefit from `.may_recover()`?
        let ty = match (
            self.eat(exp!(Colon)),
            self.check(exp!(Eq)) | self.check(exp!(Semi)) | self.check_keyword(exp!(Where)),
        ) {
            (true, false) => self.parse_ty()?,
            // If there wasn't a `:` or the colon was followed by a `=`, `;` or `where`, recover a missing type.
            (colon, _) => self.recover_missing_global_item_type(colon, None),
        };

        // Proactively parse a where-clause to be able to provide a good error message in case we
        // encounter the item body following it.
        let before_where_clause =
            if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };

        let rhs = if self.eat(exp!(Eq)) { Some(self.parse_expr()?) } else { None };

        let after_where_clause = self.parse_where_clause()?;

        // Provide a nice error message if the user placed a where-clause before the item body.
        // Users may be tempted to write such code if they are still used to the deprecated
        // where-clause location on type aliases and associated types. See also #89122.
        if before_where_clause.has_where_token
            && let Some(rhs) = &rhs
        {
            self.dcx().emit_err(diagnostics::WhereClauseBeforeConstBody {
                span: before_where_clause.span,
                name: ident.span,
                body: rhs.span,
                sugg: if !after_where_clause.has_where_token {
                    self.psess.source_map().span_to_snippet(rhs.span).ok().map(|body_s| {
                        diagnostics::WhereClauseBeforeConstBodySugg {
                            left: before_where_clause.span.shrink_to_lo(),
                            snippet: body_s,
                            right: before_where_clause.span.shrink_to_hi().to(rhs.span),
                        }
                    })
                } else {
                    // FIXME(generic_const_items): Provide a structured suggestion to merge the first
                    // where-clause into the second one.
                    None
                },
            });
        }

        // Merge the predicates of both where-clauses since either one can be relevant.
        // If we didn't parse a body (which is valid for associated consts in traits) and we were
        // allowed to recover, `before_where_clause` contains the predicates, otherwise they are
        // in `after_where_clause`. Further, both of them might contain predicates iff two
        // where-clauses were provided which is syntactically ill-formed but we want to recover from
        // it and treat them as one large where-clause.
        let mut predicates = before_where_clause.predicates;
        predicates.extend(after_where_clause.predicates);
        let where_clause = WhereClause {
            has_where_token: before_where_clause.has_where_token
                || after_where_clause.has_where_token,
            predicates,
            span: if after_where_clause.has_where_token {
                after_where_clause.span
            } else {
                before_where_clause.span
            },
        };

        if where_clause.has_where_token {
            self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
        }

        generics.where_clause = where_clause;

        if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {
            return Ok((ident, generics, ty, Some(rhs)));
        }
        self.expect_semi()?;

        Ok((ident, generics, ty, rhs))
    }

    /// We were supposed to parse `":" $ty` but the `:` or the type was missing.
    /// This means that the type is missing.
    fn recover_missing_global_item_type(
        &mut self,
        colon_present: bool,
        m: Option<Mutability>,
    ) -> Box<Ty> {
        // Construct the error and stash it away with the hope
        // that typeck will later enrich the error with a type.
        let kind = match m {
            Some(Mutability::Mut) => "static mut",
            Some(Mutability::Not) => "static",
            None => "const",
        };

        let colon = match colon_present {
            true => "",
            false => ":",
        };

        let span = self.prev_token.span.shrink_to_hi();
        let err = self.dcx().create_err(diagnostics::MissingConstType { span, colon, kind });
        err.stash(span, StashKey::ItemNoType);

        // The user intended that the type be inferred,
        // so treat this as if the user wrote e.g. `const A: _ = expr;`.
        Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID })
    }

    /// Parses an enum declaration.
    fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
        if self.token.is_keyword(kw::Struct) {
            let span = self.prev_token.span.to(self.token.span);
            let err = diagnostics::EnumStructMutuallyExclusive { span };
            if self.look_ahead(1, |t| t.is_ident()) {
                self.bump();
                self.dcx().emit_err(err);
            } else {
                return Err(self.dcx().create_err(err));
            }
        }

        let prev_span = self.prev_token.span;
        let ident = self.parse_ident()?;
        let mut generics = self.parse_generics()?;
        generics.where_clause = self.parse_where_clause()?;

        // Possibly recover `enum Foo;` instead of `enum Foo {}`
        let (variants, _) = if self.token == TokenKind::Semi {
            self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
            self.bump();
            (thin_vec![], Trailing::No)
        } else {
            self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), |p| {
                p.parse_enum_variant(ident.span)
            })
            .map_err(|mut err| {
                err.span_label(ident.span, "while parsing this enum");
                // Try to recover `enum Foo { ident : Ty }`.
                if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
                    let snapshot = self.create_snapshot_for_diagnostic();
                    self.bump();
                    match self.parse_ty() {
                        Ok(_) => {
                            err.span_suggestion_verbose(
                                prev_span,
                                "perhaps you meant to use `struct` here",
                                "struct",
                                Applicability::MaybeIncorrect,
                            );
                        }
                        Err(e) => {
                            e.cancel();
                        }
                    }
                    self.restore_snapshot(snapshot);
                }
                self.eat_to_tokens(&[exp!(CloseBrace)]);
                self.bump(); // }
                err
            })?
        };

        let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
        Ok(ItemKind::Enum(ident, generics, enum_definition))
    }

    fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
        self.recover_vcs_conflict_marker();
        let variant_attrs = self.parse_outer_attributes()?;
        self.recover_vcs_conflict_marker();
        let help = "enum variants can be `Variant`, `Variant = <integer>`, \
                    `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
        self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
            let vlo = this.token.span;

            let vis = this.parse_visibility(FollowedByType::No)?;
            if !this.recover_nested_adt_item(kw::Enum)? {
                return Ok((None, Trailing::No, UsePreAttrPos::No));
            }
            let ident = this.parse_field_ident("enum", vlo)?;

            if this.token == token::Bang {
                if let Err(err) = this.unexpected() {
                    err.with_note(msg!("macros cannot expand to enum variants")).emit();
                }

                this.bump();
                this.parse_delim_args()?;

                return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
            }

            let struct_def = if this.check(exp!(OpenBrace)) {
                // Parse a struct variant.
                let (fields, recovered) =
                    match this.parse_record_struct_body("struct", ident.span, false) {
                        Ok((fields, recovered)) => (fields, recovered),
                        Err(mut err) => {
                            if this.token == token::Colon {
                                // We handle `enum` to `struct` suggestion in the caller.
                                return Err(err);
                            }
                            this.eat_to_tokens(&[exp!(CloseBrace)]);
                            this.bump(); // }
                            err.span_label(span, "while parsing this enum");
                            err.help(help);
                            let guar = err.emit();
                            (thin_vec![], Recovered::Yes(guar))
                        }
                    };
                VariantData::Struct { fields, recovered }
            } else if this.check(exp!(OpenParen)) {
                let body = match this.parse_tuple_struct_body() {
                    Ok(body) => body,
                    Err(mut err) => {
                        if this.token == token::Colon {
                            // We handle `enum` to `struct` suggestion in the caller.
                            return Err(err);
                        }
                        this.eat_to_tokens(&[exp!(CloseParen)]);
                        this.bump(); // )
                        err.span_label(span, "while parsing this enum");
                        err.help(help);
                        err.emit();
                        thin_vec![]
                    }
                };
                VariantData::Tuple(body, DUMMY_NODE_ID)
            } else {
                VariantData::Unit(DUMMY_NODE_ID)
            };

            let disr_expr =
                if this.eat(exp!(Eq)) { Some(this.parse_expr_anon_const()?) } else { None };

            let span = vlo.to(this.prev_token.span);
            if ident.name == kw::Underscore {
                this.psess.gated_spans.gate(sym::unnamed_enum_variants, span);
            }
            let vr = ast::Variant {
                ident,
                vis,
                id: DUMMY_NODE_ID,
                attrs: variant_attrs,
                data: struct_def,
                disr_expr,
                span,
                is_placeholder: false,
            };

            Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
        })
        .map_err(|mut err| {
            err.help(help);
            err
        })
    }

    /// Parses `struct Foo { ... }`.
    fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
        let ident = self.parse_ident()?;

        let mut generics = self.parse_generics()?;

        // There is a special case worth noting here, as reported in issue #17904.
        // If we are parsing a tuple struct it is the case that the where clause
        // should follow the field list. Like so:
        //
        // struct Foo<T>(T) where T: Copy;
        //
        // If we are parsing a normal record-style struct it is the case
        // that the where clause comes before the body, and after the generics.
        // So if we look ahead and see a brace or a where-clause we begin
        // parsing a record style struct.
        //
        // Otherwise if we look ahead and see a paren we parse a tuple-style
        // struct.

        let vdata = if self.token.is_keyword(kw::Where) {
            let tuple_struct_body;
            (generics.where_clause, tuple_struct_body) =
                self.parse_struct_where_clause(ident, generics.span)?;

            if let Some(body) = tuple_struct_body {
                // If we see a misplaced tuple struct body: `struct Foo<T> where T: Copy, (T);`
                let body = VariantData::Tuple(body, DUMMY_NODE_ID);
                self.expect_semi()?;
                body
            } else if self.eat(exp!(Semi)) {
                // If we see a: `struct Foo<T> where T: Copy;` style decl.
                VariantData::Unit(DUMMY_NODE_ID)
            } else {
                // If we see: `struct Foo<T> where T: Copy { ... }`
                let (fields, recovered) = self.parse_record_struct_body(
                    "struct",
                    ident.span,
                    generics.where_clause.has_where_token,
                )?;
                VariantData::Struct { fields, recovered }
            }
        // No `where` so: `struct Foo<T>;`
        } else if self.eat(exp!(Semi)) {
            VariantData::Unit(DUMMY_NODE_ID)
        // Record-style struct definition
        } else if self.token == token::OpenBrace {
            let (fields, recovered) = self.parse_record_struct_body(
                "struct",
                ident.span,
                generics.where_clause.has_where_token,
            )?;
            VariantData::Struct { fields, recovered }
        // Tuple-style struct definition with optional where-clause.
        } else if self.token == token::OpenParen {
            let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
            generics.where_clause = self.parse_where_clause()?;
            self.expect_semi()?;
            body
        } else {
            let err = diagnostics::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
            return Err(self.dcx().create_err(err));
        };

        Ok(ItemKind::Struct(ident, generics, vdata))
    }

    /// Parses `union Foo { ... }`.
    fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
        let ident = self.parse_ident()?;

        let mut generics = self.parse_generics()?;

        let vdata = if self.token.is_keyword(kw::Where) {
            generics.where_clause = self.parse_where_clause()?;
            let (fields, recovered) = self.parse_record_struct_body(
                "union",
                ident.span,
                generics.where_clause.has_where_token,
            )?;
            VariantData::Struct { fields, recovered }
        } else if self.token == token::OpenBrace {
            let (fields, recovered) = self.parse_record_struct_body(
                "union",
                ident.span,
                generics.where_clause.has_where_token,
            )?;
            VariantData::Struct { fields, recovered }
        } else {
            let token_str = super::token_descr(&self.token);
            let msg = format!("expected `where` or `{{` after union name, found {token_str}");
            let mut err = self.dcx().struct_span_err(self.token.span, msg);
            err.span_label(self.token.span, "expected `where` or `{` after union name");
            return Err(err);
        };

        Ok(ItemKind::Union(ident, generics, vdata))
    }

    /// This function parses the fields of record structs:
    ///
    ///   - `struct S { ... }`
    ///   - `enum E { Variant { ... } }`
    pub(crate) fn parse_record_struct_body(
        &mut self,
        adt_ty: &str,
        ident_span: Span,
        parsed_where: bool,
    ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
        let mut fields = ThinVec::new();
        let mut recovered = Recovered::No;
        if self.eat(exp!(OpenBrace)) {
            while self.token != token::CloseBrace {
                match self.parse_field_def(adt_ty, ident_span) {
                    Ok(field) => {
                        fields.push(field);
                    }
                    Err(mut err) => {
                        self.consume_block(
                            exp!(OpenBrace),
                            exp!(CloseBrace),
                            ConsumeClosingDelim::No,
                        );
                        err.span_label(ident_span, format!("while parsing this {adt_ty}"));
                        let guar = err.emit();
                        recovered = Recovered::Yes(guar);
                        break;
                    }
                }
            }
            self.expect(exp!(CloseBrace))?;
        } else {
            let token_str = super::token_descr(&self.token);
            let where_str = if parsed_where { "" } else { "`where`, or " };
            let msg = format!("expected {where_str}`{{` after struct name, found {token_str}");
            let mut err = self.dcx().struct_span_err(self.token.span, msg);
            err.span_label(self.token.span, format!("expected {where_str}`{{` after struct name",));
            return Err(err);
        }

        Ok((fields, recovered))
    }

    fn parse_unsafe_field(&mut self) -> Safety {
        // not using parse_safety as that also accepts `safe`.
        if self.eat_keyword(exp!(Unsafe)) {
            let span = self.prev_token.span;
            self.psess.gated_spans.gate(sym::unsafe_fields, span);
            Safety::Unsafe(span)
        } else {
            Safety::Default
        }
    }
    /// This is the case where we find `struct Foo<T>(T) where T: Copy;`
    /// Unit like structs are handled in parse_item_struct function
    pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
        let openparen_span = self.token.span;
        let mut encountered_colon = false;
        self.parse_paren_comma_seq(|p| {
            let attrs = p.parse_outer_attributes()?;
            p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
                let mut snapshot = None;
                if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
                    // Account for `<<<<<<<` diff markers. We can't proactively error here because
                    // that can be a valid type start, so we snapshot and reparse only we've
                    // encountered another parse error.
                    snapshot = Some(p.create_snapshot_for_diagnostic());
                }
                let lo = p.token.span;
                let vis = match p.parse_visibility(FollowedByType::Yes) {
                    Ok(vis) => vis,
                    Err(err) => {
                        if let Some(ref mut snapshot) = snapshot {
                            snapshot.recover_vcs_conflict_marker();
                        }
                        return Err(err);
                    }
                };
                let mut_restriction = p.parse_mut_restriction()?;
                encountered_colon |=
                    p.token.is_ident() && p.look_ahead(1, |tok| tok == &token::Colon);
                // Unsafe fields are not supported in tuple structs, as doing so would result in a
                // parsing ambiguity for `struct X(unsafe fn())`.
                let ty = match p.parse_ty() {
                    Ok(ty) => ty,
                    Err(err) => {
                        if let Some(ref mut snapshot) = snapshot {
                            snapshot.recover_vcs_conflict_marker();
                        }
                        return Err(err);
                    }
                };
                let mut default = None;
                if p.token == token::Eq {
                    let mut snapshot = p.create_snapshot_for_diagnostic();
                    snapshot.bump();
                    match snapshot.parse_expr_anon_const() {
                        Ok(const_expr) => {
                            let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
                            p.psess.gated_spans.gate(sym::default_field_values, sp);
                            p.restore_snapshot(snapshot);
                            default = Some(const_expr);
                        }
                        Err(err) => {
                            err.cancel();
                        }
                    }
                }

                Ok((
                    FieldDef {
                        span: lo.to(ty.span),
                        vis,
                        extras: Self::field_def_extras(Safety::Default, mut_restriction, default),
                        ident: None,
                        id: DUMMY_NODE_ID,
                        ty,
                        attrs,
                        is_placeholder: false,
                    },
                    Trailing::from(p.token == token::Comma),
                    UsePreAttrPos::No,
                ))
            })
        })
        .map(|(r, _)| r)
        .map_err(|mut error| {
            if self.token == token::Colon {
                error.subdiagnostic(UseDoubleColonSuggestion { colon: self.token.span });
            }
            if encountered_colon {
                self.eat_to_tokens(&[exp!(CloseParen)]);
                self.bump();
                error.subdiagnostic(UseRegularStructSuggestion {
                    open: openparen_span,
                    close: self.prev_token.span,
                    semicolon: if self.token == token::Semi { Some(self.token.span) } else { None },
                });
            }
            error
        })
    }

    fn field_def_extras(
        safety: Safety,
        mut_restriction: MutRestriction,
        default: Option<AnonConst>,
    ) -> Option<Box<FieldDefExtras>> {
        match (safety, mut_restriction, default) {
            (
                Safety::Default,
                // We are throwing away the mut restriction span here.
                // see the span field comment for more info
                MutRestriction { kind: RestrictionKind::Unrestricted, span: _ },
                None,
            ) => None,
            (safety, mut_restriction, default) => {
                Some(Box::new(FieldDefExtras { safety, mut_restriction, default }))
            }
        }
    }

    /// Parses an element of a struct declaration.
    fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
        self.recover_vcs_conflict_marker();
        let attrs = self.parse_outer_attributes()?;
        self.recover_vcs_conflict_marker();
        self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
            let lo = this.token.span;
            let vis = this.parse_visibility(FollowedByType::No)?;
            let mut_restriction = this.parse_mut_restriction()?;
            let safety = this.parse_unsafe_field();
            this.parse_single_struct_field(
                adt_ty,
                lo,
                vis,
                mut_restriction,
                safety,
                attrs,
                ident_span,
            )
            .map(|field| (field, Trailing::No, UsePreAttrPos::No))
        })
    }

    /// Parses a structure field declaration.
    fn parse_single_struct_field(
        &mut self,
        adt_ty: &str,
        lo: Span,
        vis: Visibility,
        mut_restriction: MutRestriction,
        safety: Safety,
        attrs: AttrVec,
        ident_span: Span,
    ) -> PResult<'a, FieldDef> {
        let a_var = self.parse_name_and_ty(adt_ty, lo, vis, mut_restriction, safety, attrs)?;
        match self.token.kind {
            token::Comma => {
                self.bump();
            }
            token::Semi => {
                self.bump();
                let sp = self.prev_token.span;
                let mut err =
                    self.dcx().struct_span_err(sp, format!("{adt_ty} fields are separated by `,`"));
                err.span_suggestion_short(
                    sp,
                    "replace `;` with `,`",
                    ",",
                    Applicability::MachineApplicable,
                );
                err.span_label(ident_span, format!("while parsing this {adt_ty}"));
                err.emit();
            }
            token::CloseBrace => {}
            token::DocComment(..) => {
                let previous_span = self.prev_token.span;
                let mut err = diagnostics::DocCommentDoesNotDocumentAnything {
                    span: self.token.span,
                    missing_comma: None,
                };
                self.bump(); // consume the doc comment
                if self.eat(exp!(Comma)) || self.token == token::CloseBrace {
                    self.dcx().emit_err(err);
                } else {
                    let sp = previous_span.shrink_to_hi();
                    err.missing_comma = Some(sp);
                    return Err(self.dcx().create_err(err));
                }
            }
            _ => {
                let sp = self.prev_token.span.shrink_to_hi();
                let msg =
                    format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token));

                // Try to recover extra trailing angle brackets
                if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
                    && let Some(last_segment) = segments.last()
                {
                    let guar = self.check_trailing_angle_brackets(
                        last_segment,
                        &[exp!(Comma), exp!(CloseBrace)],
                    );
                    if let Some(_guar) = guar {
                        // Handle a case like `Vec<u8>>,` where we can continue parsing fields
                        // after the comma
                        let _ = self.eat(exp!(Comma));

                        // `check_trailing_angle_brackets` already emitted a nicer error, as
                        // proven by the presence of `_guar`. We can continue parsing.
                        return Ok(a_var);
                    }
                }

                let mut err = self.dcx().struct_span_err(sp, msg);

                if self.token.is_ident()
                    || (self.token == TokenKind::Pound
                        && (self.look_ahead(1, |t| t == &token::OpenBracket)))
                {
                    // This is likely another field, TokenKind::Pound is used for `#[..]`
                    // attribute for next field. Emit the diagnostic and continue parsing.
                    err.span_suggestion(
                        sp,
                        "try adding a comma",
                        ",",
                        Applicability::MachineApplicable,
                    );
                    err.emit();
                } else {
                    return Err(err);
                }
            }
        }
        Ok(a_var)
    }

    fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
        if let Err(err) = self.expect(exp!(Colon)) {
            let sm = self.psess.source_map();
            let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
            let semi_typo = self.token == token::Semi
                && self.look_ahead(1, |t| {
                    t.is_path_start()
                    // We check that we are in a situation like `foo; bar` to avoid bad suggestions
                    // when there's no type and `;` was used instead of a comma.
                    && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
                        (Ok(l), Ok(r)) => l.line == r.line,
                        _ => true,
                    }
                });
            if eq_typo || semi_typo {
                self.bump();
                // Gracefully handle small typos.
                err.with_span_suggestion_short(
                    self.prev_token.span,
                    "field names and their types are separated with `:`",
                    ":",
                    Applicability::MachineApplicable,
                )
                .emit();
            } else {
                return Err(err);
            }
        }
        Ok(())
    }

    /// Parses a structure field.
    fn parse_name_and_ty(
        &mut self,
        adt_ty: &str,
        lo: Span,
        vis: Visibility,
        mut_restriction: MutRestriction,
        safety: Safety,
        attrs: AttrVec,
    ) -> PResult<'a, FieldDef> {
        let name = self.parse_field_ident(adt_ty, lo)?;
        if self.token == token::Bang {
            if let Err(mut err) = self.unexpected() {
                // Encounter the macro invocation
                err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
                return Err(err);
            }
        }
        self.expect_field_ty_separator()?;
        let ty = self.parse_ty()?;
        if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
            return Err(self
                .dcx()
                .struct_span_err(self.token.span, "found single colon in a struct field type path")
                .with_span_suggestion_verbose(
                    self.token.span,
                    "write a path separator here",
                    "::",
                    Applicability::MaybeIncorrect,
                ));
        }
        let default = if self.token == token::Eq {
            self.bump();
            let const_expr = self.parse_expr_anon_const()?;
            let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
            self.psess.gated_spans.gate(sym::default_field_values, sp);
            Some(const_expr)
        } else {
            None
        };
        Ok(FieldDef {
            span: lo.to(self.prev_token.span),
            ident: Some(name),
            vis,
            extras: Self::field_def_extras(safety, mut_restriction, default),
            id: DUMMY_NODE_ID,
            ty,
            attrs,
            is_placeholder: false,
        })
    }

    /// Parses a field identifier. Specialized version of `parse_ident_common`
    /// for better diagnostics and suggestions.
    fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
        let (ident, is_raw) = self.ident_or_err(true)?;
        if is_raw == IdentIsRaw::No
            && ident.is_reserved()
            && !(ident.name == kw::Underscore && adt_ty == "enum")
        {
            let snapshot = self.create_snapshot_for_diagnostic();
            let err = if self.check_fn_front_matter(false, Case::Sensitive) {
                let inherited_vis = Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited };
                // We use `parse_fn` to get a span for the function
                let fn_parse_mode =
                    FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
                match self.parse_fn(
                    &mut AttrVec::new(),
                    fn_parse_mode,
                    lo,
                    &inherited_vis,
                    Case::Insensitive,
                ) {
                    Ok(_) => self
                        .dcx()
                        .struct_span_err(
                            lo.to(self.prev_token.span),
                            format!("functions are not allowed in {adt_ty} definitions"),
                        )
                        .with_help(
                            "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
                        )
                        .with_help(
                            "see https://doc.rust-lang.org/book/ch05-03-method-syntax.html \
                             for more information",
                        ),
                    Err(err) => {
                        err.cancel();
                        self.restore_snapshot(snapshot);
                        self.expected_ident_found_err()
                    }
                }
            } else if self.eat_keyword(exp!(Struct)) {
                match self.parse_item_struct() {
                    Ok(item) => {
                        let ItemKind::Struct(ident, ..) = item else { unreachable!() };
                        self.dcx()
                            .struct_span_err(
                                lo.with_hi(ident.span.hi()),
                                format!("structs are not allowed in {adt_ty} definitions"),
                            )
                            .with_help(
                                "consider creating a new `struct` definition instead of nesting",
                            )
                    }
                    Err(err) => {
                        err.cancel();
                        self.restore_snapshot(snapshot);
                        self.expected_ident_found_err()
                    }
                }
            } else {
                let mut err = self.expected_ident_found_err();
                if self.eat_keyword_noexpect(kw::Let)
                    && let removal_span = self.prev_token.span.until(self.token.span)
                    && let Ok(ident) = self
                        .parse_ident_common(false)
                        // Cancel this error, we don't need it.
                        .map_err(|err| err.cancel())
                    && self.token == TokenKind::Colon
                {
                    err.span_suggestion_verbose(
                        removal_span,
                        "remove the `let` keyword",
                        String::new(),
                        Applicability::MachineApplicable,
                    );
                    err.note("the `let` keyword is not allowed in `struct` fields");
                    err.note(
                        "see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> \
                         for more information",
                    );
                    err.emit();
                    return Ok(ident);
                } else {
                    self.restore_snapshot(snapshot);
                }
                err
            };
            return Err(err);
        }
        self.bump();
        Ok(ident)
    }

    /// Parses a declarative macro 2.0 definition.
    /// The `macro` keyword has already been parsed.
    /// ```ebnf
    /// MacBody = "{" TOKEN_STREAM "}" ;
    /// MacParams = "(" TOKEN_STREAM ")" ;
    /// DeclMac = "macro" Ident MacParams? MacBody ;
    /// ```
    fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
        let ident = self.parse_ident()?;
        let body = if self.check(exp!(OpenBrace)) {
            self.parse_delim_args()? // `MacBody`
        } else if self.check(exp!(OpenParen)) {
            let params = self.parse_token_tree(); // `MacParams`
            let pspan = params.span();
            if !self.check(exp!(OpenBrace)) {
                self.unexpected()?;
            }
            let body = self.parse_token_tree(); // `MacBody`
            // Convert `MacParams MacBody` into `{ MacParams => MacBody }`.
            let bspan = body.span();
            let arrow = TokenTree::token_alone(token::FatArrow, pspan.between(bspan)); // `=>`
            let tokens = TokenStream::new(vec![params, arrow, body]);
            let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
            Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
        } else {
            self.unexpected_any()?
        };

        self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
        Ok(ItemKind::MacroDef(
            ident,
            ast::MacroDef { body, macro_rules: false, eii_declaration: None },
        ))
    }

    /// Is this a possibly malformed start of a `macro_rules! foo` item definition?
    fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
        if self.check_keyword(exp!(MacroRules)) {
            let macro_rules_span = self.token.span;

            if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
                return IsMacroRulesItem::Yes { has_bang: true };
            } else if self.look_ahead(1, |t| t.is_ident()) {
                // macro_rules foo
                self.dcx().emit_err(diagnostics::MacroRulesMissingBang {
                    span: macro_rules_span,
                    hi: macro_rules_span.shrink_to_hi(),
                });

                return IsMacroRulesItem::Yes { has_bang: false };
            }
        }

        IsMacroRulesItem::No
    }

    /// Parses a `macro_rules! foo { ... }` declarative macro.
    fn parse_item_macro_rules(
        &mut self,
        vis: &Visibility,
        has_bang: bool,
    ) -> PResult<'a, ItemKind> {
        self.expect_keyword(exp!(MacroRules))?; // `macro_rules`

        if has_bang {
            self.expect(exp!(Bang))?; // `!`
        }
        let ident = self.parse_ident()?;

        if self.eat(exp!(Bang)) {
            // Handle macro_rules! foo!
            let span = self.prev_token.span;
            self.dcx().emit_err(diagnostics::MacroNameRemoveBang { span });
        }

        let body = self.parse_delim_args()?;
        self.eat_semi_for_macro_if_needed(&body, None);
        self.complain_if_pub_macro(vis, true);

        Ok(ItemKind::MacroDef(
            ident,
            ast::MacroDef { body, macro_rules: true, eii_declaration: None },
        ))
    }

    /// Item macro invocations or `macro_rules!` definitions need inherited visibility.
    /// If that's not the case, emit an error.
    fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
        if let VisibilityKind::Inherited = vis.kind {
            return;
        }

        let vstr = pprust::vis_to_string(vis);
        let vstr = vstr.trim_end();
        if macro_rules {
            self.dcx().emit_err(diagnostics::MacroRulesVisibility { span: vis.span, vis: vstr });
        } else {
            self.dcx()
                .emit_err(diagnostics::MacroInvocationVisibility { span: vis.span, vis: vstr });
        }
    }

    fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
        if args.need_semicolon() && !self.eat(exp!(Semi)) {
            self.report_invalid_macro_expansion_item(args, path);
        }
    }

    fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
        let span = args.dspan.entire();
        let mut err = self.dcx().struct_span_err(
            span,
            "macros that expand to items must be delimited with braces or followed by a semicolon",
        );
        // FIXME: This will make us not emit the help even for declarative
        // macros within the same crate (that we can fix), which is sad.
        if !span.from_expansion() {
            let DelimSpan { open, close } = args.dspan;
            // Check if this looks like `macro_rules!(name) { ... }`
            // a common mistake when trying to define a macro.
            if let Some(path) = path
                && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
                && args.delim == Delimiter::Parenthesis
            {
                let replace =
                    if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
                err.multipart_suggestion(
                    "to define a macro, remove the parentheses around the macro name",
                    vec![(open, replace.to_string()), (close, String::new())],
                    Applicability::MachineApplicable,
                );
            } else {
                err.multipart_suggestion(
                    "change the delimiters to curly braces",
                    vec![(open, "{".to_string()), (close, '}'.to_string())],
                    Applicability::MaybeIncorrect,
                );
                err.span_suggestion_verbose(
                    span.with_neighbor(self.token.span).shrink_to_hi(),
                    "add a semicolon",
                    ';',
                    Applicability::MaybeIncorrect,
                );
            }
        }
        err.emit();
    }

    /// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case
    /// it is, we try to parse the item and report error about nested types.
    fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
        if (self.token.is_keyword(kw::Enum)
            || self.token.is_keyword(kw::Struct)
            || self.token.is_keyword(kw::Union))
            && self.look_ahead(1, |t| t.is_ident())
        {
            let kw_token = self.token;
            let kw_str = pprust::token_to_string(&kw_token);
            let item = self.parse_item(
                ForceCollect::No,
                AllowConstBlockItems::DoesNotMatter, // self.token != kw::Const
            )?;
            let mut item = item.unwrap().span;
            if self.token == token::Comma {
                item = item.to(self.token.span);
            }
            self.dcx().emit_err(diagnostics::NestedAdt {
                span: kw_token.span,
                item,
                kw_str,
                keyword: keyword.as_str(),
            });
            // We successfully parsed the item but we must inform the caller about nested problem.
            return Ok(false);
        }
        Ok(true)
    }

    fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
        const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
        // In contrast to the loop below, this call inserts `impl` into the
        // list of expected tokens shown in diagnostics.
        if self.check_keyword(exp!(Impl)) {
            return true;
        }
        let mut i = 0;
        while i < ALL_QUALS.len() {
            let action = self.look_ahead(i + look_ahead, |token| {
                if token.is_keyword(kw::Impl) {
                    return Some(true);
                }
                if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
                    // Ok, we found a legal keyword, keep looking for `impl`
                    return None;
                }
                Some(false)
            });
            if let Some(ret) = action {
                return ret;
            }
            i += 1;
        }

        self.is_keyword_ahead(i, &[kw::Impl])
    }

    /// Try to recover from over-parsing in const item when a semicolon is missing.
    ///
    /// This detects cases where we parsed too much because a semicolon was missing
    /// and the next line started an expression that the parser treated as a continuation
    /// (e.g., `foo() \n &bar` was parsed as `foo() & bar`).
    ///
    /// Returns a corrected expression if recovery is successful.
    fn try_recover_const_missing_semi(
        &mut self,
        rhs: &Option<Box<Expr>>,
        const_span: Span,
    ) -> Option<Box<Expr>> {
        if self.token == TokenKind::Semi {
            return None;
        }
        let Some(rhs) = rhs else {
            return None;
        };
        if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
            return None;
        }
        if let Some((span, guar)) =
            self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
        {
            self.fn_body_missing_semi_guar = Some(guar);
            Some(self.mk_expr(span, ExprKind::Err(guar)))
        } else {
            None
        }
    }
}
enum IsMacroRulesItem {
    Yes { has_bang: bool },
    No,
}
