use std::ops::Deref;
use std::path::PathBuf;
use std::rc::Rc;
use std::{iter, mem};

use rustc_ast as ast;
use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};
use rustc_ast::{
    AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind, ForeignItemKind,
    HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind,
    NodeId, PatKind, StmtKind, TyKind,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_data_structures::sync::Lrc;
use rustc_errors::PResult;
use rustc_feature::Features;
use rustc_parse::parser::{
    AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
};
use rustc_parse::validate_attr;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
use rustc_session::parse::feature_err;
use rustc_session::{Limit, Session};
use rustc_span::hygiene::SyntaxContext;
use rustc_span::symbol::{Ident, sym};
use rustc_span::{ErrorGuaranteed, FileName, LocalExpnId, Span};
use smallvec::SmallVec;

use crate::base::*;
use crate::config::StripUnconfigured;
use crate::errors::{
    EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,
    RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,
    WrongFragmentKind,
};
use crate::fluent_generated;
use crate::mbe::diagnostics::annotate_err_with_kind;
use crate::module::{
    DirOwnership, ParsedExternalMod, mod_dir_path, mod_file_path_from_attr, parse_external_mod,
};
use crate::placeholders::{PlaceholderExpander, placeholder};

macro_rules! ast_fragments {
    (
        $($Kind:ident($AstTy:ty) {
            $kind_name:expr;
            $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)?
            $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)?
            fn $make_ast:ident;
        })*
    ) => {
        /// A fragment of AST that can be produced by a single macro expansion.
        /// Can also serve as an input and intermediate result for macro expansion operations.
        pub enum AstFragment {
            OptExpr(Option<P<ast::Expr>>),
            MethodReceiverExpr(P<ast::Expr>),
            $($Kind($AstTy),)*
        }

        /// "Discriminant" of an AST fragment.
        #[derive(Copy, Clone, PartialEq, Eq)]
        pub enum AstFragmentKind {
            OptExpr,
            MethodReceiverExpr,
            $($Kind,)*
        }

        impl AstFragmentKind {
            pub fn name(self) -> &'static str {
                match self {
                    AstFragmentKind::OptExpr => "expression",
                    AstFragmentKind::MethodReceiverExpr => "expression",
                    $(AstFragmentKind::$Kind => $kind_name,)*
                }
            }

            fn make_from<'a>(self, result: Box<dyn MacResult + 'a>) -> Option<AstFragment> {
                match self {
                    AstFragmentKind::OptExpr =>
                        result.make_expr().map(Some).map(AstFragment::OptExpr),
                    AstFragmentKind::MethodReceiverExpr =>
                        result.make_expr().map(AstFragment::MethodReceiverExpr),
                    $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
                }
            }
        }

        impl AstFragment {
            fn add_placeholders(&mut self, placeholders: &[NodeId]) {
                if placeholders.is_empty() {
                    return;
                }
                match self {
                    $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| {
                        ${ignore($flat_map_ast_elt)}
                        placeholder(AstFragmentKind::$Kind, *id, None).$make_ast()
                    })),)?)*
                    _ => panic!("unexpected AST fragment kind")
                }
            }

            pub(crate) fn make_opt_expr(self) -> Option<P<ast::Expr>> {
                match self {
                    AstFragment::OptExpr(expr) => expr,
                    _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
                }
            }

            pub(crate) fn make_method_receiver_expr(self) -> P<ast::Expr> {
                match self {
                    AstFragment::MethodReceiverExpr(expr) => expr,
                    _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
                }
            }

            $(pub fn $make_ast(self) -> $AstTy {
                match self {
                    AstFragment::$Kind(ast) => ast,
                    _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
                }
            })*

            fn make_ast<T: InvocationCollectorNode>(self) -> T::OutputTy {
                T::fragment_to_output(self)
            }

            pub(crate) fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) {
                match self {
                    AstFragment::OptExpr(opt_expr) => {
                        visit_clobber(opt_expr, |opt_expr| {
                            if let Some(expr) = opt_expr {
                                vis.filter_map_expr(expr)
                            } else {
                                None
                            }
                        });
                    }
                    AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
                    $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
                    $($(AstFragment::$Kind(ast) =>
                        ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast, $($args)*)),)?)*
                }
            }

            pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) -> V::Result {
                match self {
                    AstFragment::OptExpr(Some(expr)) => try_visit!(visitor.visit_expr(expr)),
                    AstFragment::OptExpr(None) => {}
                    AstFragment::MethodReceiverExpr(expr) => try_visit!(visitor.visit_method_receiver_expr(expr)),
                    $($(AstFragment::$Kind(ast) => try_visit!(visitor.$visit_ast(ast)),)?)*
                    $($(AstFragment::$Kind(ast) => walk_list!(visitor, $visit_ast_elt, &ast[..], $($args)*),)?)*
                }
                V::Result::output()
            }
        }

        impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> {
            $(fn $make_ast(self: Box<crate::mbe::macro_rules::ParserAnyMacro<'a>>)
                           -> Option<$AstTy> {
                Some(self.make(AstFragmentKind::$Kind).$make_ast())
            })*
        }
    }
}

ast_fragments! {
    Expr(P<ast::Expr>) { "expression"; one fn visit_expr; fn visit_expr; fn make_expr; }
    Pat(P<ast::Pat>) { "pattern"; one fn visit_pat; fn visit_pat; fn make_pat; }
    Ty(P<ast::Ty>) { "type"; one fn visit_ty; fn visit_ty; fn make_ty; }
    Stmts(SmallVec<[ast::Stmt; 1]>) {
        "statement"; many fn flat_map_stmt; fn visit_stmt(); fn make_stmts;
    }
    Items(SmallVec<[P<ast::Item>; 1]>) {
        "item"; many fn flat_map_item; fn visit_item(); fn make_items;
    }
    TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
        "trait item";
        many fn flat_map_assoc_item;
        fn visit_assoc_item(AssocCtxt::Trait);
        fn make_trait_items;
    }
    ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
        "impl item";
        many fn flat_map_assoc_item;
        fn visit_assoc_item(AssocCtxt::Impl);
        fn make_impl_items;
    }
    ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
        "foreign item";
        many fn flat_map_foreign_item;
        fn visit_foreign_item();
        fn make_foreign_items;
    }
    Arms(SmallVec<[ast::Arm; 1]>) {
        "match arm"; many fn flat_map_arm; fn visit_arm(); fn make_arms;
    }
    ExprFields(SmallVec<[ast::ExprField; 1]>) {
        "field expression"; many fn flat_map_expr_field; fn visit_expr_field(); fn make_expr_fields;
    }
    PatFields(SmallVec<[ast::PatField; 1]>) {
        "field pattern";
        many fn flat_map_pat_field;
        fn visit_pat_field();
        fn make_pat_fields;
    }
    GenericParams(SmallVec<[ast::GenericParam; 1]>) {
        "generic parameter";
        many fn flat_map_generic_param;
        fn visit_generic_param();
        fn make_generic_params;
    }
    Params(SmallVec<[ast::Param; 1]>) {
        "function parameter"; many fn flat_map_param; fn visit_param(); fn make_params;
    }
    FieldDefs(SmallVec<[ast::FieldDef; 1]>) {
        "field";
        many fn flat_map_field_def;
        fn visit_field_def();
        fn make_field_defs;
    }
    Variants(SmallVec<[ast::Variant; 1]>) {
        "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
    }
    Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; }
}

pub enum SupportsMacroExpansion {
    No,
    Yes { supports_inner_attrs: bool },
}

impl AstFragmentKind {
    pub(crate) fn dummy(self, span: Span, guar: ErrorGuaranteed) -> AstFragment {
        self.make_from(DummyResult::any(span, guar)).expect("couldn't create a dummy AST fragment")
    }

