use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use std::{iter, mem, slice};

use rustc_ast::mut_visit::*;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};
use rustc_ast::{
    self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, DUMMY_NODE_ID,
    ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner,
    MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token,
};
use rustc_ast_pretty::pprust;
use rustc_attr_parsing::{AttributeParser, Early, EvalConfigResult, ShouldEmit, validate_attr};
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::PResult;
use rustc_feature::Features;
use rustc_hir::Target;
use rustc_hir::def::MacroKinds;
use rustc_hir::limit::Limit;
use rustc_parse::parser::{
    AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
    token_descr,
};
use rustc_session::Session;
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
use rustc_session::parse::feature_err;
use rustc_span::hygiene::SyntaxContext;
use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, Symbol, sym};
use smallvec::SmallVec;

use crate::base::*;
use crate::config::{StripUnconfigured, attr_into_trace};
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};
use crate::stats::*;

macro_rules! ast_fragments {
    (
        $($Kind:ident($AstTy:ty) {
            $kind_name:expr;
            $(one
                fn $mut_visit_ast:ident;
                fn $visit_ast:ident;
                fn $ast_to_string:path;
            )?
            $(many
                fn $flat_map_ast_elt:ident;
                fn $visit_ast_elt:ident($($args:tt)*);
                fn $ast_to_string_elt:path;
            )?
            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<Box<ast::Expr>>),
            MethodReceiverExpr(Box<ast::Expr>),
            $($Kind($AstTy),)*
        }

        /// "Discriminant" of an AST fragment.
        #[derive(Copy, Clone, Debug, 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(self, result: Box<dyn MacResult + '_>) -> 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<Box<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) -> Box<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(&mut self, vis: &mut impl MutVisitor) {
                match self {
                    AstFragment::OptExpr(opt_expr) => {
                        if let Some(expr) = opt_expr.take() {
                            *opt_expr = vis.filter_map_expr(expr)
                        }
                    }
                    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()
            }

            pub(crate) fn to_string(&self) -> String {
                match self {
                    AstFragment::OptExpr(Some(expr)) => pprust::expr_to_string(expr),
                    AstFragment::OptExpr(None) => unreachable!(),
                    AstFragment::MethodReceiverExpr(expr) => pprust::expr_to_string(expr),
                    $($(AstFragment::$Kind(ast) => $ast_to_string(ast),)?)*
                    $($(
                        AstFragment::$Kind(ast) => {
                            // The closure unwraps a `P` if present, or does nothing otherwise.
                            elems_to_string(&*ast, |ast| $ast_to_string_elt(&*ast))
                        }
                    )?)*
                }
            }
        }

        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(Box<ast::Expr>) {
        "expression";
        one fn visit_expr; fn visit_expr; fn pprust::expr_to_string;
        fn make_expr;
    }
    Pat(Box<ast::Pat>) {
        "pattern";
        one fn visit_pat; fn visit_pat; fn pprust::pat_to_string;
        fn make_pat;
    }
    Ty(Box<ast::Ty>) {
        "type";
        one fn visit_ty; fn visit_ty; fn pprust::ty_to_string;
        fn make_ty;
    }
    Stmts(SmallVec<[ast::Stmt; 1]>) {
        "statement";
        many fn flat_map_stmt; fn visit_stmt(); fn pprust::stmt_to_string;
        fn make_stmts;
    }
    Items(SmallVec<[Box<ast::Item>; 1]>) {
        "item";
        many fn flat_map_item; fn visit_item(); fn pprust::item_to_string;
        fn make_items;
    }
    TraitItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
        "trait item";
        many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Trait);
            fn pprust::assoc_item_to_string;
        fn make_trait_items;
    }
    ImplItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
        "impl item";
        many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: false });
            fn pprust::assoc_item_to_string;
        fn make_impl_items;
    }
    TraitImplItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
        "impl item";
        many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: true });
            fn pprust::assoc_item_to_string;
        fn make_trait_impl_items;
    }
    ForeignItems(SmallVec<[Box<ast::ForeignItem>; 1]>) {
        "foreign item";
        many fn flat_map_foreign_item; fn visit_foreign_item(); fn pprust::foreign_item_to_string;
        fn make_foreign_items;
    }
    Arms(SmallVec<[ast::Arm; 1]>) {
        "match arm";
        many fn flat_map_arm; fn visit_arm(); fn unreachable_to_string;
        fn make_arms;
    }
    ExprFields(SmallVec<[ast::ExprField; 1]>) {
        "field expression";
        many fn flat_map_expr_field; fn visit_expr_field(); fn unreachable_to_string;
        fn make_expr_fields;
    }
    PatFields(SmallVec<[ast::PatField; 1]>) {
        "field pattern";
        many fn flat_map_pat_field; fn visit_pat_field(); fn unreachable_to_string;
        fn make_pat_fields;
    }
    GenericParams(SmallVec<[ast::GenericParam; 1]>) {
        "generic parameter";
        many fn flat_map_generic_param; fn visit_generic_param(); fn unreachable_to_string;
        fn make_generic_params;
    }
    Params(SmallVec<[ast::Param; 1]>) {
        "function parameter";
        many fn flat_map_param; fn visit_param(); fn unreachable_to_string;
        fn make_params;
    }
    FieldDefs(SmallVec<[ast::FieldDef; 1]>) {
        "field";
        many fn flat_map_field_def; fn visit_field_def(); fn unreachable_to_string;
        fn make_field_defs;
    }
    Variants(SmallVec<[ast::Variant; 1]>) {
        "variant"; many fn flat_map_variant; fn visit_variant(); fn unreachable_to_string;
        fn make_variants;
    }
    WherePredicates(SmallVec<[ast::WherePredicate; 1]>) {
        "where predicate";
        many fn flat_map_where_predicate; fn visit_where_predicate(); fn unreachable_to_string;
        fn make_where_predicates;
    }
    Crate(ast::Crate) {
        "crate";
        one fn visit_crate; fn visit_crate; fn unreachable_to_string;
        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::TraitImplItems
            | AstFragmentKind::ForeignItems
            | AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true },
            AstFragmentKind::Arms
            | AstFragmentKind::ExprFields
            | AstFragmentKind::PatFields
            | AstFragmentKind::GenericParams
            | AstFragmentKind::Params
            | AstFragmentKind::FieldDefs
            | AstFragmentKind::Variants
            | AstFragmentKind::WherePredicates => SupportsMacroExpansion::No,
        }
    }

    pub(crate) fn expect_from_annotatables(
        self,
        items: impl IntoIterator<Item = Annotatable>,
    ) -> 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::WherePredicates => AstFragment::WherePredicates(
                items.map(Annotatable::expect_where_predicate).collect(),
            ),
            AstFragmentKind::Items => {
                AstFragment::Items(items.map(Annotatable::expect_item).collect())
            }
            AstFragmentKind::ImplItems => {
                AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect())
            }
            AstFragmentKind::TraitImplItems => {
                AstFragment::TraitImplItems(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: Box<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: Box<ast::AssocItem>,
        /// Whether this is a trait impl or an inherent impl
        of_trait: bool,
    },
}

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::with_dummy_span(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.
                                    // Note that this can result in duplicate diagnostics.
                                    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<Arc<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.macro_error_and_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.macro_error_and_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 macro_stats = self.cx.sess.opts.unstable_opts.macro_stats;

        let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
        ExpandResult::Ready(match invoc.kind {
            InvocationKind::Bang { mac, span } => {
                if let SyntaxExtensionKind::Bang(expander) = ext {
                    match expander.expand(self.cx, span, mac.args.tokens.clone()) {
                        Ok(tok_result) => {
                            let fragment =
                                self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span);
                            if macro_stats {
                                update_bang_macro_stats(
                                    self.cx,
                                    fragment_kind,
                                    span,
                                    mac,
                                    &fragment,
                                );
                            }
                            fragment
                        }
                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
                    }
                } else if let Some(expander) = ext.as_legacy_bang() {
                    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
                            });
                        }
                    };
                    if let Some(fragment) = fragment_kind.make_from(tok_result) {
                        if macro_stats {
                            update_bang_macro_stats(self.cx, fragment_kind, span, mac, &fragment);
                        }
                        fragment
                    } else {
                        let guar = self.error_wrong_fragment_kind(fragment_kind, &mac, span);
                        fragment_kind.dummy(span, guar)
                    }
                } else {
                    unreachable!();
                }
            }
            InvocationKind::Attr { attr, pos, mut item, derives } => {
                if let Some(expander) = ext.as_attr() {
                    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.get_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) => {
                            let fragment = self.parse_ast_fragment(
                                tok_result,
                                fragment_kind,
                                &attr_item.path,
                                span,
                            );
                            if macro_stats {
                                update_attr_macro_stats(
                                    self.cx,
                                    fragment_kind,
                                    span,
                                    &attr_item.path,
                                    &attr,
                                    item,
                                    &fragment,
                                );
                            }
                            fragment
                        }
                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
                    }
                } else if let SyntaxExtensionKind::LegacyAttr(expander) = ext {
                    match validate_attr::parse_meta(&self.cx.sess.psess, &attr) {
                        Ok(meta) => {
                            let item_clone = macro_stats.then(|| item.clone());
                            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 {
                                let fragment = fragment_kind.expect_from_annotatables(items);
                                if macro_stats {
                                    update_attr_macro_stats(
                                        self.cx,
                                        fragment_kind,
                                        span,
                                        &meta.path,
                                        &attr,
                                        item_clone.unwrap(),
                                        &fragment,
                                    );
                                }
                                fragment
                            }
                        }
                        Err(err) => {
                            let _guar = err.emit();
                            fragment_kind.expect_from_annotatables(iter::once(item))
                        }
                    }
                } else if let SyntaxExtensionKind::NonMacroAttr = ext {
                    // `-Zmacro-stats` ignores these because they don't do any real expansion.
                    self.cx.expanded_inert_attrs.mark(&attr);
                    item.visit_attrs(|attrs| attrs.insert(pos, attr));
                    fragment_kind.expect_from_annotatables(iter::once(item))
                } else {
                    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
                            });
                        }
                    };
                    let fragment = fragment_kind.expect_from_annotatables(items);
                    if macro_stats {
                        update_derive_macro_stats(
                            self.cx,
                            fragment_kind,
                            span,
                            &meta.path,
                            &fragment,
                        );
                    }
                    fragment
                }
                SyntaxExtensionKind::MacroRules(expander)
                    if expander.kinds().contains(MacroKinds::DERIVE) =>
                {
                    if is_const {
                        let guar = self
                            .cx
                            .dcx()
                            .span_err(span, "macro `derive` does not support const derives");
                        return ExpandResult::Ready(fragment_kind.dummy(span, guar));
                    }
                    let body = item.to_tokens();
                    match expander.expand_derive(self.cx, span, &body) {
                        Ok(tok_result) => {
                            let fragment =
                                self.parse_ast_fragment(tok_result, fragment_kind, &path, span);
                            if macro_stats {
                                update_derive_macro_stats(
                                    self.cx,
                                    fragment_kind,
                                    span,
                                    &path,
                                    &fragment,
                                );
                            }
                            fragment
                        }
                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
                    }
                }
                _ => unreachable!(),
            },
            InvocationKind::GlobDelegation { item, of_trait } => {
                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, of_trait },
                                ..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<Box<ast::AssocItem>, ImplItemTag>;
                let single_delegations = build_single_delegations::<Node>(
                    self.cx, deleg, &item, &suffixes, item.span, true,
                );
                // `-Zmacro-stats` ignores these because they don't seem important.
                fragment_kind.expect_from_annotatables(single_delegations.map(|item| {
                    Annotatable::AssocItem(Box::new(item), AssocCtxt::Impl { of_trait })
                }))
            }
        })
    }

    #[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(..)
            | Annotatable::WherePredicate(..) => 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.macro_error_and_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::TraitImplItems => {
            let mut items = SmallVec::new();
            while let Some(item) = this.parse_impl_item(ForceCollect::No)? {
                items.extend(item);
            }
            AstFragment::TraitImplItems(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::CloseBrace {
                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_guard(
            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
        | AstFragmentKind::WherePredicates => 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 descr = token_descr(&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,
            descr,
            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 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(self, _collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        unreachable!()
    }
    fn walk(&mut self, _collector: &mut InvocationCollector<'_, '_>) {
        unreachable!()
    }
    fn is_mac_call(&self) -> bool {
        false
    }
    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, 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 identifiers (items) declared by this node.
    /// This is an approximation and should only be used for diagnostics.
    fn declared_idents(&self) -> Vec<Ident> {
        vec![]
    }
}

impl InvocationCollectorNode for Box<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(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_item(collector, self)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.kind, ItemKind::MacCall(..))
    }
    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
        match self.kind {
            ItemKind::MacCall(mac) => (mac, self.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 {
        Box::new(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 (span, mut attrs) = (node.span, mem::take(&mut node.attrs));
        let ItemKind::Mod(_, ident, ref mut mod_kind) = 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,
                    had_parse_error,
                } = 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 { had_parse_error }, 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_idents(&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);
            idents
        } else {
            self.kind.ident().into_iter().collect()
        }
    }
}

struct TraitItemTag;
impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, TraitItemTag> {
    type OutputTy = SmallVec<[Box<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(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Trait)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
    }
    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
        let item = self.wrapped;
        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(Box::new(item), TraitItemTag)
    }
    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
        items.flatten().collect()
    }
}

struct ImplItemTag;
impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, ImplItemTag> {
    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;
    type ItemKind = AssocItemKind;
    const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: false })
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_impl_items()
    }
    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Impl { of_trait: false })
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
    }
    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
        let item = self.wrapped;
        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(Box::new(item), ImplItemTag)
    }
    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
        items.flatten().collect()
    }
}

