rustc_expand/
expand.rs

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