    pub fn supports_macro_expansion(self) -> SupportsMacroExpansion {
        match self {
            AstFragmentKind::OptExpr
            | AstFragmentKind::Expr
            | AstFragmentKind::MethodReceiverExpr
            | AstFragmentKind::Stmts
            | AstFragmentKind::Ty
            | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false },
            AstFragmentKind::Items
            | AstFragmentKind::TraitItems
            | AstFragmentKind::ImplItems
            | AstFragmentKind::ForeignItems
            | AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true },
            AstFragmentKind::Arms
            | AstFragmentKind::ExprFields
            | AstFragmentKind::PatFields
            | AstFragmentKind::GenericParams
            | AstFragmentKind::Params
            | AstFragmentKind::FieldDefs
            | AstFragmentKind::Variants => SupportsMacroExpansion::No,
        }
    }

    fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(
        self,
        items: I,
    ) -> AstFragment {
        let mut items = items.into_iter();
        match self {
            AstFragmentKind::Arms => {
                AstFragment::Arms(items.map(Annotatable::expect_arm).collect())
            }
            AstFragmentKind::ExprFields => {
                AstFragment::ExprFields(items.map(Annotatable::expect_expr_field).collect())
            }
            AstFragmentKind::PatFields => {
                AstFragment::PatFields(items.map(Annotatable::expect_pat_field).collect())
            }
            AstFragmentKind::GenericParams => {
                AstFragment::GenericParams(items.map(Annotatable::expect_generic_param).collect())
            }
            AstFragmentKind::Params => {
                AstFragment::Params(items.map(Annotatable::expect_param).collect())
            }
            AstFragmentKind::FieldDefs => {
                AstFragment::FieldDefs(items.map(Annotatable::expect_field_def).collect())
            }
            AstFragmentKind::Variants => {
                AstFragment::Variants(items.map(Annotatable::expect_variant).collect())
            }
            AstFragmentKind::Items => {
                AstFragment::Items(items.map(Annotatable::expect_item).collect())
            }
            AstFragmentKind::ImplItems => {
                AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect())
            }
            AstFragmentKind::TraitItems => {
                AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect())
            }
            AstFragmentKind::ForeignItems => {
                AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect())
            }
            AstFragmentKind::Stmts => {
                AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect())
            }
            AstFragmentKind::Expr => AstFragment::Expr(
                items.next().expect("expected exactly one expression").expect_expr(),
            ),
            AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(
                items.next().expect("expected exactly one expression").expect_expr(),
            ),
            AstFragmentKind::OptExpr => {
                AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
            }
            AstFragmentKind::Crate => {
                AstFragment::Crate(items.next().expect("expected exactly one crate").expect_crate())
            }
            AstFragmentKind::Pat | AstFragmentKind::Ty => {
                panic!("patterns and types aren't annotatable")
            }
        }
    }
}

pub struct Invocation {
    pub kind: InvocationKind,
    pub fragment_kind: AstFragmentKind,
    pub expansion_data: ExpansionData,
}

pub enum InvocationKind {
    Bang {
        mac: P<ast::MacCall>,
        span: Span,
    },
    Attr {
        attr: ast::Attribute,
        // Re-insertion position for inert attributes.
        pos: usize,
        item: Annotatable,
        // Required for resolving derive helper attributes.
        derives: Vec<ast::Path>,
    },
    Derive {
        path: ast::Path,
        is_const: bool,
        item: Annotatable,
    },
    GlobDelegation {
        item: P<ast::AssocItem>,
    },
}

impl InvocationKind {
    fn placeholder_visibility(&self) -> Option<ast::Visibility> {
        // HACK: For unnamed fields placeholders should have the same visibility as the actual
        // fields because for tuple structs/variants resolve determines visibilities of their
        // constructor using these field visibilities before attributes on them are expanded.
        // The assumption is that the attribute expansion cannot change field visibilities,
        // and it holds because only inert attributes are supported in this position.
        match self {
            InvocationKind::Attr { item: Annotatable::FieldDef(field), .. }
            | InvocationKind::Derive { item: Annotatable::FieldDef(field), .. }
                if field.ident.is_none() =>
            {
                Some(field.vis.clone())
            }
            _ => None,
        }
    }
}

impl Invocation {
    pub fn span(&self) -> Span {
        match &self.kind {
            InvocationKind::Bang { span, .. } => *span,
            InvocationKind::Attr { attr, .. } => attr.span,
            InvocationKind::Derive { path, .. } => path.span,
            InvocationKind::GlobDelegation { item } => item.span,
        }
    }

    fn span_mut(&mut self) -> &mut Span {
        match &mut self.kind {
            InvocationKind::Bang { span, .. } => span,
            InvocationKind::Attr { attr, .. } => &mut attr.span,
            InvocationKind::Derive { path, .. } => &mut path.span,
            InvocationKind::GlobDelegation { item } => &mut item.span,
        }
    }
}

pub struct MacroExpander<'a, 'b> {
    pub cx: &'a mut ExtCtxt<'b>,
    monotonic: bool, // cf. `cx.monotonic_expander()`
}