struct TraitImplItemTag;
impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, TraitImplItemTag> {
    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;
    type ItemKind = AssocItemKind;
    const KIND: AstFragmentKind = AstFragmentKind::TraitImplItems;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: true })
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_trait_impl_items()
    }
    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Impl { of_trait: true })
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
    }
    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
        let item = self.wrapped;
        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(Box::new(item), TraitImplItemTag)
    }
    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
        items.flatten().collect()
    }
}

impl InvocationCollectorNode for Box<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(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_foreign_item(collector, self)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.kind, ForeignItemKind::MacCall(..))
    }
    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
        match self.kind {
            ForeignItemKind::MacCall(mac) => (mac, self.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(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_variant(collector, self)
    }
}

impl InvocationCollectorNode for ast::WherePredicate {
    const KIND: AstFragmentKind = AstFragmentKind::WherePredicates;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::WherePredicate(self)
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_where_predicates()
    }
    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_where_predicate(collector, 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(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_field_def(collector, 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(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_pat_field(collector, 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(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_expr_field(collector, 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(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_param(collector, 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(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_generic_param(collector, 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(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_arm(collector, self)
    }
}

impl InvocationCollectorNode for ast::Stmt {
    const KIND: AstFragmentKind = AstFragmentKind::Stmts;
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Stmt(Box::new(self))
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        fragment.make_stmts()
    }
    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_flat_map_stmt(collector, 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) -> (Box<ast::MacCall>, ast::AttrVec, 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;
                (style == MacStmtStyle::Semicolon, mac, attrs)
            }
            StmtKind::Item(item) => match *item {
                ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => {
                    (mac.args.need_semicolon(), mac, attrs)
                }
                _ => unreachable!(),
            },
            StmtKind::Semi(expr) => match *expr {
                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(Box::new(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(&mut self, collector: &mut InvocationCollector<'_, '_>) {
        walk_crate(collector, 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 ast::Ty {
    type OutputTy = Box<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(&mut self, collector: &mut InvocationCollector<'_, '_>) {
        // Save the pre-expanded name of this `ImplTrait`, so that later when defining
        // an APIT we use a name that doesn't have any placeholder fragments in it.
        if let ast::TyKind::ImplTrait(..) = self.kind {
            // HACK: pprust breaks strings with newlines when the type
            // gets too long. We don't want these to show up in compiler
            // output or built artifacts, so replace them here...
            // Perhaps we should instead format APITs more robustly.
            let name = Symbol::intern(&pprust::ty_to_string(self).replace('\n', " "));
            collector.cx.resolver.insert_impl_trait_name(self.id, name);
        }
        walk_ty(collector, self)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.kind, ast::TyKind::MacCall(..))
    }
    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
        match self.kind {
            TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
            _ => unreachable!(),
        }
    }
}

impl InvocationCollectorNode for ast::Pat {
    type OutputTy = Box<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(&mut self, collector: &mut InvocationCollector<'_, '_>) {
        walk_pat(collector, self)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.kind, PatKind::MacCall(..))
    }
    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
        match self.kind {
            PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
            _ => unreachable!(),
        }
    }
}

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

struct OptExprTag;
impl InvocationCollectorNode for AstNodeWrapper<Box<ast::Expr>, OptExprTag> {
    type OutputTy = Option<Box<ast::Expr>>;
    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(mut self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
        walk_expr(collector, &mut self.wrapped);
        Some(self.wrapped)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
    }
    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
        let node = self.wrapped;
        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 InvocationCollectorNode for AstNodeWrapper<ast::Expr, MethodReceiverTag> {
    type OutputTy = AstNodeWrapper<Box<ast::Expr>, MethodReceiverTag>;
    const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
    fn descr() -> &'static str {
        "an expression"
    }
    fn to_annotatable(self) -> Annotatable {
        Annotatable::Expr(Box::new(self.wrapped))
    }
    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
        AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag)
    }
    fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {
        walk_expr(collector, &mut self.wrapped)
    }
    fn is_mac_call(&self) -> bool {
        matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
    }
    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
        let node = self.wrapped;
        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(),
            kind: Node::delegation_item_kind(Box::new(ast::Delegation {
                id: ast::DUMMY_NODE_ID,
                qself: deleg.qself.clone(),
                path,
                ident: rename.unwrap_or(ident),
                rename,
                body: deleg.body.clone(),
                from_glob,
            })),
            tokens: None,
        }
    })
}

/// Required for `visit_node` obtained an owned `Node` from `&mut Node`.
trait DummyAstNode {
    fn dummy() -> Self;
}

impl DummyAstNode for ast::Crate {
    fn dummy() -> Self {
        ast::Crate {
            attrs: Default::default(),
            items: Default::default(),
            spans: Default::default(),
            id: DUMMY_NODE_ID,
            is_placeholder: Default::default(),
        }
    }
}

impl DummyAstNode for ast::Ty {
    fn dummy() -> Self {
        ast::Ty {
            id: DUMMY_NODE_ID,
            kind: TyKind::Dummy,
            span: Default::default(),
            tokens: Default::default(),
        }
    }
}

impl DummyAstNode for ast::Pat {
    fn dummy() -> Self {
        ast::Pat {
            id: DUMMY_NODE_ID,
            kind: PatKind::Wild,
            span: Default::default(),
            tokens: Default::default(),
        }
    }
}

impl DummyAstNode for ast::Expr {
    fn dummy() -> Self {
        ast::Expr::dummy()
    }
}

impl DummyAstNode for AstNodeWrapper<ast::Expr, MethodReceiverTag> {
    fn dummy() -> Self {
        AstNodeWrapper::new(ast::Expr::dummy(), MethodReceiverTag)
    }
}

struct InvocationCollector<'a, 'b> {
    cx: &'a mut ExtCtxt<'b>,
    invocations: Vec<(Invocation, Option<Arc<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: Box<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: Box<ast::AssocItem>,
        of_trait: bool,
        kind: AstFragmentKind,
    ) -> AstFragment {
        self.collect(kind, InvocationKind::GlobDelegation { item, of_trait })
    }

    /// 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,
                self.cx.current_expansion.lint_node_id,
            );
            AttributeParser::parse_limited_all(
                self.cx.sess,
                slice::from_ref(attr),
                None,
                Target::MacroCall,
                call.span(),
                self.cx.current_expansion.lint_node_id,
                Some(self.cx.ecfg.features),
                ShouldEmit::ErrorsAndLints,
            );

            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,
                    crate::errors::MacroCallUnusedDocComment { span: attr.span },
                );
            } else if rustc_attr_parsing::is_builtin_attr(attr)
                && !AttributeParser::<Early>::is_parsed_attribute(&attr.path())
            {
                let attr_name = attr.ident().unwrap().name;
                // `#[cfg]` and `#[cfg_attr]` are special - they are
                // eagerly evaluated.
                if attr_name != sym::cfg_trace && attr_name != sym::cfg_attr_trace {
                    self.cx.sess.psess.buffer_lint(
                        UNUSED_ATTRIBUTES,
                        attr.span,
                        self.cx.current_expansion.lint_node_id,
                        crate::errors::UnusedBuiltinAttribute {
                            attr_name,
                            macro_name: pprust::path_to_string(&call.path),
                            invoc_span: call.path.span,
                            attr_span: attr.span,
                        },
                    );
                }
            }
        }
    }

    fn expand_cfg_true(
        &mut self,
        node: &mut (impl HasAttrs + HasNodeId),
        attr: ast::Attribute,
        pos: usize,
    ) -> EvalConfigResult {
        let res = self.cfg().cfg_true(&attr, node.node_id(), ShouldEmit::ErrorsAndLints);
        if res.as_bool() {
            // A trace attribute left in AST in place of the original `cfg` attribute.
            // It can later be used by lints or other diagnostics.
            let trace_attr = attr_into_trace(attr, sym::cfg_trace);
            node.visit_attrs(|attrs| attrs.insert(pos, trace_attr));
        }

        res
    }

    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() {
                    Some(sym::cfg) => {
                        let res = self.expand_cfg_true(&mut node, attr, pos);
                        match res {
                            EvalConfigResult::True => continue,
                            EvalConfigResult::False { reason, reason_span } => {
                                for ident in node.declared_idents() {
                                    self.cx.resolver.append_stripped_cfg_item(
                                        self.cx.current_expansion.lint_node_id,
                                        ident,
                                        reason.clone(),
                                        reason_span,
                                    )
                                }
                            }
                        }

                        Default::default()
                    }
                    Some(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, of_trait) = match node.to_annotatable() {
                            Annotatable::AssocItem(item, AssocCtxt::Impl { of_trait }) => {
                                (item, of_trait)
                            }
                            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, of_trait, 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: Into<Node>> + DummyAstNode>(
        &mut self,
        node: &mut Node,
    ) {
        loop {
            return match self.take_first_attr(node) {
                Some((attr, pos, derives)) => match attr.name() {
                    Some(sym::cfg) => {
                        let span = attr.span;
                        if self.expand_cfg_true(node, attr, pos).as_bool() {
                            continue;
                        }

                        node.expand_cfg_false(self, pos, span);
                        continue;
                    }
                    Some(sym::cfg_attr) => {
                        self.expand_cfg_attr(node, &attr, pos);
                        continue;
                    }
                    _ => {
                        let n = mem::replace(node, Node::dummy());
                        *node = self
                            .collect_attr((attr, pos, derives), n.to_annotatable(), Node::KIND)
                            .make_ast::<Node>()
                            .into()
                    }
                },
                None if node.is_mac_call() => {
                    let n = mem::replace(node, Node::dummy());
                    let (mac, attrs, _) = n.take_mac_call();
                    self.check_attributes(&attrs, &mac);

                    *node = self.collect_bang(mac, Node::KIND).make_ast::<Node>().into()
                }
                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: Box<ast::Item>) -> SmallVec<[Box<ast::Item>; 1]> {
        self.flat_map_node(node)
    }

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

    fn flat_map_foreign_item(
        &mut self,
        node: Box<ast::ForeignItem>,
    ) -> SmallVec<[Box<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_where_predicate(
        &mut self,
        node: ast::WherePredicate,
    ) -> SmallVec<[ast::WherePredicate; 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 ast::Ty) {
        self.visit_node(node)
    }

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

    fn visit_expr(&mut self, node: &mut 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);
        }
        ensure_sufficient_stack(|| self.visit_node(node))
    }

    fn visit_method_receiver_expr(&mut self, node: &mut ast::Expr) {
        self.visit_node(AstNodeWrapper::from_mut(node, MethodReceiverTag))
    }

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

    fn visit_block(&mut self, node: &mut 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: Symbol,
    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: Symbol, features: &Features) -> ExpansionConfig<'_> {
        ExpansionConfig {
            crate_name,
            features,
            // FIXME should this limit be configurable?
            recursion_limit: Limit::new(1024),
            trace_mac: false,
            should_test: false,
            span_debug: false,
            proc_macro_backtrace: false,
        }
    }
}
