rustc_expand/
expand.rs

1use std::path::PathBuf;
2use std::rc::Rc;
3use std::sync::Arc;
4use std::{iter, mem, slice};
5
6use rustc_ast::mut_visit::*;
7use rustc_ast::tokenstream::TokenStream;
8use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};
9use rustc_ast::{
10    self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, DUMMY_NODE_ID,
11    ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner,
12    MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token,
13};
14use rustc_ast_pretty::pprust;
15use rustc_attr_parsing::{AttributeParser, Early, EvalConfigResult, ShouldEmit, validate_attr};
16use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
17use rustc_data_structures::stack::ensure_sufficient_stack;
18use rustc_errors::PResult;
19use rustc_feature::Features;
20use rustc_hir::Target;
21use rustc_hir::def::MacroKinds;
22use rustc_hir::limit::Limit;
23use rustc_parse::parser::{
24    AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
25    token_descr,
26};
27use rustc_session::Session;
28use rustc_session::lint::BuiltinLintDiag;
29use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
30use rustc_session::parse::feature_err;
31use rustc_span::hygiene::SyntaxContext;
32use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, Symbol, sym};
33use smallvec::SmallVec;
34
35use crate::base::*;
36use crate::config::{StripUnconfigured, attr_into_trace};
37use crate::errors::{
38    EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,
39    RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,
40    WrongFragmentKind,
41};
42use crate::fluent_generated;
43use crate::mbe::diagnostics::annotate_err_with_kind;
44use crate::module::{
45    DirOwnership, ParsedExternalMod, mod_dir_path, mod_file_path_from_attr, parse_external_mod,
46};
47use crate::placeholders::{PlaceholderExpander, placeholder};
48use crate::stats::*;
49
50macro_rules! ast_fragments {
51    (
52        $($Kind:ident($AstTy:ty) {
53            $kind_name:expr;
54            $(one
55                fn $mut_visit_ast:ident;
56                fn $visit_ast:ident;
57                fn $ast_to_string:path;
58            )?
59            $(many
60                fn $flat_map_ast_elt:ident;
61                fn $visit_ast_elt:ident($($args:tt)*);
62                fn $ast_to_string_elt:path;
63            )?
64            fn $make_ast:ident;
65        })*
66    ) => {
67        /// A fragment of AST that can be produced by a single macro expansion.
68        /// Can also serve as an input and intermediate result for macro expansion operations.
69        pub enum AstFragment {
70            OptExpr(Option<Box<ast::Expr>>),
71            MethodReceiverExpr(Box<ast::Expr>),
72            $($Kind($AstTy),)*
73        }
74
75        /// "Discriminant" of an AST fragment.
76        #[derive(Copy, Clone, Debug, PartialEq, Eq)]
77        pub enum AstFragmentKind {
78            OptExpr,
79            MethodReceiverExpr,
80            $($Kind,)*
81        }
82
83        impl AstFragmentKind {
84            pub fn name(self) -> &'static str {
85                match self {
86                    AstFragmentKind::OptExpr => "expression",
87                    AstFragmentKind::MethodReceiverExpr => "expression",
88                    $(AstFragmentKind::$Kind => $kind_name,)*
89                }
90            }
91
92            fn make_from(self, result: Box<dyn MacResult + '_>) -> Option<AstFragment> {
93                match self {
94                    AstFragmentKind::OptExpr =>
95                        result.make_expr().map(Some).map(AstFragment::OptExpr),
96                    AstFragmentKind::MethodReceiverExpr =>
97                        result.make_expr().map(AstFragment::MethodReceiverExpr),
98                    $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
99                }
100            }
101        }
102
103        impl AstFragment {
104            fn add_placeholders(&mut self, placeholders: &[NodeId]) {
105                if placeholders.is_empty() {
106                    return;
107                }
108                match self {
109                    $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| {
110                        ${ignore($flat_map_ast_elt)}
111                        placeholder(AstFragmentKind::$Kind, *id, None).$make_ast()
112                    })),)?)*
113                    _ => panic!("unexpected AST fragment kind")
114                }
115            }
116
117            pub(crate) fn make_opt_expr(self) -> Option<Box<ast::Expr>> {
118                match self {
119                    AstFragment::OptExpr(expr) => expr,
120                    _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
121                }
122            }
123
124            pub(crate) fn make_method_receiver_expr(self) -> Box<ast::Expr> {
125                match self {
126                    AstFragment::MethodReceiverExpr(expr) => expr,
127                    _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
128                }
129            }
130
131            $(pub fn $make_ast(self) -> $AstTy {
132                match self {
133                    AstFragment::$Kind(ast) => ast,
134                    _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
135                }
136            })*
137
138            fn make_ast<T: InvocationCollectorNode>(self) -> T::OutputTy {
139                T::fragment_to_output(self)
140            }
141
142            pub(crate) fn mut_visit_with(&mut self, vis: &mut impl MutVisitor) {
143                match self {
144                    AstFragment::OptExpr(opt_expr) => {
145                        if let Some(expr) = opt_expr.take() {
146                            *opt_expr = vis.filter_map_expr(expr)
147                        }
148                    }
149                    AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
150                    $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
151                    $($(AstFragment::$Kind(ast) =>
152                        ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast, $($args)*)),)?)*
153                }
154            }
155
156            pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) -> V::Result {
157                match self {
158                    AstFragment::OptExpr(Some(expr)) => try_visit!(visitor.visit_expr(expr)),
159                    AstFragment::OptExpr(None) => {}
160                    AstFragment::MethodReceiverExpr(expr) => try_visit!(visitor.visit_method_receiver_expr(expr)),
161                    $($(AstFragment::$Kind(ast) => try_visit!(visitor.$visit_ast(ast)),)?)*
162                    $($(AstFragment::$Kind(ast) => walk_list!(visitor, $visit_ast_elt, &ast[..], $($args)*),)?)*
163                }
164                V::Result::output()
165            }
166
167            pub(crate) fn to_string(&self) -> String {
168                match self {
169                    AstFragment::OptExpr(Some(expr)) => pprust::expr_to_string(expr),
170                    AstFragment::OptExpr(None) => unreachable!(),
171                    AstFragment::MethodReceiverExpr(expr) => pprust::expr_to_string(expr),
172                    $($(AstFragment::$Kind(ast) => $ast_to_string(ast),)?)*
173                    $($(
174                        AstFragment::$Kind(ast) => {
175                            // The closure unwraps a `P` if present, or does nothing otherwise.
176                            elems_to_string(&*ast, |ast| $ast_to_string_elt(&*ast))
177                        }
178                    )?)*
179                }
180            }
181        }
182
183        impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> {
184            $(fn $make_ast(self: Box<crate::mbe::macro_rules::ParserAnyMacro<'a>>)
185                           -> Option<$AstTy> {
186                Some(self.make(AstFragmentKind::$Kind).$make_ast())
187            })*
188        }
189    }
190}
191
192ast_fragments! {
193    Expr(Box<ast::Expr>) {
194        "expression";
195        one fn visit_expr; fn visit_expr; fn pprust::expr_to_string;
196        fn make_expr;
197    }
198    Pat(Box<ast::Pat>) {
199        "pattern";
200        one fn visit_pat; fn visit_pat; fn pprust::pat_to_string;
201        fn make_pat;
202    }
203    Ty(Box<ast::Ty>) {
204        "type";
205        one fn visit_ty; fn visit_ty; fn pprust::ty_to_string;
206        fn make_ty;
207    }
208    Stmts(SmallVec<[ast::Stmt; 1]>) {
209        "statement";
210        many fn flat_map_stmt; fn visit_stmt(); fn pprust::stmt_to_string;
211        fn make_stmts;
212    }
213    Items(SmallVec<[Box<ast::Item>; 1]>) {
214        "item";
215        many fn flat_map_item; fn visit_item(); fn pprust::item_to_string;
216        fn make_items;
217    }
218    TraitItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
219        "trait item";
220        many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Trait);
221            fn pprust::assoc_item_to_string;
222        fn make_trait_items;
223    }
224    ImplItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
225        "impl item";
226        many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: false });
227            fn pprust::assoc_item_to_string;
228        fn make_impl_items;
229    }
230    TraitImplItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
231        "impl item";
232        many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: true });
233            fn pprust::assoc_item_to_string;
234        fn make_trait_impl_items;
235    }
236    ForeignItems(SmallVec<[Box<ast::ForeignItem>; 1]>) {
237        "foreign item";
238        many fn flat_map_foreign_item; fn visit_foreign_item(); fn pprust::foreign_item_to_string;
239        fn make_foreign_items;
240    }
241    Arms(SmallVec<[ast::Arm; 1]>) {
242        "match arm";
243        many fn flat_map_arm; fn visit_arm(); fn unreachable_to_string;
244        fn make_arms;
245    }
246    ExprFields(SmallVec<[ast::ExprField; 1]>) {
247        "field expression";
248        many fn flat_map_expr_field; fn visit_expr_field(); fn unreachable_to_string;
249        fn make_expr_fields;
250    }
251    PatFields(SmallVec<[ast::PatField; 1]>) {
252        "field pattern";
253        many fn flat_map_pat_field; fn visit_pat_field(); fn unreachable_to_string;
254        fn make_pat_fields;
255    }
256    GenericParams(SmallVec<[ast::GenericParam; 1]>) {
257        "generic parameter";
258        many fn flat_map_generic_param; fn visit_generic_param(); fn unreachable_to_string;
259        fn make_generic_params;
260    }
261    Params(SmallVec<[ast::Param; 1]>) {
262        "function parameter";
263        many fn flat_map_param; fn visit_param(); fn unreachable_to_string;
264        fn make_params;
265    }
266    FieldDefs(SmallVec<[ast::FieldDef; 1]>) {
267        "field";
268        many fn flat_map_field_def; fn visit_field_def(); fn unreachable_to_string;
269        fn make_field_defs;
270    }
271    Variants(SmallVec<[ast::Variant; 1]>) {
272        "variant"; many fn flat_map_variant; fn visit_variant(); fn unreachable_to_string;
273        fn make_variants;
274    }
275    WherePredicates(SmallVec<[ast::WherePredicate; 1]>) {
276        "where predicate";
277        many fn flat_map_where_predicate; fn visit_where_predicate(); fn unreachable_to_string;
278        fn make_where_predicates;
279    }
280    Crate(ast::Crate) {
281        "crate";
282        one fn visit_crate; fn visit_crate; fn unreachable_to_string;
283        fn make_crate;
284    }
285}
286
287pub enum SupportsMacroExpansion {
288    No,
289    Yes { supports_inner_attrs: bool },
290}
291
292impl AstFragmentKind {
293    pub(crate) fn dummy(self, span: Span, guar: ErrorGuaranteed) -> AstFragment {
294        self.make_from(DummyResult::any(span, guar)).expect("couldn't create a dummy AST fragment")
295    }
296
297    pub fn supports_macro_expansion(self) -> SupportsMacroExpansion {
298        match self {
299            AstFragmentKind::OptExpr
300            | AstFragmentKind::Expr
301            | AstFragmentKind::MethodReceiverExpr
302            | AstFragmentKind::Stmts
303            | AstFragmentKind::Ty
304            | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false },
305            AstFragmentKind::Items
306            | AstFragmentKind::TraitItems
307            | AstFragmentKind::ImplItems
308            | AstFragmentKind::TraitImplItems
309            | AstFragmentKind::ForeignItems
310            | AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true },
311            AstFragmentKind::Arms
312            | AstFragmentKind::ExprFields
313            | AstFragmentKind::PatFields
314            | AstFragmentKind::GenericParams
315            | AstFragmentKind::Params
316            | AstFragmentKind::FieldDefs
317            | AstFragmentKind::Variants
318            | AstFragmentKind::WherePredicates => SupportsMacroExpansion::No,
319        }
320    }
321
322    pub(crate) fn expect_from_annotatables(
323        self,
324        items: impl IntoIterator<Item = Annotatable>,
325    ) -> AstFragment {
326        let mut items = items.into_iter();
327        match self {
328            AstFragmentKind::Arms => {
329                AstFragment::Arms(items.map(Annotatable::expect_arm).collect())
330            }
331            AstFragmentKind::ExprFields => {
332                AstFragment::ExprFields(items.map(Annotatable::expect_expr_field).collect())
333            }
334            AstFragmentKind::PatFields => {
335                AstFragment::PatFields(items.map(Annotatable::expect_pat_field).collect())
336            }
337            AstFragmentKind::GenericParams => {
338                AstFragment::GenericParams(items.map(Annotatable::expect_generic_param).collect())
339            }
340            AstFragmentKind::Params => {
341                AstFragment::Params(items.map(Annotatable::expect_param).collect())
342            }
343            AstFragmentKind::FieldDefs => {
344                AstFragment::FieldDefs(items.map(Annotatable::expect_field_def).collect())
345            }
346            AstFragmentKind::Variants => {
347                AstFragment::Variants(items.map(Annotatable::expect_variant).collect())
348            }
349            AstFragmentKind::WherePredicates => AstFragment::WherePredicates(
350                items.map(Annotatable::expect_where_predicate).collect(),
351            ),
352            AstFragmentKind::Items => {
353                AstFragment::Items(items.map(Annotatable::expect_item).collect())
354            }
355            AstFragmentKind::ImplItems => {
356                AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect())
357            }
358            AstFragmentKind::TraitImplItems => {
359                AstFragment::TraitImplItems(items.map(Annotatable::expect_impl_item).collect())
360            }
361            AstFragmentKind::TraitItems => {
362                AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect())
363            }
364            AstFragmentKind::ForeignItems => {
365                AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect())
366            }
367            AstFragmentKind::Stmts => {
368                AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect())
369            }
370            AstFragmentKind::Expr => AstFragment::Expr(
371                items.next().expect("expected exactly one expression").expect_expr(),
372            ),
373            AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(
374                items.next().expect("expected exactly one expression").expect_expr(),
375            ),
376            AstFragmentKind::OptExpr => {
377                AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
378            }
379            AstFragmentKind::Crate => {
380                AstFragment::Crate(items.next().expect("expected exactly one crate").expect_crate())
381            }
382            AstFragmentKind::Pat | AstFragmentKind::Ty => {
383                panic!("patterns and types aren't annotatable")
384            }
385        }
386    }
387}
388
389pub struct Invocation {
390    pub kind: InvocationKind,
391    pub fragment_kind: AstFragmentKind,
392    pub expansion_data: ExpansionData,
393}
394
395pub enum InvocationKind {
396    Bang {
397        mac: Box<ast::MacCall>,
398        span: Span,
399    },
400    Attr {
401        attr: ast::Attribute,
402        /// Re-insertion position for inert attributes.
403        pos: usize,
404        item: Annotatable,
405        /// Required for resolving derive helper attributes.
406        derives: Vec<ast::Path>,
407    },
408    Derive {
409        path: ast::Path,
410        is_const: bool,
411        item: Annotatable,
412    },
413    GlobDelegation {
414        item: Box<ast::AssocItem>,
415        /// Whether this is a trait impl or an inherent impl
416        of_trait: bool,
417    },
418}
419
420impl InvocationKind {
421    fn placeholder_visibility(&self) -> Option<ast::Visibility> {
422        // HACK: For unnamed fields placeholders should have the same visibility as the actual
423        // fields because for tuple structs/variants resolve determines visibilities of their
424        // constructor using these field visibilities before attributes on them are expanded.
425        // The assumption is that the attribute expansion cannot change field visibilities,
426        // and it holds because only inert attributes are supported in this position.
427        match self {
428            InvocationKind::Attr { item: Annotatable::FieldDef(field), .. }
429            | InvocationKind::Derive { item: Annotatable::FieldDef(field), .. }
430                if field.ident.is_none() =>
431            {
432                Some(field.vis.clone())
433            }
434            _ => None,
435        }
436    }
437}
438
439impl Invocation {
440    pub fn span(&self) -> Span {
441        match &self.kind {
442            InvocationKind::Bang { span, .. } => *span,
443            InvocationKind::Attr { attr, .. } => attr.span,
444            InvocationKind::Derive { path, .. } => path.span,
445            InvocationKind::GlobDelegation { item, .. } => item.span,
446        }
447    }
448
449    fn span_mut(&mut self) -> &mut Span {
450        match &mut self.kind {
451            InvocationKind::Bang { span, .. } => span,
452            InvocationKind::Attr { attr, .. } => &mut attr.span,
453            InvocationKind::Derive { path, .. } => &mut path.span,
454            InvocationKind::GlobDelegation { item, .. } => &mut item.span,
455        }
456    }
457}
458
459pub struct MacroExpander<'a, 'b> {
460    pub cx: &'a mut ExtCtxt<'b>,
461    monotonic: bool, // cf. `cx.monotonic_expander()`
462}
463
464impl<'a, 'b> MacroExpander<'a, 'b> {
465    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
466        MacroExpander { cx, monotonic }
467    }
468
469    pub fn expand_crate(&mut self, krate: ast::Crate) -> ast::Crate {
470        let file_path = match self.cx.source_map().span_to_filename(krate.spans.inner_span) {
471            FileName::Real(name) => name
472                .into_local_path()
473                .expect("attempting to resolve a file path in an external file"),
474            other => PathBuf::from(other.prefer_local().to_string()),
475        };
476        let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
477        self.cx.root_path = dir_path.clone();
478        self.cx.current_expansion.module = Rc::new(ModuleData {
479            mod_path: vec![Ident::with_dummy_span(self.cx.ecfg.crate_name)],
480            file_path_stack: vec![file_path],
481            dir_path,
482        });
483        let krate = self.fully_expand_fragment(AstFragment::Crate(krate)).make_crate();
484        assert_eq!(krate.id, ast::CRATE_NODE_ID);
485        self.cx.trace_macros_diag();
486        krate
487    }
488
489    /// Recursively expand all macro invocations in this AST fragment.
490    pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
491        let orig_expansion_data = self.cx.current_expansion.clone();
492        let orig_force_mode = self.cx.force_mode;
493
494        // Collect all macro invocations and replace them with placeholders.
495        let (mut fragment_with_placeholders, mut invocations) =
496            self.collect_invocations(input_fragment, &[]);
497
498        // Optimization: if we resolve all imports now,
499        // we'll be able to immediately resolve most of imported macros.
500        self.resolve_imports();
501
502        // Resolve paths in all invocations and produce output expanded fragments for them, but
503        // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
504        // The output fragments also go through expansion recursively until no invocations are left.
505        // Unresolved macros produce dummy outputs as a recovery measure.
506        invocations.reverse();
507        let mut expanded_fragments = Vec::new();
508        let mut undetermined_invocations = Vec::new();
509        let (mut progress, mut force) = (false, !self.monotonic);
510        loop {
511            let Some((invoc, ext)) = invocations.pop() else {
512                self.resolve_imports();
513                if undetermined_invocations.is_empty() {
514                    break;
515                }
516                invocations = mem::take(&mut undetermined_invocations);
517                force = !progress;
518                progress = false;
519                if force && self.monotonic {
520                    self.cx.dcx().span_delayed_bug(
521                        invocations.last().unwrap().0.span(),
522                        "expansion entered force mode without producing any errors",
523                    );
524                }
525                continue;
526            };
527
528            let ext = match ext {
529                Some(ext) => ext,
530                None => {
531                    let eager_expansion_root = if self.monotonic {
532                        invoc.expansion_data.id
533                    } else {
534                        orig_expansion_data.id
535                    };
536                    match self.cx.resolver.resolve_macro_invocation(
537                        &invoc,
538                        eager_expansion_root,
539                        force,
540                    ) {
541                        Ok(ext) => ext,
542                        Err(Indeterminate) => {
543                            // Cannot resolve, will retry this invocation later.
544                            undetermined_invocations.push((invoc, None));
545                            continue;
546                        }
547                    }
548                }
549            };
550
551            let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
552            let depth = depth - orig_expansion_data.depth;
553            self.cx.current_expansion = invoc.expansion_data.clone();
554            self.cx.force_mode = force;
555
556            let fragment_kind = invoc.fragment_kind;
557            match self.expand_invoc(invoc, &ext.kind) {
558                ExpandResult::Ready(fragment) => {
559                    let mut derive_invocations = Vec::new();
560                    let derive_placeholders = self
561                        .cx
562                        .resolver
563                        .take_derive_resolutions(expn_id)
564                        .map(|derives| {
565                            derive_invocations.reserve(derives.len());
566                            derives
567                                .into_iter()
568                                .map(|DeriveResolution { path, item, exts: _, is_const }| {
569                                    // FIXME: Consider using the derive resolutions (`_exts`)
570                                    // instead of enqueuing the derives to be resolved again later.
571                                    // Note that this can result in duplicate diagnostics.
572                                    let expn_id = LocalExpnId::fresh_empty();
573                                    derive_invocations.push((
574                                        Invocation {
575                                            kind: InvocationKind::Derive { path, item, is_const },
576                                            fragment_kind,
577                                            expansion_data: ExpansionData {
578                                                id: expn_id,
579                                                ..self.cx.current_expansion.clone()
580                                            },
581                                        },
582                                        None,
583                                    ));
584                                    NodeId::placeholder_from_expn_id(expn_id)
585                                })
586                                .collect::<Vec<_>>()
587                        })
588                        .unwrap_or_default();
589
590                    let (expanded_fragment, collected_invocations) =
591                        self.collect_invocations(fragment, &derive_placeholders);
592                    // We choose to expand any derive invocations associated with this macro
593                    // invocation *before* any macro invocations collected from the output
594                    // fragment.
595                    derive_invocations.extend(collected_invocations);
596
597                    progress = true;
598                    if expanded_fragments.len() < depth {
599                        expanded_fragments.push(Vec::new());
600                    }
601                    expanded_fragments[depth - 1].push((expn_id, expanded_fragment));
602                    invocations.extend(derive_invocations.into_iter().rev());
603                }
604                ExpandResult::Retry(invoc) => {
605                    if force {
606                        self.cx.dcx().span_bug(
607                            invoc.span(),
608                            "expansion entered force mode but is still stuck",
609                        );
610                    } else {
611                        // Cannot expand, will retry this invocation later.
612                        undetermined_invocations.push((invoc, Some(ext)));
613                    }
614                }
615            }
616        }
617
618        self.cx.current_expansion = orig_expansion_data;
619        self.cx.force_mode = orig_force_mode;
620
621        // Finally incorporate all the expanded macros into the input AST fragment.
622        let mut placeholder_expander = PlaceholderExpander::default();
623        while let Some(expanded_fragments) = expanded_fragments.pop() {
624            for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
625                placeholder_expander
626                    .add(NodeId::placeholder_from_expn_id(expn_id), expanded_fragment);
627            }
628        }
629        fragment_with_placeholders.mut_visit_with(&mut placeholder_expander);
630        fragment_with_placeholders
631    }
632
633    fn resolve_imports(&mut self) {
634        if self.monotonic {
635            self.cx.resolver.resolve_imports();
636        }
637    }
638
639    /// Collects all macro invocations reachable at this time in this AST fragment, and replace
640    /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
641    /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
642    /// prepares data for resolving paths of macro invocations.
643    fn collect_invocations(
644        &mut self,
645        mut fragment: AstFragment,
646        extra_placeholders: &[NodeId],
647    ) -> (AstFragment, Vec<(Invocation, Option<Arc<SyntaxExtension>>)>) {
648        // Resolve `$crate`s in the fragment for pretty-printing.
649        self.cx.resolver.resolve_dollar_crates();
650
651        let mut invocations = {
652            let mut collector = InvocationCollector {
653                // Non-derive macro invocations cannot see the results of cfg expansion - they
654                // will either be removed along with the item, or invoked before the cfg/cfg_attr
655                // attribute is expanded. Therefore, we don't need to configure the tokens
656                // Derive macros *can* see the results of cfg-expansion - they are handled
657                // specially in `fully_expand_fragment`
658                cx: self.cx,
659                invocations: Vec::new(),
660                monotonic: self.monotonic,
661            };
662            fragment.mut_visit_with(&mut collector);
663            fragment.add_placeholders(extra_placeholders);
664            collector.invocations
665        };
666
667        if self.monotonic {
668            self.cx
669                .resolver
670                .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);
671
672            if self.cx.sess.opts.incremental.is_some() {
673                for (invoc, _) in invocations.iter_mut() {
674                    let expn_id = invoc.expansion_data.id;
675                    let parent_def = self.cx.resolver.invocation_parent(expn_id);
676                    let span = invoc.span_mut();
677                    *span = span.with_parent(Some(parent_def));
678                }
679            }
680        }
681
682        (fragment, invocations)
683    }
684
685    fn error_recursion_limit_reached(&mut self) -> ErrorGuaranteed {
686        let expn_data = self.cx.current_expansion.id.expn_data();
687        let suggested_limit = match self.cx.ecfg.recursion_limit {
688            Limit(0) => Limit(2),
689            limit => limit * 2,
690        };
691
692        let guar = self.cx.dcx().emit_err(RecursionLimitReached {
693            span: expn_data.call_site,
694            descr: expn_data.kind.descr(),
695            suggested_limit,
696            crate_name: self.cx.ecfg.crate_name,
697        });
698
699        self.cx.macro_error_and_trace_macros_diag();
700        guar
701    }
702
703    /// A macro's expansion does not fit in this fragment kind.
704    /// For example, a non-type macro in a type position.
705    fn error_wrong_fragment_kind(
706        &mut self,
707        kind: AstFragmentKind,
708        mac: &ast::MacCall,
709        span: Span,
710    ) -> ErrorGuaranteed {
711        let guar =
712            self.cx.dcx().emit_err(WrongFragmentKind { span, kind: kind.name(), name: &mac.path });
713        self.cx.macro_error_and_trace_macros_diag();
714        guar
715    }
716
717    fn expand_invoc(
718        &mut self,
719        invoc: Invocation,
720        ext: &SyntaxExtensionKind,
721    ) -> ExpandResult<AstFragment, Invocation> {
722        let recursion_limit = match self.cx.reduced_recursion_limit {
723            Some((limit, _)) => limit,
724            None => self.cx.ecfg.recursion_limit,
725        };
726
727        if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
728            let guar = match self.cx.reduced_recursion_limit {
729                Some((_, guar)) => guar,
730                None => self.error_recursion_limit_reached(),
731            };
732
733            // Reduce the recursion limit by half each time it triggers.
734            self.cx.reduced_recursion_limit = Some((recursion_limit / 2, guar));
735
736            return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span(), guar));
737        }
738
739        let macro_stats = self.cx.sess.opts.unstable_opts.macro_stats;
740
741        let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
742        ExpandResult::Ready(match invoc.kind {
743            InvocationKind::Bang { mac, span } => {
744                if let SyntaxExtensionKind::Bang(expander) = ext {
745                    match expander.expand(self.cx, span, mac.args.tokens.clone()) {
746                        Ok(tok_result) => {
747                            let fragment =
748                                self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span);
749                            if macro_stats {
750                                update_bang_macro_stats(
751                                    self.cx,
752                                    fragment_kind,
753                                    span,
754                                    mac,
755                                    &fragment,
756                                );
757                            }
758                            fragment
759                        }
760                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
761                    }
762                } else if let Some(expander) = ext.as_legacy_bang() {
763                    let tok_result = match expander.expand(self.cx, span, mac.args.tokens.clone()) {
764                        ExpandResult::Ready(tok_result) => tok_result,
765                        ExpandResult::Retry(_) => {
766                            // retry the original
767                            return ExpandResult::Retry(Invocation {
768                                kind: InvocationKind::Bang { mac, span },
769                                ..invoc
770                            });
771                        }
772                    };
773                    if let Some(fragment) = fragment_kind.make_from(tok_result) {
774                        if macro_stats {
775                            update_bang_macro_stats(self.cx, fragment_kind, span, mac, &fragment);
776                        }
777                        fragment
778                    } else {
779                        let guar = self.error_wrong_fragment_kind(fragment_kind, &mac, span);
780                        fragment_kind.dummy(span, guar)
781                    }
782                } else {
783                    unreachable!();
784                }
785            }
786            InvocationKind::Attr { attr, pos, mut item, derives } => {
787                if let Some(expander) = ext.as_attr() {
788                    self.gate_proc_macro_input(&item);
789                    self.gate_proc_macro_attr_item(span, &item);
790                    let tokens = match &item {
791                        // FIXME: Collect tokens and use them instead of generating
792                        // fake ones. These are unstable, so it needs to be
793                        // fixed prior to stabilization
794                        // Fake tokens when we are invoking an inner attribute, and
795                        // we are invoking it on an out-of-line module or crate.
796                        Annotatable::Crate(krate) => {
797                            rustc_parse::fake_token_stream_for_crate(&self.cx.sess.psess, krate)
798                        }
799                        Annotatable::Item(item_inner)
800                            if matches!(attr.style, AttrStyle::Inner)
801                                && matches!(
802                                    item_inner.kind,
803                                    ItemKind::Mod(
804                                        _,
805                                        _,
806                                        ModKind::Unloaded
807                                            | ModKind::Loaded(_, Inline::No { .. }, _),
808                                    )
809                                ) =>
810                        {
811                            rustc_parse::fake_token_stream_for_item(&self.cx.sess.psess, item_inner)
812                        }
813                        _ => item.to_tokens(),
814                    };
815                    let attr_item = attr.get_normal_item();
816                    if let AttrArgs::Eq { .. } = attr_item.args {
817                        self.cx.dcx().emit_err(UnsupportedKeyValue { span });
818                    }
819                    let inner_tokens = attr_item.args.inner_tokens();
820                    match expander.expand(self.cx, span, inner_tokens, tokens) {
821                        Ok(tok_result) => {
822                            let fragment = self.parse_ast_fragment(
823                                tok_result,
824                                fragment_kind,
825                                &attr_item.path,
826                                span,
827                            );
828                            if macro_stats {
829                                update_attr_macro_stats(
830                                    self.cx,
831                                    fragment_kind,
832                                    span,
833                                    &attr_item.path,
834                                    &attr,
835                                    item,
836                                    &fragment,
837                                );
838                            }
839                            fragment
840                        }
841                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
842                    }
843                } else if let SyntaxExtensionKind::LegacyAttr(expander) = ext {
844                    match validate_attr::parse_meta(&self.cx.sess.psess, &attr) {
845                        Ok(meta) => {
846                            let item_clone = macro_stats.then(|| item.clone());
847                            let items = match expander.expand(self.cx, span, &meta, item, false) {
848                                ExpandResult::Ready(items) => items,
849                                ExpandResult::Retry(item) => {
850                                    // Reassemble the original invocation for retrying.
851                                    return ExpandResult::Retry(Invocation {
852                                        kind: InvocationKind::Attr { attr, pos, item, derives },
853                                        ..invoc
854                                    });
855                                }
856                            };
857                            if matches!(
858                                fragment_kind,
859                                AstFragmentKind::Expr | AstFragmentKind::MethodReceiverExpr
860                            ) && items.is_empty()
861                            {
862                                let guar = self.cx.dcx().emit_err(RemoveExprNotSupported { span });
863                                fragment_kind.dummy(span, guar)
864                            } else {
865                                let fragment = fragment_kind.expect_from_annotatables(items);
866                                if macro_stats {
867                                    update_attr_macro_stats(
868                                        self.cx,
869                                        fragment_kind,
870                                        span,
871                                        &meta.path,
872                                        &attr,
873                                        item_clone.unwrap(),
874                                        &fragment,
875                                    );
876                                }
877                                fragment
878                            }
879                        }
880                        Err(err) => {
881                            let _guar = err.emit();
882                            fragment_kind.expect_from_annotatables(iter::once(item))
883                        }
884                    }
885                } else if let SyntaxExtensionKind::NonMacroAttr = ext {
886                    // `-Zmacro-stats` ignores these because they don't do any real expansion.
887                    self.cx.expanded_inert_attrs.mark(&attr);
888                    item.visit_attrs(|attrs| attrs.insert(pos, attr));
889                    fragment_kind.expect_from_annotatables(iter::once(item))
890                } else {
891                    unreachable!();
892                }
893            }
894            InvocationKind::Derive { path, item, is_const } => match ext {
895                SyntaxExtensionKind::Derive(expander)
896                | SyntaxExtensionKind::LegacyDerive(expander) => {
897                    if let SyntaxExtensionKind::Derive(..) = ext {
898                        self.gate_proc_macro_input(&item);
899                    }
900                    // The `MetaItem` representing the trait to derive can't
901                    // have an unsafe around it (as of now).
902                    let meta = ast::MetaItem {
903                        unsafety: ast::Safety::Default,
904                        kind: MetaItemKind::Word,
905                        span,
906                        path,
907                    };
908                    let items = match expander.expand(self.cx, span, &meta, item, is_const) {
909                        ExpandResult::Ready(items) => items,
910                        ExpandResult::Retry(item) => {
911                            // Reassemble the original invocation for retrying.
912                            return ExpandResult::Retry(Invocation {
913                                kind: InvocationKind::Derive { path: meta.path, item, is_const },
914                                ..invoc
915                            });
916                        }
917                    };
918                    let fragment = fragment_kind.expect_from_annotatables(items);
919                    if macro_stats {
920                        update_derive_macro_stats(
921                            self.cx,
922                            fragment_kind,
923                            span,
924                            &meta.path,
925                            &fragment,
926                        );
927                    }
928                    fragment
929                }
930                SyntaxExtensionKind::MacroRules(expander)
931                    if expander.kinds().contains(MacroKinds::DERIVE) =>
932                {
933                    if is_const {
934                        let guar = self
935                            .cx
936                            .dcx()
937                            .span_err(span, "macro `derive` does not support const derives");
938                        return ExpandResult::Ready(fragment_kind.dummy(span, guar));
939                    }
940                    let body = item.to_tokens();
941                    match expander.expand_derive(self.cx, span, &body) {
942                        Ok(tok_result) => {
943                            let fragment =
944                                self.parse_ast_fragment(tok_result, fragment_kind, &path, span);
945                            if macro_stats {
946                                update_derive_macro_stats(
947                                    self.cx,
948                                    fragment_kind,
949                                    span,
950                                    &path,
951                                    &fragment,
952                                );
953                            }
954                            fragment
955                        }
956                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
957                    }
958                }
959                _ => unreachable!(),
960            },
961            InvocationKind::GlobDelegation { item, of_trait } => {
962                let AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() };
963                let suffixes = match ext {
964                    SyntaxExtensionKind::GlobDelegation(expander) => match expander.expand(self.cx)
965                    {
966                        ExpandResult::Ready(suffixes) => suffixes,
967                        ExpandResult::Retry(()) => {
968                            // Reassemble the original invocation for retrying.
969                            return ExpandResult::Retry(Invocation {
970                                kind: InvocationKind::GlobDelegation { item, of_trait },
971                                ..invoc
972                            });
973                        }
974                    },
975                    SyntaxExtensionKind::LegacyBang(..) => {
976                        let msg = "expanded a dummy glob delegation";
977                        let guar = self.cx.dcx().span_delayed_bug(span, msg);
978                        return ExpandResult::Ready(fragment_kind.dummy(span, guar));
979                    }
980                    _ => unreachable!(),
981                };
982
983                type Node = AstNodeWrapper<Box<ast::AssocItem>, ImplItemTag>;
984                let single_delegations = build_single_delegations::<Node>(
985                    self.cx, deleg, &item, &suffixes, item.span, true,
986                );
987                // `-Zmacro-stats` ignores these because they don't seem important.
988                fragment_kind.expect_from_annotatables(single_delegations.map(|item| {
989                    Annotatable::AssocItem(Box::new(item), AssocCtxt::Impl { of_trait })
990                }))
991            }
992        })
993    }
994
995    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
996    fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
997        let kind = match item {
998            Annotatable::Item(_)
999            | Annotatable::AssocItem(..)
1000            | Annotatable::ForeignItem(_)
1001            | Annotatable::Crate(..) => return,
1002            Annotatable::Stmt(stmt) => {
1003                // Attributes are stable on item statements,
1004                // but unstable on all other kinds of statements
1005                if stmt.is_item() {
1006                    return;
1007                }
1008                "statements"
1009            }
1010            Annotatable::Expr(_) => "expressions",
1011            Annotatable::Arm(..)
1012            | Annotatable::ExprField(..)
1013            | Annotatable::PatField(..)
1014            | Annotatable::GenericParam(..)
1015            | Annotatable::Param(..)
1016            | Annotatable::FieldDef(..)
1017            | Annotatable::Variant(..)
1018            | Annotatable::WherePredicate(..) => panic!("unexpected annotatable"),
1019        };
1020        if self.cx.ecfg.features.proc_macro_hygiene() {
1021            return;
1022        }
1023        feature_err(
1024            &self.cx.sess,
1025            sym::proc_macro_hygiene,
1026            span,
1027            format!("custom attributes cannot be applied to {kind}"),
1028        )
1029        .emit();
1030    }
1031
1032    fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
1033        struct GateProcMacroInput<'a> {
1034            sess: &'a Session,
1035        }
1036
1037        impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
1038            fn visit_item(&mut self, item: &'ast ast::Item) {
1039                match &item.kind {
1040                    ItemKind::Mod(_, _, mod_kind)
1041                        if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
1042                    {
1043                        feature_err(
1044                            self.sess,
1045                            sym::proc_macro_hygiene,
1046                            item.span,
1047                            fluent_generated::expand_non_inline_modules_in_proc_macro_input_are_unstable,
1048                        )
1049                        .emit();
1050                    }
1051                    _ => {}
1052                }
1053
1054                visit::walk_item(self, item);
1055            }
1056        }
1057
1058        if !self.cx.ecfg.features.proc_macro_hygiene() {
1059            annotatable.visit_with(&mut GateProcMacroInput { sess: &self.cx.sess });
1060        }
1061    }
1062
1063    fn parse_ast_fragment(
1064        &mut self,
1065        toks: TokenStream,
1066        kind: AstFragmentKind,
1067        path: &ast::Path,
1068        span: Span,
1069    ) -> AstFragment {
1070        let mut parser = self.cx.new_parser_from_tts(toks);
1071        match parse_ast_fragment(&mut parser, kind) {
1072            Ok(fragment) => {
1073                ensure_complete_parse(&parser, path, kind.name(), span);
1074                fragment
1075            }
1076            Err(mut err) => {
1077                if err.span.is_dummy() {
1078                    err.span(span);
1079                }
1080                annotate_err_with_kind(&mut err, kind, span);
1081                let guar = err.emit();
1082                self.cx.macro_error_and_trace_macros_diag();
1083                kind.dummy(span, guar)
1084            }
1085        }
1086    }
1087}
1088
1089pub fn parse_ast_fragment<'a>(
1090    this: &mut Parser<'a>,
1091    kind: AstFragmentKind,
1092) -> PResult<'a, AstFragment> {
1093    Ok(match kind {
1094        AstFragmentKind::Items => {
1095            let mut items = SmallVec::new();
1096            while let Some(item) = this.parse_item(ForceCollect::No)? {
1097                items.push(item);
1098            }
1099            AstFragment::Items(items)
1100        }
1101        AstFragmentKind::TraitItems => {
1102            let mut items = SmallVec::new();
1103            while let Some(item) = this.parse_trait_item(ForceCollect::No)? {
1104                items.extend(item);
1105            }
1106            AstFragment::TraitItems(items)
1107        }
1108        AstFragmentKind::ImplItems => {
1109            let mut items = SmallVec::new();
1110            while let Some(item) = this.parse_impl_item(ForceCollect::No)? {
1111                items.extend(item);
1112            }
1113            AstFragment::ImplItems(items)
1114        }
1115        AstFragmentKind::TraitImplItems => {
1116            let mut items = SmallVec::new();
1117            while let Some(item) = this.parse_impl_item(ForceCollect::No)? {
1118                items.extend(item);
1119            }
1120            AstFragment::TraitImplItems(items)
1121        }
1122        AstFragmentKind::ForeignItems => {
1123            let mut items = SmallVec::new();
1124            while let Some(item) = this.parse_foreign_item(ForceCollect::No)? {
1125                items.extend(item);
1126            }
1127            AstFragment::ForeignItems(items)
1128        }
1129        AstFragmentKind::Stmts => {
1130            let mut stmts = SmallVec::new();
1131            // Won't make progress on a `}`.
1132            while this.token != token::Eof && this.token != token::CloseBrace {
1133                if let Some(stmt) = this.parse_full_stmt(AttemptLocalParseRecovery::Yes)? {
1134                    stmts.push(stmt);
1135                }
1136            }
1137            AstFragment::Stmts(stmts)
1138        }
1139        AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
1140        AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(this.parse_expr()?),
1141        AstFragmentKind::OptExpr => {
1142            if this.token != token::Eof {
1143                AstFragment::OptExpr(Some(this.parse_expr()?))
1144            } else {
1145                AstFragment::OptExpr(None)
1146            }
1147        }
1148        AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
1149        AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_guard(
1150            None,
1151            RecoverComma::No,
1152            RecoverColon::Yes,
1153            CommaRecoveryMode::LikelyTuple,
1154        )?),
1155        AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?),
1156        AstFragmentKind::Arms
1157        | AstFragmentKind::ExprFields
1158        | AstFragmentKind::PatFields
1159        | AstFragmentKind::GenericParams
1160        | AstFragmentKind::Params
1161        | AstFragmentKind::FieldDefs
1162        | AstFragmentKind::Variants
1163        | AstFragmentKind::WherePredicates => panic!("unexpected AST fragment kind"),
1164    })
1165}
1166
1167pub(crate) fn ensure_complete_parse<'a>(
1168    parser: &Parser<'a>,
1169    macro_path: &ast::Path,
1170    kind_name: &str,
1171    span: Span,
1172) {
1173    if parser.token != token::Eof {
1174        let descr = token_descr(&parser.token);
1175        // Avoid emitting backtrace info twice.
1176        let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root());
1177
1178        let semi_span = parser.psess.source_map().next_point(span);
1179        let add_semicolon = match &parser.psess.source_map().span_to_snippet(semi_span) {
1180            Ok(snippet) if &snippet[..] != ";" && kind_name == "expression" => {
1181                Some(span.shrink_to_hi())
1182            }
1183            _ => None,
1184        };
1185
1186        let expands_to_match_arm = kind_name == "pattern" && parser.token == token::FatArrow;
1187
1188        parser.dcx().emit_err(IncompleteParse {
1189            span: def_site_span,
1190            descr,
1191            label_span: span,
1192            macro_path,
1193            kind_name,
1194            expands_to_match_arm,
1195            add_semicolon,
1196        });
1197    }
1198}
1199
1200/// Wraps a call to `walk_*` / `walk_flat_map_*`
1201/// for an AST node that supports attributes
1202/// (see the `Annotatable` enum)
1203/// This method assigns a `NodeId`, and sets that `NodeId`
1204/// as our current 'lint node id'. If a macro call is found
1205/// inside this AST node, we will use this AST node's `NodeId`
1206/// to emit lints associated with that macro (allowing
1207/// `#[allow]` / `#[deny]` to be applied close to
1208/// the macro invocation).
1209///
1210/// Do *not* call this for a macro AST node
1211/// (e.g. `ExprKind::MacCall`) - we cannot emit lints
1212/// at these AST nodes, since they are removed and
1213/// replaced with the result of macro expansion.
1214///
1215/// All other `NodeId`s are assigned by `visit_id`.
1216/// * `self` is the 'self' parameter for the current method,
1217/// * `id` is a mutable reference to the `NodeId` field
1218///    of the current AST node.
1219/// * `closure` is a closure that executes the
1220///   `walk_*` / `walk_flat_map_*` method
1221///   for the current AST node.
1222macro_rules! assign_id {
1223    ($self:ident, $id:expr, $closure:expr) => {{
1224        let old_id = $self.cx.current_expansion.lint_node_id;
1225        if $self.monotonic {
1226            debug_assert_eq!(*$id, ast::DUMMY_NODE_ID);
1227            let new_id = $self.cx.resolver.next_node_id();
1228            *$id = new_id;
1229            $self.cx.current_expansion.lint_node_id = new_id;
1230        }
1231        let ret = ($closure)();
1232        $self.cx.current_expansion.lint_node_id = old_id;
1233        ret
1234    }};
1235}
1236
1237enum AddSemicolon {
1238    Yes,
1239    No,
1240}
1241
1242/// A trait implemented for all `AstFragment` nodes and providing all pieces
1243/// of functionality used by `InvocationCollector`.
1244trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
1245    type OutputTy = SmallVec<[Self; 1]>;
1246    type ItemKind = ItemKind;
1247    const KIND: AstFragmentKind;
1248    fn to_annotatable(self) -> Annotatable;
1249    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy;
1250    fn descr() -> &'static str {
1251        unreachable!()
1252    }
1253    fn walk_flat_map(self, _collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1254        unreachable!()
1255    }
1256    fn walk(&mut self, _collector: &mut InvocationCollector<'_, '_>) {
1257        unreachable!()
1258    }
1259    fn is_mac_call(&self) -> bool {
1260        false
1261    }
1262    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1263        unreachable!()
1264    }
1265    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
1266        None
1267    }
1268    fn delegation_item_kind(_deleg: Box<ast::Delegation>) -> Self::ItemKind {
1269        unreachable!()
1270    }
1271    fn from_item(_item: ast::Item<Self::ItemKind>) -> Self {
1272        unreachable!()
1273    }
1274    fn flatten_outputs(_outputs: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
1275        unreachable!()
1276    }
1277    fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {}
1278    fn post_flat_map_node_collect_bang(_output: &mut Self::OutputTy, _add_semicolon: AddSemicolon) {
1279    }
1280    fn wrap_flat_map_node_walk_flat_map(
1281        node: Self,
1282        collector: &mut InvocationCollector<'_, '_>,
1283        walk_flat_map: impl FnOnce(Self, &mut InvocationCollector<'_, '_>) -> Self::OutputTy,
1284    ) -> Result<Self::OutputTy, Self> {
1285        Ok(walk_flat_map(node, collector))
1286    }
1287    fn expand_cfg_false(
1288        &mut self,
1289        collector: &mut InvocationCollector<'_, '_>,
1290        _pos: usize,
1291        span: Span,
1292    ) {
1293        collector.cx.dcx().emit_err(RemoveNodeNotSupported { span, descr: Self::descr() });
1294    }
1295
1296    /// All of the identifiers (items) declared by this node.
1297    /// This is an approximation and should only be used for diagnostics.
1298    fn declared_idents(&self) -> Vec<Ident> {
1299        vec![]
1300    }
1301}
1302
1303impl InvocationCollectorNode for Box<ast::Item> {
1304    const KIND: AstFragmentKind = AstFragmentKind::Items;
1305    fn to_annotatable(self) -> Annotatable {
1306        Annotatable::Item(self)
1307    }
1308    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1309        fragment.make_items()
1310    }
1311    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1312        walk_flat_map_item(collector, self)
1313    }
1314    fn is_mac_call(&self) -> bool {
1315        matches!(self.kind, ItemKind::MacCall(..))
1316    }
1317    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1318        match self.kind {
1319            ItemKind::MacCall(mac) => (mac, self.attrs, AddSemicolon::No),
1320            _ => unreachable!(),
1321        }
1322    }
1323    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
1324        match &self.kind {
1325            ItemKind::DelegationMac(deleg) => Some((deleg, self)),
1326            _ => None,
1327        }
1328    }
1329    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
1330        ItemKind::Delegation(deleg)
1331    }
1332    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
1333        Box::new(item)
1334    }
1335    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
1336        items.flatten().collect()
1337    }
1338    fn wrap_flat_map_node_walk_flat_map(
1339        mut node: Self,
1340        collector: &mut InvocationCollector<'_, '_>,
1341        walk_flat_map: impl FnOnce(Self, &mut InvocationCollector<'_, '_>) -> Self::OutputTy,
1342    ) -> Result<Self::OutputTy, Self> {
1343        if !matches!(node.kind, ItemKind::Mod(..)) {
1344            return Ok(walk_flat_map(node, collector));
1345        }
1346
1347        // Work around borrow checker not seeing through `P`'s deref.
1348        let (span, mut attrs) = (node.span, mem::take(&mut node.attrs));
1349        let ItemKind::Mod(_, ident, ref mut mod_kind) = node.kind else { unreachable!() };
1350        let ecx = &mut collector.cx;
1351        let (file_path, dir_path, dir_ownership) = match mod_kind {
1352            ModKind::Loaded(_, inline, _) => {
1353                // Inline `mod foo { ... }`, but we still need to push directories.
1354                let (dir_path, dir_ownership) = mod_dir_path(
1355                    ecx.sess,
1356                    ident,
1357                    &attrs,
1358                    &ecx.current_expansion.module,
1359                    ecx.current_expansion.dir_ownership,
1360                    *inline,
1361                );
1362                // If the module was parsed from an external file, recover its path.
1363                // This lets `parse_external_mod` catch cycles if it's self-referential.
1364                let file_path = match inline {
1365                    Inline::Yes => None,
1366                    Inline::No { .. } => mod_file_path_from_attr(ecx.sess, &attrs, &dir_path),
1367                };
1368                node.attrs = attrs;
1369                (file_path, dir_path, dir_ownership)
1370            }
1371            ModKind::Unloaded => {
1372                // We have an outline `mod foo;` so we need to parse the file.
1373                let old_attrs_len = attrs.len();
1374                let ParsedExternalMod {
1375                    items,
1376                    spans,
1377                    file_path,
1378                    dir_path,
1379                    dir_ownership,
1380                    had_parse_error,
1381                } = parse_external_mod(
1382                    ecx.sess,
1383                    ident,
1384                    span,
1385                    &ecx.current_expansion.module,
1386                    ecx.current_expansion.dir_ownership,
1387                    &mut attrs,
1388                );
1389
1390                if let Some(lint_store) = ecx.lint_store {
1391                    lint_store.pre_expansion_lint(
1392                        ecx.sess,
1393                        ecx.ecfg.features,
1394                        ecx.resolver.registered_tools(),
1395                        ecx.current_expansion.lint_node_id,
1396                        &attrs,
1397                        &items,
1398                        ident.name,
1399                    );
1400                }
1401
1402                *mod_kind = ModKind::Loaded(items, Inline::No { had_parse_error }, spans);
1403                node.attrs = attrs;
1404                if node.attrs.len() > old_attrs_len {
1405                    // If we loaded an out-of-line module and added some inner attributes,
1406                    // then we need to re-configure it and re-collect attributes for
1407                    // resolution and expansion.
1408                    return Err(node);
1409                }
1410                (Some(file_path), dir_path, dir_ownership)
1411            }
1412        };
1413
1414        // Set the module info before we flat map.
1415        let mut module = ecx.current_expansion.module.with_dir_path(dir_path);
1416        module.mod_path.push(ident);
1417        if let Some(file_path) = file_path {
1418            module.file_path_stack.push(file_path);
1419        }
1420
1421        let orig_module = mem::replace(&mut ecx.current_expansion.module, Rc::new(module));
1422        let orig_dir_ownership =
1423            mem::replace(&mut ecx.current_expansion.dir_ownership, dir_ownership);
1424
1425        let res = Ok(walk_flat_map(node, collector));
1426
1427        collector.cx.current_expansion.dir_ownership = orig_dir_ownership;
1428        collector.cx.current_expansion.module = orig_module;
1429        res
1430    }
1431
1432    fn declared_idents(&self) -> Vec<Ident> {
1433        if let ItemKind::Use(ut) = &self.kind {
1434            fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
1435                match &ut.kind {
1436                    ast::UseTreeKind::Glob => {}
1437                    ast::UseTreeKind::Simple(_) => idents.push(ut.ident()),
1438                    ast::UseTreeKind::Nested { items, .. } => {
1439                        for (ut, _) in items {
1440                            collect_use_tree_leaves(ut, idents);
1441                        }
1442                    }
1443                }
1444            }
1445            let mut idents = Vec::new();
1446            collect_use_tree_leaves(&ut, &mut idents);
1447            idents
1448        } else {
1449            self.kind.ident().into_iter().collect()
1450        }
1451    }
1452}
1453
1454struct TraitItemTag;
1455impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, TraitItemTag> {
1456    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;
1457    type ItemKind = AssocItemKind;
1458    const KIND: AstFragmentKind = AstFragmentKind::TraitItems;
1459    fn to_annotatable(self) -> Annotatable {
1460        Annotatable::AssocItem(self.wrapped, AssocCtxt::Trait)
1461    }
1462    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1463        fragment.make_trait_items()
1464    }
1465    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1466        walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Trait)
1467    }
1468    fn is_mac_call(&self) -> bool {
1469        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
1470    }
1471    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1472        let item = self.wrapped;
1473        match item.kind {
1474            AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
1475            _ => unreachable!(),
1476        }
1477    }
1478    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
1479        match &self.wrapped.kind {
1480            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
1481            _ => None,
1482        }
1483    }
1484    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
1485        AssocItemKind::Delegation(deleg)
1486    }
1487    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
1488        AstNodeWrapper::new(Box::new(item), TraitItemTag)
1489    }
1490    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
1491        items.flatten().collect()
1492    }
1493}
1494
1495struct ImplItemTag;
1496impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, ImplItemTag> {
1497    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;
1498    type ItemKind = AssocItemKind;
1499    const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
1500    fn to_annotatable(self) -> Annotatable {
1501        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: false })
1502    }
1503    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1504        fragment.make_impl_items()
1505    }
1506    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1507        walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Impl { of_trait: false })
1508    }
1509    fn is_mac_call(&self) -> bool {
1510        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
1511    }
1512    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1513        let item = self.wrapped;
1514        match item.kind {
1515            AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
1516            _ => unreachable!(),
1517        }
1518    }
1519    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
1520        match &self.wrapped.kind {
1521            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
1522            _ => None,
1523        }
1524    }
1525    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
1526        AssocItemKind::Delegation(deleg)
1527    }
1528    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
1529        AstNodeWrapper::new(Box::new(item), ImplItemTag)
1530    }
1531    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
1532        items.flatten().collect()
1533    }
1534}
1535
1536struct TraitImplItemTag;
1537impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, TraitImplItemTag> {
1538    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;
1539    type ItemKind = AssocItemKind;
1540    const KIND: AstFragmentKind = AstFragmentKind::TraitImplItems;
1541    fn to_annotatable(self) -> Annotatable {
1542        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: true })
1543    }
1544    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1545        fragment.make_trait_impl_items()
1546    }
1547    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1548        walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Impl { of_trait: true })
1549    }
1550    fn is_mac_call(&self) -> bool {
1551        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
1552    }
1553    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1554        let item = self.wrapped;
1555        match item.kind {
1556            AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
1557            _ => unreachable!(),
1558        }
1559    }
1560    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
1561        match &self.wrapped.kind {
1562            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
1563            _ => None,
1564        }
1565    }
1566    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
1567        AssocItemKind::Delegation(deleg)
1568    }
1569    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
1570        AstNodeWrapper::new(Box::new(item), TraitImplItemTag)
1571    }
1572    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
1573        items.flatten().collect()
1574    }
1575}
1576
1577impl InvocationCollectorNode for Box<ast::ForeignItem> {
1578    const KIND: AstFragmentKind = AstFragmentKind::ForeignItems;
1579    fn to_annotatable(self) -> Annotatable {
1580        Annotatable::ForeignItem(self)
1581    }
1582    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1583        fragment.make_foreign_items()
1584    }
1585    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1586        walk_flat_map_foreign_item(collector, self)
1587    }
1588    fn is_mac_call(&self) -> bool {
1589        matches!(self.kind, ForeignItemKind::MacCall(..))
1590    }
1591    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1592        match self.kind {
1593            ForeignItemKind::MacCall(mac) => (mac, self.attrs, AddSemicolon::No),
1594            _ => unreachable!(),
1595        }
1596    }
1597}
1598
1599impl InvocationCollectorNode for ast::Variant {
1600    const KIND: AstFragmentKind = AstFragmentKind::Variants;
1601    fn to_annotatable(self) -> Annotatable {
1602        Annotatable::Variant(self)
1603    }
1604    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1605        fragment.make_variants()
1606    }
1607    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1608        walk_flat_map_variant(collector, self)
1609    }
1610}
1611
1612impl InvocationCollectorNode for ast::WherePredicate {
1613    const KIND: AstFragmentKind = AstFragmentKind::WherePredicates;
1614    fn to_annotatable(self) -> Annotatable {
1615        Annotatable::WherePredicate(self)
1616    }
1617    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1618        fragment.make_where_predicates()
1619    }
1620    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1621        walk_flat_map_where_predicate(collector, self)
1622    }
1623}
1624
1625impl InvocationCollectorNode for ast::FieldDef {
1626    const KIND: AstFragmentKind = AstFragmentKind::FieldDefs;
1627    fn to_annotatable(self) -> Annotatable {
1628        Annotatable::FieldDef(self)
1629    }
1630    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1631        fragment.make_field_defs()
1632    }
1633    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1634        walk_flat_map_field_def(collector, self)
1635    }
1636}
1637
1638impl InvocationCollectorNode for ast::PatField {
1639    const KIND: AstFragmentKind = AstFragmentKind::PatFields;
1640    fn to_annotatable(self) -> Annotatable {
1641        Annotatable::PatField(self)
1642    }
1643    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1644        fragment.make_pat_fields()
1645    }
1646    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1647        walk_flat_map_pat_field(collector, self)
1648    }
1649}
1650
1651impl InvocationCollectorNode for ast::ExprField {
1652    const KIND: AstFragmentKind = AstFragmentKind::ExprFields;
1653    fn to_annotatable(self) -> Annotatable {
1654        Annotatable::ExprField(self)
1655    }
1656    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1657        fragment.make_expr_fields()
1658    }
1659    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1660        walk_flat_map_expr_field(collector, self)
1661    }
1662}
1663
1664impl InvocationCollectorNode for ast::Param {
1665    const KIND: AstFragmentKind = AstFragmentKind::Params;
1666    fn to_annotatable(self) -> Annotatable {
1667        Annotatable::Param(self)
1668    }
1669    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1670        fragment.make_params()
1671    }
1672    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1673        walk_flat_map_param(collector, self)
1674    }
1675}
1676
1677impl InvocationCollectorNode for ast::GenericParam {
1678    const KIND: AstFragmentKind = AstFragmentKind::GenericParams;
1679    fn to_annotatable(self) -> Annotatable {
1680        Annotatable::GenericParam(self)
1681    }
1682    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1683        fragment.make_generic_params()
1684    }
1685    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1686        walk_flat_map_generic_param(collector, self)
1687    }
1688}
1689
1690impl InvocationCollectorNode for ast::Arm {
1691    const KIND: AstFragmentKind = AstFragmentKind::Arms;
1692    fn to_annotatable(self) -> Annotatable {
1693        Annotatable::Arm(self)
1694    }
1695    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1696        fragment.make_arms()
1697    }
1698    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1699        walk_flat_map_arm(collector, self)
1700    }
1701}
1702
1703impl InvocationCollectorNode for ast::Stmt {
1704    const KIND: AstFragmentKind = AstFragmentKind::Stmts;
1705    fn to_annotatable(self) -> Annotatable {
1706        Annotatable::Stmt(Box::new(self))
1707    }
1708    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1709        fragment.make_stmts()
1710    }
1711    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1712        walk_flat_map_stmt(collector, self)
1713    }
1714    fn is_mac_call(&self) -> bool {
1715        match &self.kind {
1716            StmtKind::MacCall(..) => true,
1717            StmtKind::Item(item) => matches!(item.kind, ItemKind::MacCall(..)),
1718            StmtKind::Semi(expr) => matches!(expr.kind, ExprKind::MacCall(..)),
1719            StmtKind::Expr(..) => unreachable!(),
1720            StmtKind::Let(..) | StmtKind::Empty => false,
1721        }
1722    }
1723    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1724        // We pull macro invocations (both attributes and fn-like macro calls) out of their
1725        // `StmtKind`s and treat them as statement macro invocations, not as items or expressions.
1726        let (add_semicolon, mac, attrs) = match self.kind {
1727            StmtKind::MacCall(mac) => {
1728                let ast::MacCallStmt { mac, style, attrs, .. } = *mac;
1729                (style == MacStmtStyle::Semicolon, mac, attrs)
1730            }
1731            StmtKind::Item(item) => match *item {
1732                ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => {
1733                    (mac.args.need_semicolon(), mac, attrs)
1734                }
1735                _ => unreachable!(),
1736            },
1737            StmtKind::Semi(expr) => match *expr {
1738                ast::Expr { kind: ExprKind::MacCall(mac), attrs, .. } => {
1739                    (mac.args.need_semicolon(), mac, attrs)
1740                }
1741                _ => unreachable!(),
1742            },
1743            _ => unreachable!(),
1744        };
1745        (mac, attrs, if add_semicolon { AddSemicolon::Yes } else { AddSemicolon::No })
1746    }
1747    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
1748        match &self.kind {
1749            StmtKind::Item(item) => match &item.kind {
1750                ItemKind::DelegationMac(deleg) => Some((deleg, item)),
1751                _ => None,
1752            },
1753            _ => None,
1754        }
1755    }
1756    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
1757        ItemKind::Delegation(deleg)
1758    }
1759    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
1760        ast::Stmt { id: ast::DUMMY_NODE_ID, span: item.span, kind: StmtKind::Item(Box::new(item)) }
1761    }
1762    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
1763        items.flatten().collect()
1764    }
1765    fn post_flat_map_node_collect_bang(stmts: &mut Self::OutputTy, add_semicolon: AddSemicolon) {
1766        // If this is a macro invocation with a semicolon, then apply that
1767        // semicolon to the final statement produced by expansion.
1768        if matches!(add_semicolon, AddSemicolon::Yes) {
1769            if let Some(stmt) = stmts.pop() {
1770                stmts.push(stmt.add_trailing_semicolon());
1771            }
1772        }
1773    }
1774}
1775
1776impl InvocationCollectorNode for ast::Crate {
1777    type OutputTy = ast::Crate;
1778    const KIND: AstFragmentKind = AstFragmentKind::Crate;
1779    fn to_annotatable(self) -> Annotatable {
1780        Annotatable::Crate(self)
1781    }
1782    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1783        fragment.make_crate()
1784    }
1785    fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {
1786        walk_crate(collector, self)
1787    }
1788    fn expand_cfg_false(
1789        &mut self,
1790        collector: &mut InvocationCollector<'_, '_>,
1791        pos: usize,
1792        _span: Span,
1793    ) {
1794        // Attributes above `cfg(FALSE)` are left in place, because we may want to configure
1795        // some global crate properties even on fully unconfigured crates.
1796        self.attrs.truncate(pos);
1797        // Standard prelude imports are left in the crate for backward compatibility.
1798        self.items.truncate(collector.cx.num_standard_library_imports);
1799    }
1800}
1801
1802impl InvocationCollectorNode for ast::Ty {
1803    type OutputTy = Box<ast::Ty>;
1804    const KIND: AstFragmentKind = AstFragmentKind::Ty;
1805    fn to_annotatable(self) -> Annotatable {
1806        unreachable!()
1807    }
1808    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1809        fragment.make_ty()
1810    }
1811    fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {
1812        // Save the pre-expanded name of this `ImplTrait`, so that later when defining
1813        // an APIT we use a name that doesn't have any placeholder fragments in it.
1814        if let ast::TyKind::ImplTrait(..) = self.kind {
1815            // HACK: pprust breaks strings with newlines when the type
1816            // gets too long. We don't want these to show up in compiler
1817            // output or built artifacts, so replace them here...
1818            // Perhaps we should instead format APITs more robustly.
1819            let name = Symbol::intern(&pprust::ty_to_string(self).replace('\n', " "));
1820            collector.cx.resolver.insert_impl_trait_name(self.id, name);
1821        }
1822        walk_ty(collector, self)
1823    }
1824    fn is_mac_call(&self) -> bool {
1825        matches!(self.kind, ast::TyKind::MacCall(..))
1826    }
1827    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1828        match self.kind {
1829            TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
1830            _ => unreachable!(),
1831        }
1832    }
1833}
1834
1835impl InvocationCollectorNode for ast::Pat {
1836    type OutputTy = Box<ast::Pat>;
1837    const KIND: AstFragmentKind = AstFragmentKind::Pat;
1838    fn to_annotatable(self) -> Annotatable {
1839        unreachable!()
1840    }
1841    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1842        fragment.make_pat()
1843    }
1844    fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {
1845        walk_pat(collector, self)
1846    }
1847    fn is_mac_call(&self) -> bool {
1848        matches!(self.kind, PatKind::MacCall(..))
1849    }
1850    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1851        match self.kind {
1852            PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
1853            _ => unreachable!(),
1854        }
1855    }
1856}
1857
1858impl InvocationCollectorNode for ast::Expr {
1859    type OutputTy = Box<ast::Expr>;
1860    const KIND: AstFragmentKind = AstFragmentKind::Expr;
1861    fn to_annotatable(self) -> Annotatable {
1862        Annotatable::Expr(Box::new(self))
1863    }
1864    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1865        fragment.make_expr()
1866    }
1867    fn descr() -> &'static str {
1868        "an expression"
1869    }
1870    fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {
1871        walk_expr(collector, self)
1872    }
1873    fn is_mac_call(&self) -> bool {
1874        matches!(self.kind, ExprKind::MacCall(..))
1875    }
1876    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1877        match self.kind {
1878            ExprKind::MacCall(mac) => (mac, self.attrs, AddSemicolon::No),
1879            _ => unreachable!(),
1880        }
1881    }
1882}
1883
1884struct OptExprTag;
1885impl InvocationCollectorNode for AstNodeWrapper<Box<ast::Expr>, OptExprTag> {
1886    type OutputTy = Option<Box<ast::Expr>>;
1887    const KIND: AstFragmentKind = AstFragmentKind::OptExpr;
1888    fn to_annotatable(self) -> Annotatable {
1889        Annotatable::Expr(self.wrapped)
1890    }
1891    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1892        fragment.make_opt_expr()
1893    }
1894    fn walk_flat_map(mut self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {
1895        walk_expr(collector, &mut self.wrapped);
1896        Some(self.wrapped)
1897    }
1898    fn is_mac_call(&self) -> bool {
1899        matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
1900    }
1901    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1902        let node = self.wrapped;
1903        match node.kind {
1904            ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
1905            _ => unreachable!(),
1906        }
1907    }
1908    fn pre_flat_map_node_collect_attr(cfg: &StripUnconfigured<'_>, attr: &ast::Attribute) {
1909        cfg.maybe_emit_expr_attr_err(attr);
1910    }
1911}
1912
1913/// This struct is a hack to workaround unstable of `stmt_expr_attributes`.
1914/// It can be removed once that feature is stabilized.
1915struct MethodReceiverTag;
1916
1917impl InvocationCollectorNode for AstNodeWrapper<ast::Expr, MethodReceiverTag> {
1918    type OutputTy = AstNodeWrapper<Box<ast::Expr>, MethodReceiverTag>;
1919    const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
1920    fn descr() -> &'static str {
1921        "an expression"
1922    }
1923    fn to_annotatable(self) -> Annotatable {
1924        Annotatable::Expr(Box::new(self.wrapped))
1925    }
1926    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
1927        AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag)
1928    }
1929    fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {
1930        walk_expr(collector, &mut self.wrapped)
1931    }
1932    fn is_mac_call(&self) -> bool {
1933        matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
1934    }
1935    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
1936        let node = self.wrapped;
1937        match node.kind {
1938            ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
1939            _ => unreachable!(),
1940        }
1941    }
1942}
1943
1944fn build_single_delegations<'a, Node: InvocationCollectorNode>(
1945    ecx: &ExtCtxt<'_>,
1946    deleg: &'a ast::DelegationMac,
1947    item: &'a ast::Item<Node::ItemKind>,
1948    suffixes: &'a [(Ident, Option<Ident>)],
1949    item_span: Span,
1950    from_glob: bool,
1951) -> impl Iterator<Item = ast::Item<Node::ItemKind>> + 'a {
1952    if suffixes.is_empty() {
1953        // Report an error for now, to avoid keeping stem for resolution and
1954        // stability checks.
1955        let kind = String::from(if from_glob { "glob" } else { "list" });
1956        ecx.dcx().emit_err(EmptyDelegationMac { span: item.span, kind });
1957    }
1958
1959    suffixes.iter().map(move |&(ident, rename)| {
1960        let mut path = deleg.prefix.clone();
1961        path.segments.push(ast::PathSegment { ident, id: ast::DUMMY_NODE_ID, args: None });
1962
1963        ast::Item {
1964            attrs: item.attrs.clone(),
1965            id: ast::DUMMY_NODE_ID,
1966            span: if from_glob { item_span } else { ident.span },
1967            vis: item.vis.clone(),
1968            kind: Node::delegation_item_kind(Box::new(ast::Delegation {
1969                id: ast::DUMMY_NODE_ID,
1970                qself: deleg.qself.clone(),
1971                path,
1972                ident: rename.unwrap_or(ident),
1973                rename,
1974                body: deleg.body.clone(),
1975                from_glob,
1976            })),
1977            tokens: None,
1978        }
1979    })
1980}
1981
1982/// Required for `visit_node` obtained an owned `Node` from `&mut Node`.
1983trait DummyAstNode {
1984    fn dummy() -> Self;
1985}
1986
1987impl DummyAstNode for ast::Crate {
1988    fn dummy() -> Self {
1989        ast::Crate {
1990            attrs: Default::default(),
1991            items: Default::default(),
1992            spans: Default::default(),
1993            id: DUMMY_NODE_ID,
1994            is_placeholder: Default::default(),
1995        }
1996    }
1997}
1998
1999impl DummyAstNode for ast::Ty {
2000    fn dummy() -> Self {
2001        ast::Ty {
2002            id: DUMMY_NODE_ID,
2003            kind: TyKind::Dummy,
2004            span: Default::default(),
2005            tokens: Default::default(),
2006        }
2007    }
2008}
2009
2010impl DummyAstNode for ast::Pat {
2011    fn dummy() -> Self {
2012        ast::Pat {
2013            id: DUMMY_NODE_ID,
2014            kind: PatKind::Wild,
2015            span: Default::default(),
2016            tokens: Default::default(),
2017        }
2018    }
2019}
2020
2021impl DummyAstNode for ast::Expr {
2022    fn dummy() -> Self {
2023        ast::Expr::dummy()
2024    }
2025}
2026
2027impl DummyAstNode for AstNodeWrapper<ast::Expr, MethodReceiverTag> {
2028    fn dummy() -> Self {
2029        AstNodeWrapper::new(ast::Expr::dummy(), MethodReceiverTag)
2030    }
2031}
2032
2033struct InvocationCollector<'a, 'b> {
2034    cx: &'a mut ExtCtxt<'b>,
2035    invocations: Vec<(Invocation, Option<Arc<SyntaxExtension>>)>,
2036    monotonic: bool,
2037}
2038
2039impl<'a, 'b> InvocationCollector<'a, 'b> {
2040    fn cfg(&self) -> StripUnconfigured<'_> {
2041        StripUnconfigured {
2042            sess: self.cx.sess,
2043            features: Some(self.cx.ecfg.features),
2044            config_tokens: false,
2045            lint_node_id: self.cx.current_expansion.lint_node_id,
2046        }
2047    }
2048
2049    fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
2050        let expn_id = LocalExpnId::fresh_empty();
2051        if matches!(kind, InvocationKind::GlobDelegation { .. }) {
2052            // In resolver we need to know which invocation ids are delegations early,
2053            // before their `ExpnData` is filled.
2054            self.cx.resolver.register_glob_delegation(expn_id);
2055        }
2056        let vis = kind.placeholder_visibility();
2057        self.invocations.push((
2058            Invocation {
2059                kind,
2060                fragment_kind,
2061                expansion_data: ExpansionData {
2062                    id: expn_id,
2063                    depth: self.cx.current_expansion.depth + 1,
2064                    ..self.cx.current_expansion.clone()
2065                },
2066            },
2067            None,
2068        ));
2069        placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
2070    }
2071
2072    fn collect_bang(&mut self, mac: Box<ast::MacCall>, kind: AstFragmentKind) -> AstFragment {
2073        // cache the macro call span so that it can be
2074        // easily adjusted for incremental compilation
2075        let span = mac.span();
2076        self.collect(kind, InvocationKind::Bang { mac, span })
2077    }
2078
2079    fn collect_attr(
2080        &mut self,
2081        (attr, pos, derives): (ast::Attribute, usize, Vec<ast::Path>),
2082        item: Annotatable,
2083        kind: AstFragmentKind,
2084    ) -> AstFragment {
2085        self.collect(kind, InvocationKind::Attr { attr, pos, item, derives })
2086    }
2087
2088    fn collect_glob_delegation(
2089        &mut self,
2090        item: Box<ast::AssocItem>,
2091        of_trait: bool,
2092        kind: AstFragmentKind,
2093    ) -> AstFragment {
2094        self.collect(kind, InvocationKind::GlobDelegation { item, of_trait })
2095    }
2096
2097    /// If `item` is an attribute invocation, remove the attribute and return it together with
2098    /// its position and derives following it. We have to collect the derives in order to resolve
2099    /// legacy derive helpers (helpers written before derives that introduce them).
2100    fn take_first_attr(
2101        &self,
2102        item: &mut impl HasAttrs,
2103    ) -> Option<(ast::Attribute, usize, Vec<ast::Path>)> {
2104        let mut attr = None;
2105
2106        let mut cfg_pos = None;
2107        let mut attr_pos = None;
2108        for (pos, attr) in item.attrs().iter().enumerate() {
2109            if !attr.is_doc_comment() && !self.cx.expanded_inert_attrs.is_marked(attr) {
2110                let name = attr.ident().map(|ident| ident.name);
2111                if name == Some(sym::cfg) || name == Some(sym::cfg_attr) {
2112                    cfg_pos = Some(pos); // a cfg attr found, no need to search anymore
2113                    break;
2114                } else if attr_pos.is_none()
2115                    && !name.is_some_and(rustc_feature::is_builtin_attr_name)
2116                {
2117                    attr_pos = Some(pos); // a non-cfg attr found, still may find a cfg attr
2118                }
2119            }
2120        }
2121
2122        item.visit_attrs(|attrs| {
2123            attr = Some(match (cfg_pos, attr_pos) {
2124                (Some(pos), _) => (attrs.remove(pos), pos, Vec::new()),
2125                (_, Some(pos)) => {
2126                    let attr = attrs.remove(pos);
2127                    let following_derives = attrs[pos..]
2128                        .iter()
2129                        .filter(|a| a.has_name(sym::derive))
2130                        .flat_map(|a| a.meta_item_list().unwrap_or_default())
2131                        .filter_map(|meta_item_inner| match meta_item_inner {
2132                            MetaItemInner::MetaItem(ast::MetaItem {
2133                                kind: MetaItemKind::Word,
2134                                path,
2135                                ..
2136                            }) => Some(path),
2137                            _ => None,
2138                        })
2139                        .collect();
2140
2141                    (attr, pos, following_derives)
2142                }
2143                _ => return,
2144            });
2145        });
2146
2147        attr
2148    }
2149
2150    // Detect use of feature-gated or invalid attributes on macro invocations
2151    // since they will not be detected after macro expansion.
2152    fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
2153        let features = self.cx.ecfg.features;
2154        let mut attrs = attrs.iter().peekable();
2155        let mut span: Option<Span> = None;
2156        while let Some(attr) = attrs.next() {
2157            rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
2158            validate_attr::check_attr(
2159                &self.cx.sess.psess,
2160                attr,
2161                self.cx.current_expansion.lint_node_id,
2162            );
2163            AttributeParser::parse_limited_all(
2164                self.cx.sess,
2165                slice::from_ref(attr),
2166                None,
2167                Target::MacroCall,
2168                call.span(),
2169                self.cx.current_expansion.lint_node_id,
2170                Some(self.cx.ecfg.features),
2171                ShouldEmit::ErrorsAndLints,
2172            );
2173
2174            let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
2175            span = Some(current_span);
2176
2177            if attrs.peek().is_some_and(|next_attr| next_attr.doc_str().is_some()) {
2178                continue;
2179            }
2180
2181            if attr.is_doc_comment() {
2182                self.cx.sess.psess.buffer_lint(
2183                    UNUSED_DOC_COMMENTS,
2184                    current_span,
2185                    self.cx.current_expansion.lint_node_id,
2186                    BuiltinLintDiag::UnusedDocComment(attr.span),
2187                );
2188            } else if rustc_attr_parsing::is_builtin_attr(attr)
2189                && !AttributeParser::<Early>::is_parsed_attribute(&attr.path())
2190            {
2191                let attr_name = attr.ident().unwrap().name;
2192                // `#[cfg]` and `#[cfg_attr]` are special - they are
2193                // eagerly evaluated.
2194                if attr_name != sym::cfg_trace && attr_name != sym::cfg_attr_trace {
2195                    self.cx.sess.psess.buffer_lint(
2196                        UNUSED_ATTRIBUTES,
2197                        attr.span,
2198                        self.cx.current_expansion.lint_node_id,
2199                        BuiltinLintDiag::UnusedBuiltinAttribute {
2200                            attr_name,
2201                            macro_name: pprust::path_to_string(&call.path),
2202                            invoc_span: call.path.span,
2203                            attr_span: attr.span,
2204                        },
2205                    );
2206                }
2207            }
2208        }
2209    }
2210
2211    fn expand_cfg_true(
2212        &mut self,
2213        node: &mut (impl HasAttrs + HasNodeId),
2214        attr: ast::Attribute,
2215        pos: usize,
2216    ) -> EvalConfigResult {
2217        let res = self.cfg().cfg_true(&attr, node.node_id(), ShouldEmit::ErrorsAndLints);
2218        if res.as_bool() {
2219            // A trace attribute left in AST in place of the original `cfg` attribute.
2220            // It can later be used by lints or other diagnostics.
2221            let trace_attr = attr_into_trace(attr, sym::cfg_trace);
2222            node.visit_attrs(|attrs| attrs.insert(pos, trace_attr));
2223        }
2224
2225        res
2226    }
2227
2228    fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: &ast::Attribute, pos: usize) {
2229        node.visit_attrs(|attrs| {
2230            // Repeated `insert` calls is inefficient, but the number of
2231            // insertions is almost always 0 or 1 in practice.
2232            for cfg in self.cfg().expand_cfg_attr(attr, false).into_iter().rev() {
2233                attrs.insert(pos, cfg)
2234            }
2235        });
2236    }
2237
2238    fn flat_map_node<Node: InvocationCollectorNode<OutputTy: Default>>(
2239        &mut self,
2240        mut node: Node,
2241    ) -> Node::OutputTy {
2242        loop {
2243            return match self.take_first_attr(&mut node) {
2244                Some((attr, pos, derives)) => match attr.name() {
2245                    Some(sym::cfg) => {
2246                        let res = self.expand_cfg_true(&mut node, attr, pos);
2247                        match res {
2248                            EvalConfigResult::True => continue,
2249                            EvalConfigResult::False { reason, reason_span } => {
2250                                for ident in node.declared_idents() {
2251                                    self.cx.resolver.append_stripped_cfg_item(
2252                                        self.cx.current_expansion.lint_node_id,
2253                                        ident,
2254                                        reason.clone(),
2255                                        reason_span,
2256                                    )
2257                                }
2258                            }
2259                        }
2260
2261                        Default::default()
2262                    }
2263                    Some(sym::cfg_attr) => {
2264                        self.expand_cfg_attr(&mut node, &attr, pos);
2265                        continue;
2266                    }
2267                    _ => {
2268                        Node::pre_flat_map_node_collect_attr(&self.cfg(), &attr);
2269                        self.collect_attr((attr, pos, derives), node.to_annotatable(), Node::KIND)
2270                            .make_ast::<Node>()
2271                    }
2272                },
2273                None if node.is_mac_call() => {
2274                    let (mac, attrs, add_semicolon) = node.take_mac_call();
2275                    self.check_attributes(&attrs, &mac);
2276                    let mut res = self.collect_bang(mac, Node::KIND).make_ast::<Node>();
2277                    Node::post_flat_map_node_collect_bang(&mut res, add_semicolon);
2278                    res
2279                }
2280                None if let Some((deleg, item)) = node.delegation() => {
2281                    let Some(suffixes) = &deleg.suffixes else {
2282                        let traitless_qself =
2283                            matches!(&deleg.qself, Some(qself) if qself.position == 0);
2284                        let (item, of_trait) = match node.to_annotatable() {
2285                            Annotatable::AssocItem(item, AssocCtxt::Impl { of_trait }) => {
2286                                (item, of_trait)
2287                            }
2288                            ann @ (Annotatable::Item(_)
2289                            | Annotatable::AssocItem(..)
2290                            | Annotatable::Stmt(_)) => {
2291                                let span = ann.span();
2292                                self.cx.dcx().emit_err(GlobDelegationOutsideImpls { span });
2293                                return Default::default();
2294                            }
2295                            _ => unreachable!(),
2296                        };
2297                        if traitless_qself {
2298                            let span = item.span;
2299                            self.cx.dcx().emit_err(GlobDelegationTraitlessQpath { span });
2300                            return Default::default();
2301                        }
2302                        return self
2303                            .collect_glob_delegation(item, of_trait, Node::KIND)
2304                            .make_ast::<Node>();
2305                    };
2306
2307                    let single_delegations = build_single_delegations::<Node>(
2308                        self.cx, deleg, item, suffixes, item.span, false,
2309                    );
2310                    Node::flatten_outputs(single_delegations.map(|item| {
2311                        let mut item = Node::from_item(item);
2312                        assign_id!(self, item.node_id_mut(), || item.walk_flat_map(self))
2313                    }))
2314                }
2315                None => {
2316                    match Node::wrap_flat_map_node_walk_flat_map(node, self, |mut node, this| {
2317                        assign_id!(this, node.node_id_mut(), || node.walk_flat_map(this))
2318                    }) {
2319                        Ok(output) => output,
2320                        Err(returned_node) => {
2321                            node = returned_node;
2322                            continue;
2323                        }
2324                    }
2325                }
2326            };
2327        }
2328    }
2329
2330    fn visit_node<Node: InvocationCollectorNode<OutputTy: Into<Node>> + DummyAstNode>(
2331        &mut self,
2332        node: &mut Node,
2333    ) {
2334        loop {
2335            return match self.take_first_attr(node) {
2336                Some((attr, pos, derives)) => match attr.name() {
2337                    Some(sym::cfg) => {
2338                        let span = attr.span;
2339                        if self.expand_cfg_true(node, attr, pos).as_bool() {
2340                            continue;
2341                        }
2342
2343                        node.expand_cfg_false(self, pos, span);
2344                        continue;
2345                    }
2346                    Some(sym::cfg_attr) => {
2347                        self.expand_cfg_attr(node, &attr, pos);
2348                        continue;
2349                    }
2350                    _ => {
2351                        let n = mem::replace(node, Node::dummy());
2352                        *node = self
2353                            .collect_attr((attr, pos, derives), n.to_annotatable(), Node::KIND)
2354                            .make_ast::<Node>()
2355                            .into()
2356                    }
2357                },
2358                None if node.is_mac_call() => {
2359                    let n = mem::replace(node, Node::dummy());
2360                    let (mac, attrs, _) = n.take_mac_call();
2361                    self.check_attributes(&attrs, &mac);
2362
2363                    *node = self.collect_bang(mac, Node::KIND).make_ast::<Node>().into()
2364                }
2365                None if node.delegation().is_some() => unreachable!(),
2366                None => {
2367                    assign_id!(self, node.node_id_mut(), || node.walk(self))
2368                }
2369            };
2370        }
2371    }
2372}
2373
2374impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
2375    fn flat_map_item(&mut self, node: Box<ast::Item>) -> SmallVec<[Box<ast::Item>; 1]> {
2376        self.flat_map_node(node)
2377    }
2378
2379    fn flat_map_assoc_item(
2380        &mut self,
2381        node: Box<ast::AssocItem>,
2382        ctxt: AssocCtxt,
2383    ) -> SmallVec<[Box<ast::AssocItem>; 1]> {
2384        match ctxt {
2385            AssocCtxt::Trait => self.flat_map_node(AstNodeWrapper::new(node, TraitItemTag)),
2386            AssocCtxt::Impl { of_trait: false } => {
2387                self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag))
2388            }
2389            AssocCtxt::Impl { of_trait: true } => {
2390                self.flat_map_node(AstNodeWrapper::new(node, TraitImplItemTag))
2391            }
2392        }
2393    }
2394
2395    fn flat_map_foreign_item(
2396        &mut self,
2397        node: Box<ast::ForeignItem>,
2398    ) -> SmallVec<[Box<ast::ForeignItem>; 1]> {
2399        self.flat_map_node(node)
2400    }
2401
2402    fn flat_map_variant(&mut self, node: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
2403        self.flat_map_node(node)
2404    }
2405
2406    fn flat_map_where_predicate(
2407        &mut self,
2408        node: ast::WherePredicate,
2409    ) -> SmallVec<[ast::WherePredicate; 1]> {
2410        self.flat_map_node(node)
2411    }
2412
2413    fn flat_map_field_def(&mut self, node: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
2414        self.flat_map_node(node)
2415    }
2416
2417    fn flat_map_pat_field(&mut self, node: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
2418        self.flat_map_node(node)
2419    }
2420
2421    fn flat_map_expr_field(&mut self, node: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
2422        self.flat_map_node(node)
2423    }
2424
2425    fn flat_map_param(&mut self, node: ast::Param) -> SmallVec<[ast::Param; 1]> {
2426        self.flat_map_node(node)
2427    }
2428
2429    fn flat_map_generic_param(
2430        &mut self,
2431        node: ast::GenericParam,
2432    ) -> SmallVec<[ast::GenericParam; 1]> {
2433        self.flat_map_node(node)
2434    }
2435
2436    fn flat_map_arm(&mut self, node: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
2437        self.flat_map_node(node)
2438    }
2439
2440    fn flat_map_stmt(&mut self, node: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
2441        // FIXME: invocations in semicolon-less expressions positions are expanded as expressions,
2442        // changing that requires some compatibility measures.
2443        if node.is_expr() {
2444            // The only way that we can end up with a `MacCall` expression statement,
2445            // (as opposed to a `StmtKind::MacCall`) is if we have a macro as the
2446            // trailing expression in a block (e.g. `fn foo() { my_macro!() }`).
2447            // Record this information, so that we can report a more specific
2448            // `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` lint if needed.
2449            // See #78991 for an investigation of treating macros in this position
2450            // as statements, rather than expressions, during parsing.
2451            return match &node.kind {
2452                StmtKind::Expr(expr)
2453                    if matches!(**expr, ast::Expr { kind: ExprKind::MacCall(..), .. }) =>
2454                {
2455                    self.cx.current_expansion.is_trailing_mac = true;
2456                    // Don't use `assign_id` for this statement - it may get removed
2457                    // entirely due to a `#[cfg]` on the contained expression
2458                    let res = walk_flat_map_stmt(self, node);
2459                    self.cx.current_expansion.is_trailing_mac = false;
2460                    res
2461                }
2462                _ => walk_flat_map_stmt(self, node),
2463            };
2464        }
2465
2466        self.flat_map_node(node)
2467    }
2468
2469    fn visit_crate(&mut self, node: &mut ast::Crate) {
2470        self.visit_node(node)
2471    }
2472
2473    fn visit_ty(&mut self, node: &mut ast::Ty) {
2474        self.visit_node(node)
2475    }
2476
2477    fn visit_pat(&mut self, node: &mut ast::Pat) {
2478        self.visit_node(node)
2479    }
2480
2481    fn visit_expr(&mut self, node: &mut ast::Expr) {
2482        // FIXME: Feature gating is performed inconsistently between `Expr` and `OptExpr`.
2483        if let Some(attr) = node.attrs.first() {
2484            self.cfg().maybe_emit_expr_attr_err(attr);
2485        }
2486        ensure_sufficient_stack(|| self.visit_node(node))
2487    }
2488
2489    fn visit_method_receiver_expr(&mut self, node: &mut ast::Expr) {
2490        self.visit_node(AstNodeWrapper::from_mut(node, MethodReceiverTag))
2491    }
2492
2493    fn filter_map_expr(&mut self, node: Box<ast::Expr>) -> Option<Box<ast::Expr>> {
2494        self.flat_map_node(AstNodeWrapper::new(node, OptExprTag))
2495    }
2496
2497    fn visit_block(&mut self, node: &mut ast::Block) {
2498        let orig_dir_ownership = mem::replace(
2499            &mut self.cx.current_expansion.dir_ownership,
2500            DirOwnership::UnownedViaBlock,
2501        );
2502        walk_block(self, node);
2503        self.cx.current_expansion.dir_ownership = orig_dir_ownership;
2504    }
2505
2506    fn visit_id(&mut self, id: &mut NodeId) {
2507        // We may have already assigned a `NodeId`
2508        // by calling `assign_id`
2509        if self.monotonic && *id == ast::DUMMY_NODE_ID {
2510            *id = self.cx.resolver.next_node_id();
2511        }
2512    }
2513}
2514
2515pub struct ExpansionConfig<'feat> {
2516    pub crate_name: Symbol,
2517    pub features: &'feat Features,
2518    pub recursion_limit: Limit,
2519    pub trace_mac: bool,
2520    /// If false, strip `#[test]` nodes
2521    pub should_test: bool,
2522    /// If true, use verbose debugging for `proc_macro::Span`
2523    pub span_debug: bool,
2524    /// If true, show backtraces for proc-macro panics
2525    pub proc_macro_backtrace: bool,
2526}
2527
2528impl ExpansionConfig<'_> {
2529    pub fn default(crate_name: Symbol, features: &Features) -> ExpansionConfig<'_> {
2530        ExpansionConfig {
2531            crate_name,
2532            features,
2533            // FIXME should this limit be configurable?
2534            recursion_limit: Limit::new(1024),
2535            trace_mac: false,
2536            should_test: false,
2537            span_debug: false,
2538            proc_macro_backtrace: false,
2539        }
2540    }
2541}