impl<'a, 'b> MacroExpander<'a, 'b> {
    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
        MacroExpander { cx, monotonic }
    }

    pub fn expand_crate(&mut self, krate: ast::Crate) -> ast::Crate {
        let file_path = match self.cx.source_map().span_to_filename(krate.spans.inner_span) {
            FileName::Real(name) => name
                .into_local_path()
                .expect("attempting to resolve a file path in an external file"),
            other => PathBuf::from(other.prefer_local().to_string()),
        };
        let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
        self.cx.root_path = dir_path.clone();
        self.cx.current_expansion.module = Rc::new(ModuleData {
            mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
            file_path_stack: vec![file_path],
            dir_path,
        });
        let krate = self.fully_expand_fragment(AstFragment::Crate(krate)).make_crate();
        assert_eq!(krate.id, ast::CRATE_NODE_ID);
        self.cx.trace_macros_diag();
        krate
    }

    /// Recursively expand all macro invocations in this AST fragment.
    pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
        let orig_expansion_data = self.cx.current_expansion.clone();
        let orig_force_mode = self.cx.force_mode;

        // Collect all macro invocations and replace them with placeholders.
        let (mut fragment_with_placeholders, mut invocations) =
            self.collect_invocations(input_fragment, &[]);

        // Optimization: if we resolve all imports now,
        // we'll be able to immediately resolve most of imported macros.
        self.resolve_imports();

        // Resolve paths in all invocations and produce output expanded fragments for them, but
        // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
        // The output fragments also go through expansion recursively until no invocations are left.
        // Unresolved macros produce dummy outputs as a recovery measure.
        invocations.reverse();
        let mut expanded_fragments = Vec::new();
        let mut undetermined_invocations = Vec::new();
        let (mut progress, mut force) = (false, !self.monotonic);
        loop {
            let Some((invoc, ext)) = invocations.pop() else {
                self.resolve_imports();
                if undetermined_invocations.is_empty() {
                    break;
                }
                invocations = mem::take(&mut undetermined_invocations);
                force = !progress;
                progress = false;
                if force && self.monotonic {
                    self.cx.dcx().span_delayed_bug(
                        invocations.last().unwrap().0.span(),
                        "expansion entered force mode without producing any errors",
                    );
                }
                continue;
            };

            let ext = match ext {
                Some(ext) => ext,
                None => {
                    let eager_expansion_root = if self.monotonic {
                        invoc.expansion_data.id
                    } else {
                        orig_expansion_data.id
                    };
                    match self.cx.resolver.resolve_macro_invocation(
                        &invoc,
                        eager_expansion_root,
                        force,
                    ) {
                        Ok(ext) => ext,
                        Err(Indeterminate) => {
                            // Cannot resolve, will retry this invocation later.
                            undetermined_invocations.push((invoc, None));
                            continue;
                        }
                    }
                }
            };

            let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
            let depth = depth - orig_expansion_data.depth;
            self.cx.current_expansion = invoc.expansion_data.clone();
            self.cx.force_mode = force;

            let fragment_kind = invoc.fragment_kind;
            match self.expand_invoc(invoc, &ext.kind) {
                ExpandResult::Ready(fragment) => {
                    let mut derive_invocations = Vec::new();
                    let derive_placeholders = self
                        .cx
                        .resolver
                        .take_derive_resolutions(expn_id)
                        .map(|derives| {
                            derive_invocations.reserve(derives.len());
                            derives
                                .into_iter()
                                .map(|DeriveResolution { path, item, exts: _, is_const }| {
                                    // FIXME: Consider using the derive resolutions (`_exts`)
                                    // instead of enqueuing the derives to be resolved again later.
                                    let expn_id = LocalExpnId::fresh_empty();
                                    derive_invocations.push((
                                        Invocation {
                                            kind: InvocationKind::Derive { path, item, is_const },
                                            fragment_kind,
                                            expansion_data: ExpansionData {
                                                id: expn_id,
                                                ..self.cx.current_expansion.clone()
                                            },
                                        },
                                        None,
                                    ));
                                    NodeId::placeholder_from_expn_id(expn_id)
                                })
                                .collect::<Vec<_>>()
                        })
                        .unwrap_or_default();

                    let (expanded_fragment, collected_invocations) =
                        self.collect_invocations(fragment, &derive_placeholders);
                    // We choose to expand any derive invocations associated with this macro
                    // invocation *before* any macro invocations collected from the output
                    // fragment.
                    derive_invocations.extend(collected_invocations);

                    progress = true;
                    if expanded_fragments.len() < depth {
                        expanded_fragments.push(Vec::new());
                    }
                    expanded_fragments[depth - 1].push((expn_id, expanded_fragment));
                    invocations.extend(derive_invocations.into_iter().rev());
                }
                ExpandResult::Retry(invoc) => {
                    if force {
                        self.cx.dcx().span_bug(
                            invoc.span(),
                            "expansion entered force mode but is still stuck",
                        );
                    } else {
                        // Cannot expand, will retry this invocation later.
                        undetermined_invocations.push((invoc, Some(ext)));
                    }
                }
            }
        }

        self.cx.current_expansion = orig_expansion_data;
        self.cx.force_mode = orig_force_mode;

        // Finally incorporate all the expanded macros into the input AST fragment.
        let mut placeholder_expander = PlaceholderExpander::default();
        while let Some(expanded_fragments) = expanded_fragments.pop() {
            for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
                placeholder_expander
                    .add(NodeId::placeholder_from_expn_id(expn_id), expanded_fragment);
            }
        }
        fragment_with_placeholders.mut_visit_with(&mut placeholder_expander);
        fragment_with_placeholders
    }

    fn resolve_imports(&mut self) {
        if self.monotonic {
            self.cx.resolver.resolve_imports();
        }
    }

    /// Collects all macro invocations reachable at this time in this AST fragment, and replace
    /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
    /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
    /// prepares data for resolving paths of macro invocations.
    fn collect_invocations(
        &mut self,
        mut fragment: AstFragment,
        extra_placeholders: &[NodeId],
    ) -> (AstFragment, Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>) {
        // Resolve `$crate`s in the fragment for pretty-printing.
        self.cx.resolver.resolve_dollar_crates();

        let mut invocations = {
            let mut collector = InvocationCollector {
                // Non-derive macro invocations cannot see the results of cfg expansion - they
                // will either be removed along with the item, or invoked before the cfg/cfg_attr
                // attribute is expanded. Therefore, we don't need to configure the tokens
                // Derive macros *can* see the results of cfg-expansion - they are handled
                // specially in `fully_expand_fragment`
                cx: self.cx,
                invocations: Vec::new(),
                monotonic: self.monotonic,
            };
            fragment.mut_visit_with(&mut collector);
            fragment.add_placeholders(extra_placeholders);
            collector.invocations
        };

        if self.monotonic {
            self.cx
                .resolver
                .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);

            if self.cx.sess.opts.incremental.is_some() {
                for (invoc, _) in invocations.iter_mut() {
                    let expn_id = invoc.expansion_data.id;
                    let parent_def = self.cx.resolver.invocation_parent(expn_id);
                    let span = invoc.span_mut();
                    *span = span.with_parent(Some(parent_def));
                }
            }
        }

        (fragment, invocations)
    }

    fn error_recursion_limit_reached(&mut self) -> ErrorGuaranteed {
        let expn_data = self.cx.current_expansion.id.expn_data();
        let suggested_limit = match self.cx.ecfg.recursion_limit {
            Limit(0) => Limit(2),
            limit => limit * 2,
        };

        let guar = self.cx.dcx().emit_err(RecursionLimitReached {
            span: expn_data.call_site,
            descr: expn_data.kind.descr(),
            suggested_limit,
            crate_name: &self.cx.ecfg.crate_name,
        });

        self.cx.trace_macros_diag();
        guar
    }

    /// A macro's expansion does not fit in this fragment kind.
    /// For example, a non-type macro in a type position.
    fn error_wrong_fragment_kind(
        &mut self,
        kind: AstFragmentKind,
        mac: &ast::MacCall,
        span: Span,
    ) -> ErrorGuaranteed {
        let guar =
            self.cx.dcx().emit_err(WrongFragmentKind { span, kind: kind.name(), name: &mac.path });
        self.cx.trace_macros_diag();
        guar
    }

    fn expand_invoc(
        &mut self,
        invoc: Invocation,
        ext: &SyntaxExtensionKind,
    ) -> ExpandResult<AstFragment, Invocation> {
        let recursion_limit = match self.cx.reduced_recursion_limit {
            Some((limit, _)) => limit,
            None => self.cx.ecfg.recursion_limit,
        };

        if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
            let guar = match self.cx.reduced_recursion_limit {
                Some((_, guar)) => guar,
                None => self.error_recursion_limit_reached(),
            };

            // Reduce the recursion limit by half each time it triggers.
            self.cx.reduced_recursion_limit = Some((recursion_limit / 2, guar));

            return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span(), guar));
        }

        let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
        ExpandResult::Ready(match invoc.kind {
            InvocationKind::Bang { mac, span } => match ext {
                SyntaxExtensionKind::Bang(expander) => {
                    match expander.expand(self.cx, span, mac.args.tokens.clone()) {
                        Ok(tok_result) => {
                            self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
                        }
                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
                    }
                }
                SyntaxExtensionKind::LegacyBang(expander) => {
                    let tok_result = match expander.expand(self.cx, span, mac.args.tokens.clone()) {
                        ExpandResult::Ready(tok_result) => tok_result,
                        ExpandResult::Retry(_) => {
                            // retry the original
                            return ExpandResult::Retry(Invocation {
                                kind: InvocationKind::Bang { mac, span },
                                ..invoc
                            });
                        }
                    };
                    let result = if let Some(result) = fragment_kind.make_from(tok_result) {
                        result
                    } else {
                        let guar = self.error_wrong_fragment_kind(fragment_kind, &mac, span);
                        fragment_kind.dummy(span, guar)
                    };
                    result
                }
                _ => unreachable!(),
            },
            InvocationKind::Attr { attr, pos, mut item, derives } => match ext {
                SyntaxExtensionKind::Attr(expander) => {
                    self.gate_proc_macro_input(&item);
                    self.gate_proc_macro_attr_item(span, &item);
                    let tokens = match &item {
                        // FIXME: Collect tokens and use them instead of generating
                        // fake ones. These are unstable, so it needs to be
                        // fixed prior to stabilization
                        // Fake tokens when we are invoking an inner attribute, and
                        // we are invoking it on an out-of-line module or crate.
                        Annotatable::Crate(krate) => {
                            rustc_parse::fake_token_stream_for_crate(&self.cx.sess.psess, krate)
                        }
                        Annotatable::Item(item_inner)
                            if matches!(attr.style, AttrStyle::Inner)
                                && matches!(
                                    item_inner.kind,
                                    ItemKind::Mod(
                                        _,
                                        ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _),
                                    )
                                ) =>
                        {
                            rustc_parse::fake_token_stream_for_item(&self.cx.sess.psess, item_inner)
                        }
                        _ => item.to_tokens(),
                    };
                    let attr_item = attr.unwrap_normal_item();
                    if let AttrArgs::Eq(..) = attr_item.args {
                        self.cx.dcx().emit_err(UnsupportedKeyValue { span });
                    }
                    let inner_tokens = attr_item.args.inner_tokens();
                    match expander.expand(self.cx, span, inner_tokens, tokens) {
                        Ok(tok_result) => self.parse_ast_fragment(
                            tok_result,
                            fragment_kind,
                            &attr_item.path,
                            span,
                        ),
                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
                    }
                }
                SyntaxExtensionKind::LegacyAttr(expander) => {
                    match validate_attr::parse_meta(&self.cx.sess.psess, &attr) {
                        Ok(meta) => {
                            let items = match expander.expand(self.cx, span, &meta, item, false) {
                                ExpandResult::Ready(items) => items,
                                ExpandResult::Retry(item) => {
                                    // Reassemble the original invocation for retrying.
                                    return ExpandResult::Retry(Invocation {
                                        kind: InvocationKind::Attr { attr, pos, item, derives },
                                        ..invoc
                                    });
                                }
                            };
                            if matches!(
                                fragment_kind,
                                AstFragmentKind::Expr | AstFragmentKind::MethodReceiverExpr
                            ) && items.is_empty()
                            {
                                let guar = self.cx.dcx().emit_err(RemoveExprNotSupported { span });
                                fragment_kind.dummy(span, guar)
                            } else {
                                fragment_kind.expect_from_annotatables(items)
                            }
                        }
                        Err(err) => {
                            let guar = err.emit();
                            fragment_kind.dummy(span, guar)
                        }
                    }
                }
                SyntaxExtensionKind::NonMacroAttr => {
                    self.cx.expanded_inert_attrs.mark(&attr);
                    item.visit_attrs(|attrs| attrs.insert(pos, attr));
                    fragment_kind.expect_from_annotatables(iter::once(item))
                }
                _ => unreachable!(),
            },
            InvocationKind::Derive { path, item, is_const } => match ext {
                SyntaxExtensionKind::Derive(expander)
                | SyntaxExtensionKind::LegacyDerive(expander) => {
                    if let SyntaxExtensionKind::Derive(..) = ext {
                        self.gate_proc_macro_input(&item);
                    }
                    // The `MetaItem` representing the trait to derive can't
                    // have an unsafe around it (as of now).
                    let meta = ast::MetaItem {
                        unsafety: ast::Safety::Default,
                        kind: MetaItemKind::Word,
                        span,
                        path,
                    };
                    let items = match expander.expand(self.cx, span, &meta, item, is_const) {
                        ExpandResult::Ready(items) => items,
                        ExpandResult::Retry(item) => {
                            // Reassemble the original invocation for retrying.
                            return ExpandResult::Retry(Invocation {
                                kind: InvocationKind::Derive { path: meta.path, item, is_const },
                                ..invoc
                            });
                        }
                    };
                    fragment_kind.expect_from_annotatables(items)
                }
                _ => unreachable!(),
            },
            InvocationKind::GlobDelegation { item } => {
                let AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() };
                let suffixes = match ext {
                    SyntaxExtensionKind::GlobDelegation(expander) => match expander.expand(self.cx)
                    {
                        ExpandResult::Ready(suffixes) => suffixes,
                        ExpandResult::Retry(()) => {
                            // Reassemble the original invocation for retrying.
                            return ExpandResult::Retry(Invocation {
                                kind: InvocationKind::GlobDelegation { item },
                                ..invoc
                            });
                        }
                    },
                    SyntaxExtensionKind::LegacyBang(..) => {
                        let msg = "expanded a dummy glob delegation";
                        let guar = self.cx.dcx().span_delayed_bug(span, msg);
                        return ExpandResult::Ready(fragment_kind.dummy(span, guar));
                    }
                    _ => unreachable!(),
                };

                type Node = AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>;
                let single_delegations = build_single_delegations::<Node>(
                    self.cx, deleg, &item, &suffixes, item.span, true,
                );
                fragment_kind.expect_from_annotatables(
                    single_delegations.map(|item| Annotatable::AssocItem(P(item), AssocCtxt::Impl)),
                )
            }
        })
    }

    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
    fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
        let kind = match item {
            Annotatable::Item(_)
            | Annotatable::AssocItem(..)
            | Annotatable::ForeignItem(_)
            | Annotatable::Crate(..) => return,
            Annotatable::Stmt(stmt) => {
                // Attributes are stable on item statements,
                // but unstable on all other kinds of statements
                if stmt.is_item() {
                    return;
                }
                "statements"
            }
            Annotatable::Expr(_) => "expressions",
            Annotatable::Arm(..)
            | Annotatable::ExprField(..)
            | Annotatable::PatField(..)
            | Annotatable::GenericParam(..)
            | Annotatable::Param(..)
            | Annotatable::FieldDef(..)
            | Annotatable::Variant(..) => panic!("unexpected annotatable"),
        };
        if self.cx.ecfg.features.proc_macro_hygiene {
            return;
        }
        feature_err(
            &self.cx.sess,
            sym::proc_macro_hygiene,
            span,
            format!("custom attributes cannot be applied to {kind}"),
        )
        .emit();
    }

    fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
        struct GateProcMacroInput<'a> {
            sess: &'a Session,
        }

        impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
            fn visit_item(&mut self, item: &'ast ast::Item) {
                match &item.kind {
                    ItemKind::Mod(_, mod_kind)
                        if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
                    {
                        feature_err(
                            self.sess,
                            sym::proc_macro_hygiene,
                            item.span,
                            fluent_generated::expand_non_inline_modules_in_proc_macro_input_are_unstable,
                        )
                        .emit();
                    }
                    _ => {}
                }

                visit::walk_item(self, item);
            }
        }

        if !self.cx.ecfg.features.proc_macro_hygiene {
            annotatable.visit_with(&mut GateProcMacroInput { sess: &self.cx.sess });
        }
    }

    fn parse_ast_fragment(
        &mut self,
        toks: TokenStream,
        kind: AstFragmentKind,
        path: &ast::Path,
        span: Span,
    ) -> AstFragment {
        let mut parser = self.cx.new_parser_from_tts(toks);
        match parse_ast_fragment(&mut parser, kind) {
            Ok(fragment) => {
                ensure_complete_parse(&parser, path, kind.name(), span);
                fragment
            }
            Err(mut err) => {
                if err.span.is_dummy() {
                    err.span(span);
                }
                annotate_err_with_kind(&mut err, kind, span);
                let guar = err.emit();
                self.cx.trace_macros_diag();
                kind.dummy(span, guar)
            }
        }
    }
}

