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