pub fn parse_ast_fragment<'a>(
    this: &mut Parser<'a>,
    kind: AstFragmentKind,
) -> PResult<'a, AstFragment> {
    Ok(match kind {
        AstFragmentKind::Items => {
            let mut items = SmallVec::new();
            while let Some(item) = this.parse_item(ForceCollect::No)? {
                items.push(item);
            }
            AstFragment::Items(items)
        }
        AstFragmentKind::TraitItems => {
            let mut items = SmallVec::new();
            while let Some(item) = this.parse_trait_item(ForceCollect::No)? {
                items.extend(item);
            }
            AstFragment::TraitItems(items)
        }
        AstFragmentKind::ImplItems => {
            let mut items = SmallVec::new();
            while let Some(item) = this.parse_impl_item(ForceCollect::No)? {
                items.extend(item);
            }
            AstFragment::ImplItems(items)
        }
        AstFragmentKind::ForeignItems => {
            let mut items = SmallVec::new();
            while let Some(item) = this.parse_foreign_item(ForceCollect::No)? {
                items.extend(item);
            }
            AstFragment::ForeignItems(items)
        }
        AstFragmentKind::Stmts => {
            let mut stmts = SmallVec::new();
            // Won't make progress on a `}`.
            while this.token != token::Eof && this.token != token::CloseDelim(Delimiter::Brace) {
                if let Some(stmt) = this.parse_full_stmt(AttemptLocalParseRecovery::Yes)? {
                    stmts.push(stmt);
                }
            }
            AstFragment::Stmts(stmts)
        }
        AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
        AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(this.parse_expr()?),
        AstFragmentKind::OptExpr => {
            if this.token != token::Eof {
                AstFragment::OptExpr(Some(this.parse_expr()?))
            } else {
                AstFragment::OptExpr(None)
            }
        }
        AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
        AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_alt(
            None,
            RecoverComma::No,
            RecoverColon::Yes,
            CommaRecoveryMode::LikelyTuple,
        )?),
        AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?),
        AstFragmentKind::Arms
        | AstFragmentKind::ExprFields
        | AstFragmentKind::PatFields
        | AstFragmentKind::GenericParams
        | AstFragmentKind::Params
        | AstFragmentKind::FieldDefs
        | AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
    })
}

pub(crate) fn ensure_complete_parse<'a>(
    parser: &Parser<'a>,
    macro_path: &ast::Path,
    kind_name: &str,
    span: Span,
) {
    if parser.token != token::Eof {
        let token = pprust::token_to_string(&parser.token);
        // Avoid emitting backtrace info twice.
        let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root());

        let semi_span = parser.psess.source_map().next_point(span);
        let add_semicolon = match &parser.psess.source_map().span_to_snippet(semi_span) {
            Ok(snippet) if &snippet[..] != ";" && kind_name == "expression" => {
                Some(span.shrink_to_hi())
            }
            _ => None,
        };

        let expands_to_match_arm = kind_name == "pattern" && parser.token == token::FatArrow;

        parser.dcx().emit_err(IncompleteParse {
            span: def_site_span,
            token,
            label_span: span,
            macro_path,
            kind_name,
            expands_to_match_arm,
            add_semicolon,
        });
    }
}

/// Wraps a call to `walk_*` / `walk_flat_map_*`
/// for an AST node that supports attributes
/// (see the `Annotatable` enum)
/// This method assigns a `NodeId`, and sets that `NodeId`
/// as our current 'lint node id'. If a macro call is found
/// inside this AST node, we will use this AST node's `NodeId`
/// to emit lints associated with that macro (allowing
/// `#[allow]` / `#[deny]` to be applied close to
/// the macro invocation).
///
/// Do *not* call this for a macro AST node
/// (e.g. `ExprKind::MacCall`) - we cannot emit lints
/// at these AST nodes, since they are removed and
/// replaced with the result of macro expansion.
///
/// All other `NodeId`s are assigned by `visit_id`.
/// * `self` is the 'self' parameter for the current method,
/// * `id` is a mutable reference to the `NodeId` field
///    of the current AST node.
/// * `closure` is a closure that executes the
///   `walk_*` / `walk_flat_map_*` method
///   for the current AST node.
macro_rules! assign_id {
    ($self:ident, $id:expr, $closure:expr) => {{
        let old_id = $self.cx.current_expansion.lint_node_id;
        if $self.monotonic {
            debug_assert_eq!(*$id, ast::DUMMY_NODE_ID);
            let new_id = $self.cx.resolver.next_node_id();
            *$id = new_id;
            $self.cx.current_expansion.lint_node_id = new_id;
        }
        let ret = ($closure)();
        $self.cx.current_expansion.lint_node_id = old_id;
        ret
    }};
}

enum AddSemicolon {
    Yes,
    No,
}

/// A trait implemented for all `AstFragment` nodes and providing all pieces
/// of functionality used by `InvocationCollector`.
trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
    type OutputTy = SmallVec<[Self; 1]>;
    type AttrsTy: Deref<Target = [ast::Attribute]> = ast::AttrVec;
    type ItemKind = ItemKind;
    const KIND: AstFragmentKind;
    fn to_annotatable(self) -> Annotatable;
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy;
    fn descr() -> &'static str {
        unreachable!()
    }
    fn walk_flat_map<V: MutVisitor>(self, _visitor: &mut V) -> Self::OutputTy {
        unreachable!()
    }
    fn walk<V: MutVisitor>(&mut self, _visitor: &mut V) {
        unreachable!()
    }
    fn is_mac_call(&self) -> bool {
        false
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        unreachable!()
    }
    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
        None
    }
    fn delegation_item_kind(_deleg: Box<ast::Delegation>) -> Self::ItemKind {
        unreachable!()
    }
    fn from_item(_item: ast::Item<Self::ItemKind>) -> Self {
        unreachable!()
    }
    fn flatten_outputs(_outputs: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
        unreachable!()
    }
    fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {}
    fn post_flat_map_node_collect_bang(_output: &mut Self::OutputTy, _add_semicolon: AddSemicolon) {
    }
    fn wrap_flat_map_node_walk_flat_map(
        node: Self,
        collector: &mut InvocationCollector<'_, '_>,
        walk_flat_map: impl FnOnce(Self, &mut InvocationCollector<'_, '_>) -> Self::OutputTy,
    ) -> Result<Self::OutputTy, Self> {
        Ok(walk_flat_map(node, collector))
    }
    fn expand_cfg_false(
        &mut self,
        collector: &mut InvocationCollector<'_, '_>,
        _pos: usize,
        span: Span,
    ) {
        collector.cx.dcx().emit_err(RemoveNodeNotSupported { span, descr: Self::descr() });
    }

    /// All of the names (items) declared by this node.
    /// This is an approximation and should only be used for diagnostics.
    fn declared_names(&self) -> Vec<Ident> {
        vec![]
    }
}

impl InvocationCollectorNode for P<ast::Item> {
    const KIND: AstFragmentKind = AstFragmentKind::Items;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Item(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_items()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_item(visitor, self)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.kind, ItemKind::MacCall(..))
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        let node = self.into_inner();
        match node.kind {
            ItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
            _ => unreachable!(),
        }
    }
    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
        match &self.kind {
            ItemKind::DelegationMac(deleg) => Some((deleg, self)),
            _ => None,
        }
    }
    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
        ItemKind::Delegation(deleg)
    }
    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
        P(item)
    }
    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
        items.flatten().collect()
    }
    fn wrap_flat_map_node_walk_flat_map(
        mut node: Self,
        collector: &mut InvocationCollector<'_, '_>,
        walk_flat_map: impl FnOnce(Self, &mut InvocationCollector<'_, '_>) -> Self::OutputTy,
    ) -> Result<Self::OutputTy, Self> {
        if !matches!(node.kind, ItemKind::Mod(..)) {
            return Ok(walk_flat_map(node, collector));
        }

        // Work around borrow checker not seeing through `P`'s deref.
        let (ident, span, mut attrs) = (node.ident, node.span, mem::take(&mut node.attrs));
        let ItemKind::Mod(_, mod_kind) = &mut node.kind else { unreachable!() };

        let ecx = &mut collector.cx;
        let (file_path, dir_path, dir_ownership) = match mod_kind {
            ModKind::Loaded(_, inline, _) => {
                // Inline `mod foo { ... }`, but we still need to push directories.
                let (dir_path, dir_ownership) = mod_dir_path(
                    ecx.sess,
                    ident,
                    &attrs,
                    &ecx.current_expansion.module,
                    ecx.current_expansion.dir_ownership,
                    *inline,
                );
                // If the module was parsed from an external file, recover its path.
                // This lets `parse_external_mod` catch cycles if it's self-referential.
                let file_path = match inline {
                    Inline::Yes => None,
                    Inline::No => mod_file_path_from_attr(ecx.sess, &attrs, &dir_path),
                };
                node.attrs = attrs;
                (file_path, dir_path, dir_ownership)
            }
            ModKind::Unloaded => {
                // We have an outline `mod foo;` so we need to parse the file.
                let old_attrs_len = attrs.len();
                let ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership } =
                    parse_external_mod(
                        ecx.sess,
                        ident,
                        span,
                        &ecx.current_expansion.module,
                        ecx.current_expansion.dir_ownership,
                        &mut attrs,
                    );

                if let Some(lint_store) = ecx.lint_store {
                    lint_store.pre_expansion_lint(
                        ecx.sess,
                        ecx.ecfg.features,
                        ecx.resolver.registered_tools(),
                        ecx.current_expansion.lint_node_id,
                        &attrs,
                        &items,
                        ident.name,
                    );
                }

                *mod_kind = ModKind::Loaded(items, Inline::No, spans);
                node.attrs = attrs;
                if node.attrs.len() > old_attrs_len {
                    // If we loaded an out-of-line module and added some inner attributes,
                    // then we need to re-configure it and re-collect attributes for
                    // resolution and expansion.
                    return Err(node);
                }
                (Some(file_path), dir_path, dir_ownership)
            }
        };

        // Set the module info before we flat map.
        let mut module = ecx.current_expansion.module.with_dir_path(dir_path);
        module.mod_path.push(ident);
        if let Some(file_path) = file_path {
            module.file_path_stack.push(file_path);
        }

        let orig_module = mem::replace(&mut ecx.current_expansion.module, Rc::new(module));
        let orig_dir_ownership =
            mem::replace(&mut ecx.current_expansion.dir_ownership, dir_ownership);

        let res = Ok(walk_flat_map(node, collector));

        collector.cx.current_expansion.dir_ownership = orig_dir_ownership;
        collector.cx.current_expansion.module = orig_module;
        res
    }
    fn declared_names(&self) -> Vec<Ident> {
        if let ItemKind::Use(ut) = &self.kind {
            fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
                match &ut.kind {
                    ast::UseTreeKind::Glob => {}
                    ast::UseTreeKind::Simple(_) => idents.push(ut.ident()),
                    ast::UseTreeKind::Nested { items, .. } => {
                        for (ut, _) in items {
                            collect_use_tree_leaves(ut, idents);
                        }
                    }
                }
            }

            let mut idents = Vec::new();
            collect_use_tree_leaves(ut, &mut idents);
            return idents;
        }

        vec![self.ident]
    }
}

struct TraitItemTag;
impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag> {
    type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
    type ItemKind = AssocItemKind;
    const KIND: AstFragmentKind = AstFragmentKind::TraitItems;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::AssocItem(self.wrapped, AssocCtxt::Trait)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_trait_items()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_item(visitor, self.wrapped)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        let item = self.wrapped.into_inner();
        match item.kind {
            AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
            _ => unreachable!(),
        }
    }
    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
        match &self.wrapped.kind {
            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
            _ => None,
        }
    }
    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
        AssocItemKind::Delegation(deleg)
    }
    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
        AstNodeWrapper::new(P(item), TraitItemTag)
    }
    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
        items.flatten().collect()
    }
}

struct ImplItemTag;
impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag> {
    type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
    type ItemKind = AssocItemKind;
    const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_impl_items()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_item(visitor, self.wrapped)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        let item = self.wrapped.into_inner();
        match item.kind {
            AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
            _ => unreachable!(),
        }
    }
    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
        match &self.wrapped.kind {
            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
            _ => None,
        }
    }
    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
        AssocItemKind::Delegation(deleg)
    }
    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
        AstNodeWrapper::new(P(item), ImplItemTag)
    }
    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
        items.flatten().collect()
    }
}

impl InvocationCollectorNode for P<ast::ForeignItem> {
    const KIND: AstFragmentKind = AstFragmentKind::ForeignItems;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::ForeignItem(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_foreign_items()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_item(visitor, self)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.kind, ForeignItemKind::MacCall(..))
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        let node = self.into_inner();
        match node.kind {
            ForeignItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
            _ => unreachable!(),
        }
    }
}

impl InvocationCollectorNode for ast::Variant {
    const KIND: AstFragmentKind = AstFragmentKind::Variants;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Variant(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_variants()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_variant(visitor, self)
    }
}

impl InvocationCollectorNode for ast::FieldDef {
    const KIND: AstFragmentKind = AstFragmentKind::FieldDefs;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::FieldDef(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_field_defs()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_field_def(visitor, self)
    }
}

impl InvocationCollectorNode for ast::PatField {
    const KIND: AstFragmentKind = AstFragmentKind::PatFields;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::PatField(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_pat_fields()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_pat_field(visitor, self)
    }
}

impl InvocationCollectorNode for ast::ExprField {
    const KIND: AstFragmentKind = AstFragmentKind::ExprFields;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::ExprField(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_expr_fields()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_expr_field(visitor, self)
    }
}

impl InvocationCollectorNode for ast::Param {
    const KIND: AstFragmentKind = AstFragmentKind::Params;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Param(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_params()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_param(visitor, self)
    }
}

impl InvocationCollectorNode for ast::GenericParam {
    const KIND: AstFragmentKind = AstFragmentKind::GenericParams;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::GenericParam(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_generic_params()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_generic_param(visitor, self)
    }
}

impl InvocationCollectorNode for ast::Arm {
    const KIND: AstFragmentKind = AstFragmentKind::Arms;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Arm(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_arms()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_arm(visitor, self)
    }
}

impl InvocationCollectorNode for ast::Stmt {
    type AttrsTy = ast::AttrVec;
    const KIND: AstFragmentKind = AstFragmentKind::Stmts;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Stmt(P(self))
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_stmts()
    }
    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
        walk_flat_map_stmt(visitor, self)
    }
    fn is_mac_call(&self) -> bool {
        match &self.kind {
            StmtKind::MacCall(..) => true,
            StmtKind::Item(item) => matches!(item.kind, ItemKind::MacCall(..)),
            StmtKind::Semi(expr) => matches!(expr.kind, ExprKind::MacCall(..)),
            StmtKind::Expr(..) => unreachable!(),
            StmtKind::Let(..) | StmtKind::Empty => false,
        }
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        // We pull macro invocations (both attributes and fn-like macro calls) out of their
        // `StmtKind`s and treat them as statement macro invocations, not as items or expressions.
        let (add_semicolon, mac, attrs) = match self.kind {
            StmtKind::MacCall(mac) => {
                let ast::MacCallStmt { mac, style, attrs, .. } = mac.into_inner();
                (style == MacStmtStyle::Semicolon, mac, attrs)
            }
            StmtKind::Item(item) => match item.into_inner() {
                ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => {
                    (mac.args.need_semicolon(), mac, attrs)
                }
                _ => unreachable!(),
            },
            StmtKind::Semi(expr) => match expr.into_inner() {
                ast::Expr { kind: ExprKind::MacCall(mac), attrs, .. } => {
                    (mac.args.need_semicolon(), mac, attrs)
                }
                _ => unreachable!(),
            },
            _ => unreachable!(),
        };
        (mac, attrs, if add_semicolon { AddSemicolon::Yes } else { AddSemicolon::No })
    }
    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
        match &self.kind {
            StmtKind::Item(item) => match &item.kind {
                ItemKind::DelegationMac(deleg) => Some((deleg, item)),
                _ => None,
            },
            _ => None,
        }
    }
    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
        ItemKind::Delegation(deleg)
    }
    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
        ast::Stmt { id: ast::DUMMY_NODE_ID, span: item.span, kind: StmtKind::Item(P(item)) }
    }
    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
        items.flatten().collect()
    }
    fn post_flat_map_node_collect_bang(stmts: &mut Self::OutputTy, add_semicolon: AddSemicolon) {
        // If this is a macro invocation with a semicolon, then apply that
        // semicolon to the final statement produced by expansion.
        if matches!(add_semicolon, AddSemicolon::Yes) {
            if let Some(stmt) = stmts.pop() {
                stmts.push(stmt.add_trailing_semicolon());
            }
        }
    }
}

impl InvocationCollectorNode for ast::Crate {
    type OutputTy = ast::Crate;
    const KIND: AstFragmentKind = AstFragmentKind::Crate;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Crate(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_crate()
    }
    fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
        walk_crate(visitor, self)
    }
    fn expand_cfg_false(
        &mut self,
        collector: &mut InvocationCollector<'_, '_>,
        pos: usize,
        _span: Span,
    ) {
        // Attributes above `cfg(FALSE)` are left in place, because we may want to configure
        // some global crate properties even on fully unconfigured crates.
        self.attrs.truncate(pos);
        // Standard prelude imports are left in the crate for backward compatibility.
        self.items.truncate(collector.cx.num_standard_library_imports);
    }
}

impl InvocationCollectorNode for P<ast::Ty> {
    type OutputTy = P<ast::Ty>;
    const KIND: AstFragmentKind = AstFragmentKind::Ty;
    fn to_annotatable(self) -> Annotatable {
        unreachable!()
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_ty()
    }
    fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
        walk_ty(visitor, self)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.kind, ast::TyKind::MacCall(..))
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        let node = self.into_inner();
        match node.kind {
            TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
            _ => unreachable!(),
        }
    }
}

impl InvocationCollectorNode for P<ast::Pat> {
    type OutputTy = P<ast::Pat>;
    const KIND: AstFragmentKind = AstFragmentKind::Pat;
    fn to_annotatable(self) -> Annotatable {
        unreachable!()
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_pat()
    }
    fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
        walk_pat(visitor, self)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.kind, PatKind::MacCall(..))
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        let node = self.into_inner();
        match node.kind {
            PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
            _ => unreachable!(),
        }
    }
}

impl InvocationCollectorNode for P<ast::Expr> {
    type OutputTy = P<ast::Expr>;
    type AttrsTy = ast::AttrVec;
    const KIND: AstFragmentKind = AstFragmentKind::Expr;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Expr(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_expr()
    }
    fn descr() -> &'static str {
        "an expression"
    }
    fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
        walk_expr(visitor, self)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.kind, ExprKind::MacCall(..))
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        let node = self.into_inner();
        match node.kind {
            ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
            _ => unreachable!(),
        }
    }
}

struct OptExprTag;
impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
    type OutputTy = Option<P<ast::Expr>>;
    type AttrsTy = ast::AttrVec;
    const KIND: AstFragmentKind = AstFragmentKind::OptExpr;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Expr(self.wrapped)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_opt_expr()
    }
    fn walk_flat_map<V: MutVisitor>(mut self, visitor: &mut V) -> Self::OutputTy {
        walk_expr(visitor, &mut self.wrapped);
        Some(self.wrapped)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        let node = self.wrapped.into_inner();
        match node.kind {
            ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
            _ => unreachable!(),
        }
    }
    fn pre_flat_map_node_collect_attr(cfg: &StripUnconfigured<'_>, attr: &ast::Attribute) {
        cfg.maybe_emit_expr_attr_err(attr);
    }
}

/// This struct is a hack to workaround unstable of `stmt_expr_attributes`.
/// It can be removed once that feature is stabilized.
struct MethodReceiverTag;
impl DummyAstNode for MethodReceiverTag {
    fn dummy() -> MethodReceiverTag {
        MethodReceiverTag
    }
}
impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> {
    type OutputTy = Self;
    type AttrsTy = ast::AttrVec;
    const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
    fn descr() -> &'static str {
        "an expression"
    }
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Expr(self.wrapped)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag)
    }
    fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
        walk_expr(visitor, &mut self.wrapped)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
    }
    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
        let node = self.wrapped.into_inner();
        match node.kind {
            ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
            _ => unreachable!(),
        }
    }
}

fn build_single_delegations<'a, Node: InvocationCollectorNode>(
    ecx: &ExtCtxt<'_>,
    deleg: &'a ast::DelegationMac,
    item: &'a ast::Item<Node::ItemKind>,
    suffixes: &'a [(Ident, Option<Ident>)],
    item_span: Span,
    from_glob: bool,
) -> impl Iterator<Item = ast::Item<Node::ItemKind>> + 'a {
    if suffixes.is_empty() {
        // Report an error for now, to avoid keeping stem for resolution and
        // stability checks.
        let kind = String::from(if from_glob { "glob" } else { "list" });
        ecx.dcx().emit_err(EmptyDelegationMac { span: item.span, kind });
    }

    suffixes.iter().map(move |&(ident, rename)| {
        let mut path = deleg.prefix.clone();
        path.segments.push(ast::PathSegment { ident, id: ast::DUMMY_NODE_ID, args: None });

        ast::Item {
            attrs: item.attrs.clone(),
            id: ast::DUMMY_NODE_ID,
            span: if from_glob { item_span } else { ident.span },
            vis: item.vis.clone(),
            ident: rename.unwrap_or(ident),
            kind: Node::delegation_item_kind(Box::new(ast::Delegation {
                id: ast::DUMMY_NODE_ID,
                qself: deleg.qself.clone(),
                path,
                rename,
                body: deleg.body.clone(),
                from_glob,
            })),
            tokens: None,
        }
    })
}

struct InvocationCollector<'a, 'b> {
    cx: &'a mut ExtCtxt<'b>,
    invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
    monotonic: bool,
}

impl<'a, 'b> InvocationCollector<'a, 'b> {
    fn cfg(&self) -> StripUnconfigured<'_> {
        StripUnconfigured {
            sess: self.cx.sess,
            features: Some(self.cx.ecfg.features),
            config_tokens: false,
            lint_node_id: self.cx.current_expansion.lint_node_id,
        }
    }

    fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
        let expn_id = LocalExpnId::fresh_empty();
        if matches!(kind, InvocationKind::GlobDelegation { .. }) {
            // In resolver we need to know which invocation ids are delegations early,
            // before their `ExpnData` is filled.
            self.cx.resolver.register_glob_delegation(expn_id);
        }
        let vis = kind.placeholder_visibility();
        self.invocations.push((
            Invocation {
                kind,
                fragment_kind,
                expansion_data: ExpansionData {
                    id: expn_id,
                    depth: self.cx.current_expansion.depth + 1,
                    ..self.cx.current_expansion.clone()
                },
            },
            None,
        ));
        placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
    }

    fn collect_bang(&mut self, mac: P<ast::MacCall>, kind: AstFragmentKind) -> AstFragment {
        // cache the macro call span so that it can be
        // easily adjusted for incremental compilation
        let span = mac.span();
        self.collect(kind, InvocationKind::Bang { mac, span })
    }

    fn collect_attr(
        &mut self,
        (attr, pos, derives): (ast::Attribute, usize, Vec<ast::Path>),
        item: Annotatable,
        kind: AstFragmentKind,
    ) -> AstFragment {
        self.collect(kind, InvocationKind::Attr { attr, pos, item, derives })
    }

    fn collect_glob_delegation(
        &mut self,
        item: P<ast::AssocItem>,
        kind: AstFragmentKind,
    ) -> AstFragment {
        self.collect(kind, InvocationKind::GlobDelegation { item })
    }

    /// If `item` is an attribute invocation, remove the attribute and return it together with
    /// its position and derives following it. We have to collect the derives in order to resolve
    /// legacy derive helpers (helpers written before derives that introduce them).
    fn take_first_attr(
        &self,
        item: &mut impl HasAttrs,
    ) -> Option<(ast::Attribute, usize, Vec<ast::Path>)> {
        let mut attr = None;

        let mut cfg_pos = None;
        let mut attr_pos = None;
        for (pos, attr) in item.attrs().iter().enumerate() {
            if !attr.is_doc_comment() && !self.cx.expanded_inert_attrs.is_marked(attr) {
                let name = attr.ident().map(|ident| ident.name);
                if name == Some(sym::cfg) || name == Some(sym::cfg_attr) {
                    cfg_pos = Some(pos); // a cfg attr found, no need to search anymore
                    break;
                } else if attr_pos.is_none()
                    && !name.is_some_and(rustc_feature::is_builtin_attr_name)
                {
                    attr_pos = Some(pos); // a non-cfg attr found, still may find a cfg attr
                }
            }
        }

        item.visit_attrs(|attrs| {
            attr = Some(match (cfg_pos, attr_pos) {
                (Some(pos), _) => (attrs.remove(pos), pos, Vec::new()),
                (_, Some(pos)) => {
                    let attr = attrs.remove(pos);
                    let following_derives = attrs[pos..]
                        .iter()
                        .filter(|a| a.has_name(sym::derive))
                        .flat_map(|a| a.meta_item_list().unwrap_or_default())
                        .filter_map(|meta_item_inner| match meta_item_inner {
                            MetaItemInner::MetaItem(ast::MetaItem {
                                kind: MetaItemKind::Word,
                                path,
                                ..
                            }) => Some(path),
                            _ => None,
                        })
                        .collect();

                    (attr, pos, following_derives)
                }
                _ => return,
            });
        });

        attr
    }

    // Detect use of feature-gated or invalid attributes on macro invocations
    // since they will not be detected after macro expansion.
    fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
        let features = self.cx.ecfg.features;
        let mut attrs = attrs.iter().peekable();
        let mut span: Option<Span> = None;
        while let Some(attr) = attrs.next() {
            rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
            validate_attr::check_attr(&self.cx.sess.psess, attr);

            let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
            span = Some(current_span);

            if attrs.peek().is_some_and(|next_attr| next_attr.doc_str().is_some()) {
                continue;
            }

            if attr.is_doc_comment() {
                self.cx.sess.psess.buffer_lint(
                    UNUSED_DOC_COMMENTS,
                    current_span,
                    self.cx.current_expansion.lint_node_id,
                    BuiltinLintDiag::UnusedDocComment(attr.span),
                );
            } else if rustc_attr::is_builtin_attr(attr) {
                let attr_name = attr.ident().unwrap().name;
                // `#[cfg]` and `#[cfg_attr]` are special - they are
                // eagerly evaluated.
                if attr_name != sym::cfg && attr_name != sym::cfg_attr {
                    self.cx.sess.psess.buffer_lint(
                        UNUSED_ATTRIBUTES,
                        attr.span,
                        self.cx.current_expansion.lint_node_id,
                        BuiltinLintDiag::UnusedBuiltinAttribute {
                            attr_name,
                            macro_name: pprust::path_to_string(&call.path),
                            invoc_span: call.path.span,
                        },
                    );
                }
            }
        }
    }

    fn expand_cfg_true(
        &mut self,
        node: &mut impl HasAttrs,
        attr: ast::Attribute,
        pos: usize,
    ) -> (bool, Option<ast::MetaItem>) {
        let (res, meta_item) = self.cfg().cfg_true(&attr);
        if res {
            // FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion,
            // and some tools like rustdoc and clippy rely on that. Find a way to remove them
            // while keeping the tools working.
            self.cx.expanded_inert_attrs.mark(&attr);
            node.visit_attrs(|attrs| attrs.insert(pos, attr));
        }

        (res, meta_item)
    }

    fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: &ast::Attribute, pos: usize) {
        node.visit_attrs(|attrs| {
            // Repeated `insert` calls is inefficient, but the number of
            // insertions is almost always 0 or 1 in practice.
            for cfg in self.cfg().expand_cfg_attr(attr, false).into_iter().rev() {
                attrs.insert(pos, cfg)
            }
        });
    }

    fn flat_map_node<Node: InvocationCollectorNode<OutputTy: Default>>(
        &mut self,
        mut node: Node,
    ) -> Node::OutputTy {
        loop {
            return match self.take_first_attr(&mut node) {
                Some((attr, pos, derives)) => match attr.name_or_empty() {
                    sym::cfg => {
                        let (res, meta_item) = self.expand_cfg_true(&mut node, attr, pos);
                        if res {
                            continue;
                        }

                        if let Some(meta_item) = meta_item {
                            for name in node.declared_names() {
                                self.cx.resolver.append_stripped_cfg_item(
                                    self.cx.current_expansion.lint_node_id,
                                    name,
                                    meta_item.clone(),
                                )
                            }
                        }
                        Default::default()
                    }
                    sym::cfg_attr => {
                        self.expand_cfg_attr(&mut node, &attr, pos);
                        continue;
                    }
                    _ => {
                        Node::pre_flat_map_node_collect_attr(&self.cfg(), &attr);
                        self.collect_attr((attr, pos, derives), node.to_annotatable(), Node::KIND)
                            .make_ast::<Node>()
                    }
                },
                None if node.is_mac_call() => {
                    let (mac, attrs, add_semicolon) = node.take_mac_call();
                    self.check_attributes(&attrs, &mac);
                    let mut res = self.collect_bang(mac, Node::KIND).make_ast::<Node>();
                    Node::post_flat_map_node_collect_bang(&mut res, add_semicolon);
                    res
                }
                None if let Some((deleg, item)) = node.delegation() => {
                    let Some(suffixes) = &deleg.suffixes else {
                        let traitless_qself =
                            matches!(&deleg.qself, Some(qself) if qself.position == 0);
                        let item = match node.to_annotatable() {
                            Annotatable::AssocItem(item, AssocCtxt::Impl) => item,
                            ann @ (Annotatable::Item(_)
                            | Annotatable::AssocItem(..)
                            | Annotatable::Stmt(_)) => {
                                let span = ann.span();
                                self.cx.dcx().emit_err(GlobDelegationOutsideImpls { span });
                                return Default::default();
                            }
                            _ => unreachable!(),
                        };
                        if traitless_qself {
                            let span = item.span;
                            self.cx.dcx().emit_err(GlobDelegationTraitlessQpath { span });
                            return Default::default();
                        }
                        return self.collect_glob_delegation(item, Node::KIND).make_ast::<Node>();
                    };

                    let single_delegations = build_single_delegations::<Node>(
                        self.cx, deleg, item, suffixes, item.span, false,
                    );
                    Node::flatten_outputs(single_delegations.map(|item| {
                        let mut item = Node::from_item(item);
                        assign_id!(self, item.node_id_mut(), || item.walk_flat_map(self))
                    }))
                }
                None => {
                    match Node::wrap_flat_map_node_walk_flat_map(node, self, |mut node, this| {
                        assign_id!(this, node.node_id_mut(), || node.walk_flat_map(this))
                    }) {
                        Ok(output) => output,
                        Err(returned_node) => {
                            node = returned_node;
                            continue;
                        }
                    }
                }
            };
        }
    }

    fn visit_node<Node: InvocationCollectorNode<OutputTy = Node> + DummyAstNode>(
        &mut self,
        node: &mut Node,
    ) {
        loop {
            return match self.take_first_attr(node) {
                Some((attr, pos, derives)) => match attr.name_or_empty() {
                    sym::cfg => {
                        let span = attr.span;
                        if self.expand_cfg_true(node, attr, pos).0 {
                            continue;
                        }

                        node.expand_cfg_false(self, pos, span);
                        continue;
                    }
                    sym::cfg_attr => {
                        self.expand_cfg_attr(node, &attr, pos);
                        continue;
                    }
                    _ => visit_clobber(node, |node| {
                        self.collect_attr((attr, pos, derives), node.to_annotatable(), Node::KIND)
                            .make_ast::<Node>()
                    }),
                },
                None if node.is_mac_call() => {
                    visit_clobber(node, |node| {
                        // Do not clobber unless it's actually a macro (uncommon case).
                        let (mac, attrs, _) = node.take_mac_call();
                        self.check_attributes(&attrs, &mac);
                        self.collect_bang(mac, Node::KIND).make_ast::<Node>()
                    })
                }
                None if node.delegation().is_some() => unreachable!(),
                None => {
                    assign_id!(self, node.node_id_mut(), || node.walk(self))
                }
            };
        }
    }
}

impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
    fn flat_map_item(&mut self, node: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
        self.flat_map_node(node)
    }

    fn flat_map_assoc_item(
        &mut self,
        node: P<ast::AssocItem>,
        ctxt: AssocCtxt,
    ) -> SmallVec<[P<ast::AssocItem>; 1]> {
        match ctxt {
            AssocCtxt::Trait => self.flat_map_node(AstNodeWrapper::new(node, TraitItemTag)),
            AssocCtxt::Impl => self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag)),
        }
    }

    fn flat_map_foreign_item(
        &mut self,
        node: P<ast::ForeignItem>,
    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
        self.flat_map_node(node)
    }

    fn flat_map_variant(&mut self, node: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
        self.flat_map_node(node)
    }

    fn flat_map_field_def(&mut self, node: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
        self.flat_map_node(node)
    }

    fn flat_map_pat_field(&mut self, node: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
        self.flat_map_node(node)
    }

    fn flat_map_expr_field(&mut self, node: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
        self.flat_map_node(node)
    }

    fn flat_map_param(&mut self, node: ast::Param) -> SmallVec<[ast::Param; 1]> {
        self.flat_map_node(node)
    }

    fn flat_map_generic_param(
        &mut self,
        node: ast::GenericParam,
    ) -> SmallVec<[ast::GenericParam; 1]> {
        self.flat_map_node(node)
    }

    fn flat_map_arm(&mut self, node: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
        self.flat_map_node(node)
    }

    fn flat_map_stmt(&mut self, node: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
        // FIXME: invocations in semicolon-less expressions positions are expanded as expressions,
        // changing that requires some compatibility measures.
        if node.is_expr() {
            // The only way that we can end up with a `MacCall` expression statement,
            // (as opposed to a `StmtKind::MacCall`) is if we have a macro as the
            // trailing expression in a block (e.g. `fn foo() { my_macro!() }`).
            // Record this information, so that we can report a more specific
            // `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` lint if needed.
            // See #78991 for an investigation of treating macros in this position
            // as statements, rather than expressions, during parsing.
            return match &node.kind {
                StmtKind::Expr(expr)
                    if matches!(**expr, ast::Expr { kind: ExprKind::MacCall(..), .. }) =>
                {
                    self.cx.current_expansion.is_trailing_mac = true;
                    // Don't use `assign_id` for this statement - it may get removed
                    // entirely due to a `#[cfg]` on the contained expression
                    let res = walk_flat_map_stmt(self, node);
                    self.cx.current_expansion.is_trailing_mac = false;
                    res
                }
                _ => walk_flat_map_stmt(self, node),
            };
        }

        self.flat_map_node(node)
    }

    fn visit_crate(&mut self, node: &mut ast::Crate) {
        self.visit_node(node)
    }

    fn visit_ty(&mut self, node: &mut P<ast::Ty>) {
        self.visit_node(node)
    }

    fn visit_pat(&mut self, node: &mut P<ast::Pat>) {
        self.visit_node(node)
    }

    fn visit_expr(&mut self, node: &mut P<ast::Expr>) {
        // FIXME: Feature gating is performed inconsistently between `Expr` and `OptExpr`.
        if let Some(attr) = node.attrs.first() {
            self.cfg().maybe_emit_expr_attr_err(attr);
        }
        self.visit_node(node)
    }

    fn visit_method_receiver_expr(&mut self, node: &mut P<ast::Expr>) {
        visit_clobber(node, |node| {
            let mut wrapper = AstNodeWrapper::new(node, MethodReceiverTag);
            self.visit_node(&mut wrapper);
            wrapper.wrapped
        })
    }

    fn filter_map_expr(&mut self, node: P<ast::Expr>) -> Option<P<ast::Expr>> {
        self.flat_map_node(AstNodeWrapper::new(node, OptExprTag))
    }

    fn visit_block(&mut self, node: &mut P<ast::Block>) {
        let orig_dir_ownership = mem::replace(
            &mut self.cx.current_expansion.dir_ownership,
            DirOwnership::UnownedViaBlock,
        );
        walk_block(self, node);
        self.cx.current_expansion.dir_ownership = orig_dir_ownership;
    }

    fn visit_id(&mut self, id: &mut NodeId) {
        // We may have already assigned a `NodeId`
        // by calling `assign_id`
        if self.monotonic && *id == ast::DUMMY_NODE_ID {
            *id = self.cx.resolver.next_node_id();
        }
    }
}

pub struct ExpansionConfig<'feat> {
    pub crate_name: String,
    pub features: &'feat Features,
    pub recursion_limit: Limit,
    pub trace_mac: bool,
    /// If false, strip `#[test]` nodes
    pub should_test: bool,
    /// If true, use verbose debugging for `proc_macro::Span`
    pub span_debug: bool,
    /// If true, show backtraces for proc-macro panics
    pub proc_macro_backtrace: bool,
}

impl ExpansionConfig<'_> {
    pub fn default(crate_name: String, features: &Features) -> ExpansionConfig<'_> {
        ExpansionConfig {
            crate_name,
            features,
            recursion_limit: Limit::new(1024),
            trace_mac: false,
            should_test: false,
            span_debug: false,
            proc_macro_backtrace: false,
        }
    }
}
