2 use crate::config::StripUnconfigured;
4 use crate::hygiene::SyntaxContext;
5 use crate::mbe::macro_rules::annotate_err_with_kind;
6 use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
7 use crate::placeholders::{placeholder, PlaceholderExpander};
10 use rustc_ast::mut_visit::*;
11 use rustc_ast::ptr::P;
13 use rustc_ast::tokenstream::TokenStream;
14 use rustc_ast::visit::{self, AssocCtxt, Visitor};
15 use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs, MacCall};
16 use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
17 use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
18 use rustc_ast_pretty::pprust;
19 use rustc_attr::is_builtin_attr;
20 use rustc_data_structures::map_in_place::MapInPlace;
21 use rustc_data_structures::stack::ensure_sufficient_stack;
22 use rustc_data_structures::sync::Lrc;
23 use rustc_errors::{Applicability, FatalError, PResult};
24 use rustc_feature::Features;
25 use rustc_parse::parser::{
26 AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma,
28 use rustc_parse::validate_attr;
29 use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
30 use rustc_session::lint::BuiltinLintDiagnostics;
31 use rustc_session::parse::{feature_err, ParseSess};
32 use rustc_session::Limit;
33 use rustc_span::symbol::{sym, Ident};
34 use rustc_span::{FileName, LocalExpnId, Span};
36 use smallvec::{smallvec, SmallVec};
37 use std::ops::DerefMut;
38 use std::path::PathBuf;
42 macro_rules! ast_fragments {
44 $($Kind:ident($AstTy:ty) {
46 $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)?
47 $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)?
51 /// A fragment of AST that can be produced by a single macro expansion.
52 /// Can also serve as an input and intermediate result for macro expansion operations.
53 pub enum AstFragment {
54 OptExpr(Option<P<ast::Expr>>),
58 /// "Discriminant" of an AST fragment.
59 #[derive(Copy, Clone, PartialEq, Eq)]
60 pub enum AstFragmentKind {
65 impl AstFragmentKind {
66 pub fn name(self) -> &'static str {
68 AstFragmentKind::OptExpr => "expression",
69 $(AstFragmentKind::$Kind => $kind_name,)*
73 fn make_from<'a>(self, result: Box<dyn MacResult + 'a>) -> Option<AstFragment> {
75 AstFragmentKind::OptExpr =>
76 result.make_expr().map(Some).map(AstFragment::OptExpr),
77 $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
83 pub fn add_placeholders(&mut self, placeholders: &[NodeId]) {
84 if placeholders.is_empty() {
88 $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| {
89 // We are repeating through arguments with `many`, to do that we have to
90 // mention some macro variable from those arguments even if it's not used.
91 macro _repeating($flat_map_ast_elt) {}
92 placeholder(AstFragmentKind::$Kind, *id, None).$make_ast()
94 _ => panic!("unexpected AST fragment kind")
98 pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
100 AstFragment::OptExpr(expr) => expr,
101 _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
105 $(pub fn $make_ast(self) -> $AstTy {
107 AstFragment::$Kind(ast) => ast,
108 _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
112 pub fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) {
114 AstFragment::OptExpr(opt_expr) => {
115 visit_clobber(opt_expr, |opt_expr| {
116 if let Some(expr) = opt_expr {
117 vis.filter_map_expr(expr)
123 $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
124 $($(AstFragment::$Kind(ast) =>
125 ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)*
129 pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
131 AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
132 AstFragment::OptExpr(None) => {}
133 $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
134 $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
135 visitor.$visit_ast_elt(ast_elt, $($args)*);
141 impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> {
142 $(fn $make_ast(self: Box<crate::mbe::macro_rules::ParserAnyMacro<'a>>)
144 Some(self.make(AstFragmentKind::$Kind).$make_ast())
151 Expr(P<ast::Expr>) { "expression"; one fn visit_expr; fn visit_expr; fn make_expr; }
152 Pat(P<ast::Pat>) { "pattern"; one fn visit_pat; fn visit_pat; fn make_pat; }
153 Ty(P<ast::Ty>) { "type"; one fn visit_ty; fn visit_ty; fn make_ty; }
154 Stmts(SmallVec<[ast::Stmt; 1]>) {
155 "statement"; many fn flat_map_stmt; fn visit_stmt(); fn make_stmts;
157 Items(SmallVec<[P<ast::Item>; 1]>) {
158 "item"; many fn flat_map_item; fn visit_item(); fn make_items;
160 TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
162 many fn flat_map_trait_item;
163 fn visit_assoc_item(AssocCtxt::Trait);
166 ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
168 many fn flat_map_impl_item;
169 fn visit_assoc_item(AssocCtxt::Impl);
172 ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
174 many fn flat_map_foreign_item;
175 fn visit_foreign_item();
176 fn make_foreign_items;
178 Arms(SmallVec<[ast::Arm; 1]>) {
179 "match arm"; many fn flat_map_arm; fn visit_arm(); fn make_arms;
181 Fields(SmallVec<[ast::ExprField; 1]>) {
182 "field expression"; many fn flat_map_expr_field; fn visit_expr_field(); fn make_expr_fields;
184 FieldPats(SmallVec<[ast::PatField; 1]>) {
186 many fn flat_map_pat_field;
187 fn visit_pat_field();
190 GenericParams(SmallVec<[ast::GenericParam; 1]>) {
192 many fn flat_map_generic_param;
193 fn visit_generic_param();
194 fn make_generic_params;
196 Params(SmallVec<[ast::Param; 1]>) {
197 "function parameter"; many fn flat_map_param; fn visit_param(); fn make_params;
199 StructFields(SmallVec<[ast::FieldDef; 1]>) {
201 many fn flat_map_field_def;
202 fn visit_field_def();
205 Variants(SmallVec<[ast::Variant; 1]>) {
206 "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
210 pub enum SupportsMacroExpansion {
212 Yes { supports_inner_attrs: bool },
215 impl AstFragmentKind {
216 crate fn dummy(self, span: Span) -> AstFragment {
217 self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment")
220 pub fn supports_macro_expansion(self) -> SupportsMacroExpansion {
222 AstFragmentKind::OptExpr
223 | AstFragmentKind::Expr
224 | AstFragmentKind::Stmts
225 | AstFragmentKind::Ty
226 | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false },
227 AstFragmentKind::Items
228 | AstFragmentKind::TraitItems
229 | AstFragmentKind::ImplItems
230 | AstFragmentKind::ForeignItems => {
231 SupportsMacroExpansion::Yes { supports_inner_attrs: true }
233 AstFragmentKind::Arms
234 | AstFragmentKind::Fields
235 | AstFragmentKind::FieldPats
236 | AstFragmentKind::GenericParams
237 | AstFragmentKind::Params
238 | AstFragmentKind::StructFields
239 | AstFragmentKind::Variants => SupportsMacroExpansion::No,
243 fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(
247 let mut items = items.into_iter();
249 AstFragmentKind::Arms => {
250 AstFragment::Arms(items.map(Annotatable::expect_arm).collect())
252 AstFragmentKind::Fields => {
253 AstFragment::Fields(items.map(Annotatable::expect_expr_field).collect())
255 AstFragmentKind::FieldPats => {
256 AstFragment::FieldPats(items.map(Annotatable::expect_pat_field).collect())
258 AstFragmentKind::GenericParams => {
259 AstFragment::GenericParams(items.map(Annotatable::expect_generic_param).collect())
261 AstFragmentKind::Params => {
262 AstFragment::Params(items.map(Annotatable::expect_param).collect())
264 AstFragmentKind::StructFields => {
265 AstFragment::StructFields(items.map(Annotatable::expect_field_def).collect())
267 AstFragmentKind::Variants => {
268 AstFragment::Variants(items.map(Annotatable::expect_variant).collect())
270 AstFragmentKind::Items => {
271 AstFragment::Items(items.map(Annotatable::expect_item).collect())
273 AstFragmentKind::ImplItems => {
274 AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect())
276 AstFragmentKind::TraitItems => {
277 AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect())
279 AstFragmentKind::ForeignItems => {
280 AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect())
282 AstFragmentKind::Stmts => {
283 AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect())
285 AstFragmentKind::Expr => AstFragment::Expr(
286 items.next().expect("expected exactly one expression").expect_expr(),
288 AstFragmentKind::OptExpr => {
289 AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
291 AstFragmentKind::Pat | AstFragmentKind::Ty => {
292 panic!("patterns and types aren't annotatable")
298 pub struct Invocation {
299 pub kind: InvocationKind,
300 pub fragment_kind: AstFragmentKind,
301 pub expansion_data: ExpansionData,
304 pub enum InvocationKind {
310 attr: ast::Attribute,
311 // Re-insertion position for inert attributes.
314 // Required for resolving derive helper attributes.
323 impl InvocationKind {
324 fn placeholder_visibility(&self) -> Option<ast::Visibility> {
325 // HACK: For unnamed fields placeholders should have the same visibility as the actual
326 // fields because for tuple structs/variants resolve determines visibilities of their
327 // constructor using these field visibilities before attributes on them are are expanded.
328 // The assumption is that the attribute expansion cannot change field visibilities,
329 // and it holds because only inert attributes are supported in this position.
331 InvocationKind::Attr { item: Annotatable::FieldDef(field), .. }
332 | InvocationKind::Derive { item: Annotatable::FieldDef(field), .. }
333 if field.ident.is_none() =>
335 Some(field.vis.clone())
343 pub fn span(&self) -> Span {
345 InvocationKind::Bang { span, .. } => *span,
346 InvocationKind::Attr { attr, .. } => attr.span,
347 InvocationKind::Derive { path, .. } => path.span,
352 pub struct MacroExpander<'a, 'b> {
353 pub cx: &'a mut ExtCtxt<'b>,
354 monotonic: bool, // cf. `cx.monotonic_expander()`
357 impl<'a, 'b> MacroExpander<'a, 'b> {
358 pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
359 MacroExpander { cx, monotonic }
362 // FIXME: Avoid visiting the crate as a `Mod` item,
363 // make crate a first class expansion target instead.
364 pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
365 let file_path = match self.cx.source_map().span_to_filename(krate.span) {
366 FileName::Real(name) => name
368 .expect("attempting to resolve a file path in an external file"),
369 other => PathBuf::from(other.prefer_local().to_string()),
371 let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
372 self.cx.root_path = dir_path.clone();
373 self.cx.current_expansion.module = Rc::new(ModuleData {
374 mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
375 file_path_stack: vec![file_path],
379 let krate_item = AstFragment::Items(smallvec![P(ast::Item {
382 kind: ast::ItemKind::Mod(
384 ModKind::Loaded(krate.items, Inline::Yes, krate.span)
386 ident: Ident::empty(),
387 id: ast::DUMMY_NODE_ID,
388 vis: ast::Visibility {
389 span: krate.span.shrink_to_lo(),
390 kind: ast::VisibilityKind::Public,
396 match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
399 kind: ast::ItemKind::Mod(_, ModKind::Loaded(items, ..)),
406 // Resolution failed so we return an empty expansion
407 krate.attrs = vec![];
408 krate.items = vec![];
410 Some(ast::Item { span, kind, .. }) => {
411 krate.attrs = vec![];
412 krate.items = vec![];
416 "expected crate top-level item to be a module after macro expansion, found {} {}",
417 kind.article(), kind.descr()
420 // FIXME: this workaround issue #84569
424 self.cx.trace_macros_diag();
428 // Recursively expand all macro invocations in this AST fragment.
429 pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
430 let orig_expansion_data = self.cx.current_expansion.clone();
431 let orig_force_mode = self.cx.force_mode;
433 // Collect all macro invocations and replace them with placeholders.
434 let (mut fragment_with_placeholders, mut invocations) =
435 self.collect_invocations(input_fragment, &[]);
437 // Optimization: if we resolve all imports now,
438 // we'll be able to immediately resolve most of imported macros.
439 self.resolve_imports();
441 // Resolve paths in all invocations and produce output expanded fragments for them, but
442 // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
443 // The output fragments also go through expansion recursively until no invocations are left.
444 // Unresolved macros produce dummy outputs as a recovery measure.
445 invocations.reverse();
446 let mut expanded_fragments = Vec::new();
447 let mut undetermined_invocations = Vec::new();
448 let (mut progress, mut force) = (false, !self.monotonic);
450 let Some((invoc, ext)) = invocations.pop() else {
451 self.resolve_imports();
452 if undetermined_invocations.is_empty() {
455 invocations = mem::take(&mut undetermined_invocations);
456 force = !mem::replace(&mut progress, false);
457 if force && self.monotonic {
458 self.cx.sess.delay_span_bug(
459 invocations.last().unwrap().0.span(),
460 "expansion entered force mode without producing any errors",
466 let ext = match ext {
469 let eager_expansion_root = if self.monotonic {
470 invoc.expansion_data.id
472 orig_expansion_data.id
474 match self.cx.resolver.resolve_macro_invocation(
476 eager_expansion_root,
480 Err(Indeterminate) => {
481 // Cannot resolve, will retry this invocation later.
482 undetermined_invocations.push((invoc, None));
489 let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
490 let depth = depth - orig_expansion_data.depth;
491 self.cx.current_expansion = invoc.expansion_data.clone();
492 self.cx.force_mode = force;
494 let fragment_kind = invoc.fragment_kind;
495 let (expanded_fragment, new_invocations) = match self.expand_invoc(invoc, &ext.kind) {
496 ExpandResult::Ready(fragment) => {
497 let mut derive_invocations = Vec::new();
498 let derive_placeholders = self
501 .take_derive_resolutions(expn_id)
503 derive_invocations.reserve(derives.len());
506 .map(|(path, item, _exts)| {
507 // FIXME: Consider using the derive resolutions (`_exts`)
508 // instead of enqueuing the derives to be resolved again later.
509 let expn_id = LocalExpnId::fresh_empty();
510 derive_invocations.push((
512 kind: InvocationKind::Derive { path, item },
514 expansion_data: ExpansionData {
516 ..self.cx.current_expansion.clone()
521 NodeId::placeholder_from_expn_id(expn_id)
525 .unwrap_or_default();
527 let (fragment, collected_invocations) =
528 self.collect_invocations(fragment, &derive_placeholders);
529 // We choose to expand any derive invocations associated with this macro invocation
530 // *before* any macro invocations collected from the output fragment
531 derive_invocations.extend(collected_invocations);
532 (fragment, derive_invocations)
534 ExpandResult::Retry(invoc) => {
538 "expansion entered force mode but is still stuck",
541 // Cannot expand, will retry this invocation later.
542 undetermined_invocations.push((invoc, Some(ext)));
549 if expanded_fragments.len() < depth {
550 expanded_fragments.push(Vec::new());
552 expanded_fragments[depth - 1].push((expn_id, expanded_fragment));
553 invocations.extend(new_invocations.into_iter().rev());
556 self.cx.current_expansion = orig_expansion_data;
557 self.cx.force_mode = orig_force_mode;
559 // Finally incorporate all the expanded macros into the input AST fragment.
560 let mut placeholder_expander = PlaceholderExpander::default();
561 while let Some(expanded_fragments) = expanded_fragments.pop() {
562 for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
564 .add(NodeId::placeholder_from_expn_id(expn_id), expanded_fragment);
567 fragment_with_placeholders.mut_visit_with(&mut placeholder_expander);
568 fragment_with_placeholders
571 fn resolve_imports(&mut self) {
573 self.cx.resolver.resolve_imports();
577 /// Collects all macro invocations reachable at this time in this AST fragment, and replace
578 /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
579 /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
580 /// prepares data for resolving paths of macro invocations.
581 fn collect_invocations(
583 mut fragment: AstFragment,
584 extra_placeholders: &[NodeId],
585 ) -> (AstFragment, Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>) {
586 // Resolve `$crate`s in the fragment for pretty-printing.
587 self.cx.resolver.resolve_dollar_crates();
589 let mut invocations = {
590 let mut collector = InvocationCollector {
591 // Non-derive macro invocations cannot see the results of cfg expansion - they
592 // will either be removed along with the item, or invoked before the cfg/cfg_attr
593 // attribute is expanded. Therefore, we don't need to configure the tokens
594 // Derive macros *can* see the results of cfg-expansion - they are handled
595 // specially in `fully_expand_fragment`
596 cfg: StripUnconfigured {
598 features: self.cx.ecfg.features,
599 config_tokens: false,
602 invocations: Vec::new(),
603 monotonic: self.monotonic,
605 fragment.mut_visit_with(&mut collector);
606 fragment.add_placeholders(extra_placeholders);
607 collector.invocations
613 .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);
615 if self.cx.sess.opts.debugging_opts.incremental_relative_spans {
616 for (invoc, _) in invocations.iter_mut() {
617 let expn_id = invoc.expansion_data.id;
618 let parent_def = self.cx.resolver.invocation_parent(expn_id);
619 let span = match &mut invoc.kind {
620 InvocationKind::Bang { ref mut span, .. } => span,
621 InvocationKind::Attr { attr, .. } => &mut attr.span,
622 InvocationKind::Derive { path, .. } => &mut path.span,
624 *span = span.with_parent(Some(parent_def));
629 (fragment, invocations)
632 fn error_recursion_limit_reached(&mut self) {
633 let expn_data = self.cx.current_expansion.id.expn_data();
634 let suggested_limit = match self.cx.ecfg.recursion_limit {
635 Limit(0) => Limit(2),
641 &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
644 "consider increasing the recursion limit by adding a \
645 `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
646 suggested_limit, self.cx.ecfg.crate_name,
649 self.cx.trace_macros_diag();
652 /// A macro's expansion does not fit in this fragment kind.
653 /// For example, a non-type macro in a type position.
654 fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
656 "non-{kind} macro in {kind} position: {path}",
658 path = pprust::path_to_string(&mac.path),
660 self.cx.span_err(span, &msg);
661 self.cx.trace_macros_diag();
667 ext: &SyntaxExtensionKind,
668 ) -> ExpandResult<AstFragment, Invocation> {
669 let recursion_limit =
670 self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
671 if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
672 if self.cx.reduced_recursion_limit.is_none() {
673 self.error_recursion_limit_reached();
676 // Reduce the recursion limit by half each time it triggers.
677 self.cx.reduced_recursion_limit = Some(recursion_limit / 2);
679 return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span()));
682 let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
683 ExpandResult::Ready(match invoc.kind {
684 InvocationKind::Bang { mac, .. } => match ext {
685 SyntaxExtensionKind::Bang(expander) => {
686 let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) {
687 Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
690 self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
692 SyntaxExtensionKind::LegacyBang(expander) => {
693 let prev = self.cx.current_expansion.prior_type_ascription;
694 self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription;
695 let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
696 let result = if let Some(result) = fragment_kind.make_from(tok_result) {
699 self.error_wrong_fragment_kind(fragment_kind, &mac, span);
700 fragment_kind.dummy(span)
702 self.cx.current_expansion.prior_type_ascription = prev;
707 InvocationKind::Attr { attr, pos, mut item, derives } => match ext {
708 SyntaxExtensionKind::Attr(expander) => {
709 self.gate_proc_macro_input(&item);
710 self.gate_proc_macro_attr_item(span, &item);
711 let mut fake_tokens = false;
712 if let Annotatable::Item(item_inner) = &item {
713 if let ItemKind::Mod(_, mod_kind) = &item_inner.kind {
714 // FIXME: Collect tokens and use them instead of generating
715 // fake ones. These are unstable, so it needs to be
716 // fixed prior to stabilization
717 // Fake tokens when we are invoking an inner attribute, and:
718 fake_tokens = matches!(attr.style, ast::AttrStyle::Inner) &&
719 // We are invoking an attribute on the crate root, or an outline
721 (item_inner.ident.name.is_empty() || !matches!(mod_kind, ast::ModKind::Loaded(_, Inline::Yes, _)));
724 let tokens = if fake_tokens {
725 rustc_parse::fake_token_stream(
726 &self.cx.sess.parse_sess,
727 &item.into_nonterminal(),
730 item.into_tokens(&self.cx.sess.parse_sess)
732 let attr_item = attr.unwrap_normal_item();
733 if let MacArgs::Eq(..) = attr_item.args {
734 self.cx.span_err(span, "key-value macro attributes are not supported");
736 let inner_tokens = attr_item.args.inner_tokens();
737 let tok_result = match expander.expand(self.cx, span, inner_tokens, tokens) {
738 Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
741 self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span)
743 SyntaxExtensionKind::LegacyAttr(expander) => {
744 match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) {
746 let items = match expander.expand(self.cx, span, &meta, item) {
747 ExpandResult::Ready(items) => items,
748 ExpandResult::Retry(item) => {
749 // Reassemble the original invocation for retrying.
750 return ExpandResult::Retry(Invocation {
751 kind: InvocationKind::Attr { attr, pos, item, derives },
756 if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
758 "removing an expression is not supported in this position";
759 self.cx.span_err(span, msg);
760 fragment_kind.dummy(span)
762 fragment_kind.expect_from_annotatables(items)
767 fragment_kind.dummy(span)
771 SyntaxExtensionKind::NonMacroAttr => {
772 self.cx.expanded_inert_attrs.mark(&attr);
773 item.visit_attrs(|attrs| attrs.insert(pos, attr));
774 fragment_kind.expect_from_annotatables(iter::once(item))
778 InvocationKind::Derive { path, item } => match ext {
779 SyntaxExtensionKind::Derive(expander)
780 | SyntaxExtensionKind::LegacyDerive(expander) => {
781 if let SyntaxExtensionKind::Derive(..) = ext {
782 self.gate_proc_macro_input(&item);
784 let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
785 let items = match expander.expand(self.cx, span, &meta, item) {
786 ExpandResult::Ready(items) => items,
787 ExpandResult::Retry(item) => {
788 // Reassemble the original invocation for retrying.
789 return ExpandResult::Retry(Invocation {
790 kind: InvocationKind::Derive { path: meta.path, item },
795 fragment_kind.expect_from_annotatables(items)
802 fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
803 let kind = match item {
805 | Annotatable::TraitItem(_)
806 | Annotatable::ImplItem(_)
807 | Annotatable::ForeignItem(_) => return,
808 Annotatable::Stmt(stmt) => {
809 // Attributes are stable on item statements,
810 // but unstable on all other kinds of statements
816 Annotatable::Expr(_) => "expressions",
818 | Annotatable::ExprField(..)
819 | Annotatable::PatField(..)
820 | Annotatable::GenericParam(..)
821 | Annotatable::Param(..)
822 | Annotatable::FieldDef(..)
823 | Annotatable::Variant(..) => panic!("unexpected annotatable"),
825 if self.cx.ecfg.proc_macro_hygiene() {
829 &self.cx.sess.parse_sess,
830 sym::proc_macro_hygiene,
832 &format!("custom attributes cannot be applied to {}", kind),
837 fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
838 struct GateProcMacroInput<'a> {
839 parse_sess: &'a ParseSess,
842 impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
843 fn visit_item(&mut self, item: &'ast ast::Item) {
845 ast::ItemKind::Mod(_, mod_kind)
846 if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
850 sym::proc_macro_hygiene,
852 "non-inline modules in proc macro input are unstable",
859 visit::walk_item(self, item);
863 if !self.cx.ecfg.proc_macro_hygiene() {
865 .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess });
869 fn parse_ast_fragment(
872 kind: AstFragmentKind,
876 let mut parser = self.cx.new_parser_from_tts(toks);
877 match parse_ast_fragment(&mut parser, kind) {
879 ensure_complete_parse(&mut parser, path, kind.name(), span);
883 if err.span.is_dummy() {
886 annotate_err_with_kind(&mut err, kind, span);
888 self.cx.trace_macros_diag();
895 pub fn parse_ast_fragment<'a>(
896 this: &mut Parser<'a>,
897 kind: AstFragmentKind,
898 ) -> PResult<'a, AstFragment> {
900 AstFragmentKind::Items => {
901 let mut items = SmallVec::new();
902 while let Some(item) = this.parse_item(ForceCollect::No)? {
905 AstFragment::Items(items)
907 AstFragmentKind::TraitItems => {
908 let mut items = SmallVec::new();
909 while let Some(item) = this.parse_trait_item(ForceCollect::No)? {
912 AstFragment::TraitItems(items)
914 AstFragmentKind::ImplItems => {
915 let mut items = SmallVec::new();
916 while let Some(item) = this.parse_impl_item(ForceCollect::No)? {
919 AstFragment::ImplItems(items)
921 AstFragmentKind::ForeignItems => {
922 let mut items = SmallVec::new();
923 while let Some(item) = this.parse_foreign_item(ForceCollect::No)? {
926 AstFragment::ForeignItems(items)
928 AstFragmentKind::Stmts => {
929 let mut stmts = SmallVec::new();
930 // Won't make progress on a `}`.
931 while this.token != token::Eof && this.token != token::CloseDelim(token::Brace) {
932 if let Some(stmt) = this.parse_full_stmt(AttemptLocalParseRecovery::Yes)? {
936 AstFragment::Stmts(stmts)
938 AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
939 AstFragmentKind::OptExpr => {
940 if this.token != token::Eof {
941 AstFragment::OptExpr(Some(this.parse_expr()?))
943 AstFragment::OptExpr(None)
946 AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
947 AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_alt(
952 AstFragmentKind::Arms
953 | AstFragmentKind::Fields
954 | AstFragmentKind::FieldPats
955 | AstFragmentKind::GenericParams
956 | AstFragmentKind::Params
957 | AstFragmentKind::StructFields
958 | AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
962 pub fn ensure_complete_parse<'a>(
963 this: &mut Parser<'a>,
968 if this.token != token::Eof {
969 let token = pprust::token_to_string(&this.token);
970 let msg = format!("macro expansion ignores token `{}` and any following", token);
971 // Avoid emitting backtrace info twice.
972 let def_site_span = this.token.span.with_ctxt(SyntaxContext::root());
973 let mut err = this.struct_span_err(def_site_span, &msg);
974 err.span_label(span, "caused by the macro expansion here");
976 "the usage of `{}!` is likely invalid in {} context",
977 pprust::path_to_string(macro_path),
981 let semi_span = this.sess.source_map().next_point(span);
983 let semi_full_span = semi_span.to(this.sess.source_map().next_point(semi_span));
984 match this.sess.source_map().span_to_snippet(semi_full_span) {
985 Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
988 "you might be missing a semicolon here",
990 Applicability::MaybeIncorrect,
999 struct InvocationCollector<'a, 'b> {
1000 cx: &'a mut ExtCtxt<'b>,
1001 cfg: StripUnconfigured<'a>,
1002 invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
1006 impl<'a, 'b> InvocationCollector<'a, 'b> {
1007 fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
1008 let expn_id = LocalExpnId::fresh_empty();
1009 let vis = kind.placeholder_visibility();
1010 self.invocations.push((
1014 expansion_data: ExpansionData {
1016 depth: self.cx.current_expansion.depth + 1,
1017 ..self.cx.current_expansion.clone()
1022 placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
1025 fn collect_bang(&mut self, mac: ast::MacCall, kind: AstFragmentKind) -> AstFragment {
1026 // cache the macro call span so that it can be
1027 // easily adjusted for incremental compilation
1028 let span = mac.span();
1029 self.collect(kind, InvocationKind::Bang { mac, span })
1034 (attr, pos, derives): (ast::Attribute, usize, Vec<Path>),
1036 kind: AstFragmentKind,
1038 self.collect(kind, InvocationKind::Attr { attr, pos, item, derives })
1041 /// If `item` is an attribute invocation, remove the attribute and return it together with
1042 /// its position and derives following it. We have to collect the derives in order to resolve
1043 /// legacy derive helpers (helpers written before derives that introduce them).
1046 item: &mut impl AstLike,
1047 ) -> Option<(ast::Attribute, usize, Vec<Path>)> {
1048 let mut attr = None;
1050 item.visit_attrs(|attrs| {
1053 .position(|a| !self.cx.expanded_inert_attrs.is_marked(a) && !is_builtin_attr(a))
1055 let attr = attrs.remove(attr_pos);
1056 let following_derives = attrs[attr_pos..]
1058 .filter(|a| a.has_name(sym::derive))
1059 .flat_map(|a| a.meta_item_list().unwrap_or_default())
1060 .filter_map(|nested_meta| match nested_meta {
1061 NestedMetaItem::MetaItem(ast::MetaItem {
1062 kind: MetaItemKind::Word,
1070 (attr, attr_pos, following_derives)
1080 ) -> Result<(bool, MacCall, Vec<ast::Attribute>), ast::Stmt> {
1082 StmtKind::MacCall(mac) => {
1083 let MacCallStmt { mac, style, attrs, .. } = mac.into_inner();
1084 Ok((style == MacStmtStyle::Semicolon, mac, attrs.into()))
1086 StmtKind::Item(item) if matches!(item.kind, ItemKind::MacCall(..)) => {
1087 match item.into_inner() {
1088 ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => {
1089 Ok((mac.args.need_semicolon(), mac, attrs))
1091 _ => unreachable!(),
1094 StmtKind::Semi(expr) if matches!(expr.kind, ast::ExprKind::MacCall(..)) => {
1095 match expr.into_inner() {
1096 ast::Expr { kind: ast::ExprKind::MacCall(mac), attrs, .. } => {
1097 Ok((mac.args.need_semicolon(), mac, attrs.into()))
1099 _ => unreachable!(),
1102 StmtKind::Local(..) | StmtKind::Empty | StmtKind::Item(..) | StmtKind::Semi(..) => {
1105 StmtKind::Expr(..) => unreachable!(),
1109 fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
1110 self.cfg.configure(node)
1113 // Detect use of feature-gated or invalid attributes on macro invocations
1114 // since they will not be detected after macro expansion.
1115 fn check_attributes(&self, attrs: &[ast::Attribute], call: &MacCall) {
1116 let features = self.cx.ecfg.features.unwrap();
1117 let mut attrs = attrs.iter().peekable();
1118 let mut span: Option<Span> = None;
1119 while let Some(attr) = attrs.next() {
1120 rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
1121 validate_attr::check_meta(&self.cx.sess.parse_sess, attr);
1123 let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
1124 span = Some(current_span);
1126 if attrs.peek().map_or(false, |next_attr| next_attr.doc_str().is_some()) {
1130 if attr.is_doc_comment() {
1131 self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
1132 &UNUSED_DOC_COMMENTS,
1134 self.cx.current_expansion.lint_node_id,
1135 "unused doc comment",
1136 BuiltinLintDiagnostics::UnusedDocComment(attr.span),
1138 } else if rustc_attr::is_builtin_attr(attr) {
1139 let attr_name = attr.ident().unwrap().name;
1140 // `#[cfg]` and `#[cfg_attr]` are special - they are
1141 // eagerly evaluated.
1142 if attr_name != sym::cfg && attr_name != sym::cfg_attr {
1143 self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
1146 self.cx.current_expansion.lint_node_id,
1147 &format!("unused attribute `{}`", attr_name),
1148 BuiltinLintDiagnostics::UnusedBuiltinAttribute {
1150 macro_name: pprust::path_to_string(&call.path),
1151 invoc_span: call.path.span,
1160 /// Wraps a call to `noop_visit_*` / `noop_flat_map_*`
1161 /// for an AST node that supports attributes
1162 /// (see the `Annotatable` enum)
1163 /// This method assigns a `NodeId`, and sets that `NodeId`
1164 /// as our current 'lint node id'. If a macro call is found
1165 /// inside this AST node, we will use this AST node's `NodeId`
1166 /// to emit lints associated with that macro (allowing
1167 /// `#[allow]` / `#[deny]` to be applied close to
1168 /// the macro invocation).
1170 /// Do *not* call this for a macro AST node
1171 /// (e.g. `ExprKind::MacCall`) - we cannot emit lints
1172 /// at these AST nodes, since they are removed and
1173 /// replaced with the result of macro expansion.
1175 /// All other `NodeId`s are assigned by `visit_id`.
1176 /// * `self` is the 'self' parameter for the current method,
1177 /// * `id` is a mutable reference to the `NodeId` field
1178 /// of the current AST node.
1179 /// * `closure` is a closure that executes the
1180 /// `noop_visit_*` / `noop_flat_map_*` method
1181 /// for the current AST node.
1182 macro_rules! assign_id {
1183 ($self:ident, $id:expr, $closure:expr) => {{
1184 let old_id = $self.cx.current_expansion.lint_node_id;
1185 if $self.monotonic {
1186 debug_assert_eq!(*$id, ast::DUMMY_NODE_ID);
1187 let new_id = $self.cx.resolver.next_node_id();
1189 $self.cx.current_expansion.lint_node_id = new_id;
1191 let ret = ($closure)();
1192 $self.cx.current_expansion.lint_node_id = old_id;
1197 impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1198 fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
1199 self.cfg.configure_expr(expr);
1200 visit_clobber(expr.deref_mut(), |mut expr| {
1201 if let Some(attr) = self.take_first_attr(&mut expr) {
1202 // Collect the invoc regardless of whether or not attributes are permitted here
1203 // expansion will eat the attribute so it won't error later.
1204 self.cfg.maybe_emit_expr_attr_err(&attr.0);
1206 // AstFragmentKind::Expr requires the macro to emit an expression.
1208 .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::Expr)
1213 if let ast::ExprKind::MacCall(mac) = expr.kind {
1214 self.check_attributes(&expr.attrs, &mac);
1215 self.collect_bang(mac, AstFragmentKind::Expr).make_expr().into_inner()
1217 assign_id!(self, &mut expr.id, || {
1218 ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self));
1225 fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
1226 let mut arm = configure!(self, arm);
1228 if let Some(attr) = self.take_first_attr(&mut arm) {
1230 .collect_attr(attr, Annotatable::Arm(arm), AstFragmentKind::Arms)
1234 assign_id!(self, &mut arm.id, || noop_flat_map_arm(arm, self))
1237 fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
1238 let mut field = configure!(self, field);
1240 if let Some(attr) = self.take_first_attr(&mut field) {
1242 .collect_attr(attr, Annotatable::ExprField(field), AstFragmentKind::Fields)
1243 .make_expr_fields();
1246 assign_id!(self, &mut field.id, || noop_flat_map_expr_field(field, self))
1249 fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
1250 let mut fp = configure!(self, fp);
1252 if let Some(attr) = self.take_first_attr(&mut fp) {
1254 .collect_attr(attr, Annotatable::PatField(fp), AstFragmentKind::FieldPats)
1258 assign_id!(self, &mut fp.id, || noop_flat_map_pat_field(fp, self))
1261 fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
1262 let mut p = configure!(self, p);
1264 if let Some(attr) = self.take_first_attr(&mut p) {
1266 .collect_attr(attr, Annotatable::Param(p), AstFragmentKind::Params)
1270 assign_id!(self, &mut p.id, || noop_flat_map_param(p, self))
1273 fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
1274 let mut sf = configure!(self, sf);
1276 if let Some(attr) = self.take_first_attr(&mut sf) {
1278 .collect_attr(attr, Annotatable::FieldDef(sf), AstFragmentKind::StructFields)
1282 assign_id!(self, &mut sf.id, || noop_flat_map_field_def(sf, self))
1285 fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
1286 let mut variant = configure!(self, variant);
1288 if let Some(attr) = self.take_first_attr(&mut variant) {
1290 .collect_attr(attr, Annotatable::Variant(variant), AstFragmentKind::Variants)
1294 assign_id!(self, &mut variant.id, || noop_flat_map_variant(variant, self))
1297 fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
1298 let expr = configure!(self, expr);
1299 expr.filter_map(|mut expr| {
1300 if let Some(attr) = self.take_first_attr(&mut expr) {
1301 self.cfg.maybe_emit_expr_attr_err(&attr.0);
1304 .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr)
1306 .map(|expr| expr.into_inner());
1309 if let ast::ExprKind::MacCall(mac) = expr.kind {
1310 self.check_attributes(&expr.attrs, &mac);
1311 self.collect_bang(mac, AstFragmentKind::OptExpr)
1313 .map(|expr| expr.into_inner())
1315 assign_id!(self, &mut expr.id, || {
1317 noop_visit_expr(&mut expr, self);
1325 fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
1327 PatKind::MacCall(_) => {}
1328 _ => return noop_visit_pat(pat, self),
1331 visit_clobber(pat, |mut pat| match mem::replace(&mut pat.kind, PatKind::Wild) {
1332 PatKind::MacCall(mac) => self.collect_bang(mac, AstFragmentKind::Pat).make_pat(),
1333 _ => unreachable!(),
1337 fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
1338 let mut stmt = configure!(self, stmt);
1340 // We pull macro invocations (both attributes and fn-like macro calls) out of their
1341 // `StmtKind`s and treat them as statement macro invocations, not as items or expressions.
1342 // FIXME: invocations in semicolon-less expressions positions are expanded as expressions,
1343 // changing that requires some compatibility measures.
1344 let mut stmt = if !stmt.is_expr() {
1345 if let Some(attr) = self.take_first_attr(&mut stmt) {
1347 .collect_attr(attr, Annotatable::Stmt(P(stmt)), AstFragmentKind::Stmts)
1351 match self.take_stmt_bang(stmt) {
1352 Ok((add_semicolon, mac, attrs)) => {
1353 self.check_attributes(&attrs, &mac);
1354 let mut stmts = self.collect_bang(mac, AstFragmentKind::Stmts).make_stmts();
1356 // If this is a macro invocation with a semicolon, then apply that
1357 // semicolon to the final statement produced by expansion.
1359 if let Some(stmt) = stmts.pop() {
1360 stmts.push(stmt.add_trailing_semicolon());
1372 // The only way that we can end up with a `MacCall` expression statement,
1373 // (as opposed to a `StmtKind::MacCall`) is if we have a macro as the
1374 // traiing expression in a block (e.g. `fn foo() { my_macro!() }`).
1375 // Record this information, so that we can report a more specific
1376 // `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` lint if needed.
1377 // See #78991 for an investigation of treating macros in this position
1378 // as statements, rather than expressions, during parsing.
1379 let res = match &stmt.kind {
1380 StmtKind::Expr(expr)
1381 if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) =>
1383 self.cx.current_expansion.is_trailing_mac = true;
1384 // Don't use `assign_id` for this statement - it may get removed
1385 // entirely due to a `#[cfg]` on the contained expression
1386 noop_flat_map_stmt(stmt, self)
1388 _ => assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self)),
1390 self.cx.current_expansion.is_trailing_mac = false;
1394 fn visit_block(&mut self, block: &mut P<Block>) {
1395 let orig_dir_ownership = mem::replace(
1396 &mut self.cx.current_expansion.dir_ownership,
1397 DirOwnership::UnownedViaBlock,
1399 noop_visit_block(block, self);
1400 self.cx.current_expansion.dir_ownership = orig_dir_ownership;
1403 fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
1404 let mut item = configure!(self, item);
1406 if let Some(attr) = self.take_first_attr(&mut item) {
1408 .collect_attr(attr, Annotatable::Item(item), AstFragmentKind::Items)
1412 let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
1413 let ident = item.ident;
1414 let span = item.span;
1417 ast::ItemKind::MacCall(ref mac) => {
1418 self.check_attributes(&attrs, &mac);
1420 item.and_then(|item| match item.kind {
1421 ItemKind::MacCall(mac) => {
1422 self.collect_bang(mac, AstFragmentKind::Items).make_items()
1424 _ => unreachable!(),
1427 ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::empty() => {
1428 let (file_path, dir_path, dir_ownership) = match mod_kind {
1429 ModKind::Loaded(_, inline, _) => {
1430 // Inline `mod foo { ... }`, but we still need to push directories.
1431 let (dir_path, dir_ownership) = mod_dir_path(
1435 &self.cx.current_expansion.module,
1436 self.cx.current_expansion.dir_ownership,
1440 (None, dir_path, dir_ownership)
1442 ModKind::Unloaded => {
1443 // We have an outline `mod foo;` so we need to parse the file.
1444 let old_attrs_len = attrs.len();
1445 let ParsedExternalMod {
1451 } = parse_external_mod(
1455 &self.cx.current_expansion.module,
1456 self.cx.current_expansion.dir_ownership,
1460 if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
1461 (attrs, items) = extern_mod_loaded(ident, attrs, items, inner_span);
1464 *mod_kind = ModKind::Loaded(items, Inline::No, inner_span);
1466 if item.attrs.len() > old_attrs_len {
1467 // If we loaded an out-of-line module and added some inner attributes,
1468 // then we need to re-configure it and re-collect attributes for
1469 // resolution and expansion.
1470 item = configure!(self, item);
1472 if let Some(attr) = self.take_first_attr(&mut item) {
1476 Annotatable::Item(item),
1477 AstFragmentKind::Items,
1482 (Some(file_path), dir_path, dir_ownership)
1486 // Set the module info before we flat map.
1487 let mut module = self.cx.current_expansion.module.with_dir_path(dir_path);
1488 module.mod_path.push(ident);
1489 if let Some(file_path) = file_path {
1490 module.file_path_stack.push(file_path);
1494 mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
1495 let orig_dir_ownership =
1496 mem::replace(&mut self.cx.current_expansion.dir_ownership, dir_ownership);
1498 let result = assign_id!(self, &mut item.id, || noop_flat_map_item(item, self));
1500 // Restore the module info.
1501 self.cx.current_expansion.dir_ownership = orig_dir_ownership;
1502 self.cx.current_expansion.module = orig_module;
1508 // The crate root is special - don't assign an ID to it.
1509 if !(matches!(item.kind, ast::ItemKind::Mod(..)) && ident == Ident::empty()) {
1510 assign_id!(self, &mut item.id, || noop_flat_map_item(item, self))
1512 noop_flat_map_item(item, self)
1518 fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
1519 let mut item = configure!(self, item);
1521 if let Some(attr) = self.take_first_attr(&mut item) {
1523 .collect_attr(attr, Annotatable::TraitItem(item), AstFragmentKind::TraitItems)
1524 .make_trait_items();
1528 ast::AssocItemKind::MacCall(ref mac) => {
1529 self.check_attributes(&item.attrs, &mac);
1530 item.and_then(|item| match item.kind {
1531 ast::AssocItemKind::MacCall(mac) => {
1532 self.collect_bang(mac, AstFragmentKind::TraitItems).make_trait_items()
1534 _ => unreachable!(),
1538 assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self))
1543 fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
1544 let mut item = configure!(self, item);
1546 if let Some(attr) = self.take_first_attr(&mut item) {
1548 .collect_attr(attr, Annotatable::ImplItem(item), AstFragmentKind::ImplItems)
1553 ast::AssocItemKind::MacCall(ref mac) => {
1554 self.check_attributes(&item.attrs, &mac);
1555 item.and_then(|item| match item.kind {
1556 ast::AssocItemKind::MacCall(mac) => {
1557 self.collect_bang(mac, AstFragmentKind::ImplItems).make_impl_items()
1559 _ => unreachable!(),
1563 assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self))
1568 fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
1570 ast::TyKind::MacCall(_) => {}
1571 _ => return noop_visit_ty(ty, self),
1574 visit_clobber(ty, |mut ty| match mem::replace(&mut ty.kind, ast::TyKind::Err) {
1575 ast::TyKind::MacCall(mac) => self.collect_bang(mac, AstFragmentKind::Ty).make_ty(),
1576 _ => unreachable!(),
1580 fn flat_map_foreign_item(
1582 foreign_item: P<ast::ForeignItem>,
1583 ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
1584 let mut foreign_item = configure!(self, foreign_item);
1586 if let Some(attr) = self.take_first_attr(&mut foreign_item) {
1590 Annotatable::ForeignItem(foreign_item),
1591 AstFragmentKind::ForeignItems,
1593 .make_foreign_items();
1596 match foreign_item.kind {
1597 ast::ForeignItemKind::MacCall(ref mac) => {
1598 self.check_attributes(&foreign_item.attrs, &mac);
1599 foreign_item.and_then(|item| match item.kind {
1600 ast::ForeignItemKind::MacCall(mac) => {
1601 self.collect_bang(mac, AstFragmentKind::ForeignItems).make_foreign_items()
1603 _ => unreachable!(),
1607 assign_id!(self, &mut foreign_item.id, || noop_flat_map_foreign_item(
1615 fn flat_map_generic_param(
1617 param: ast::GenericParam,
1618 ) -> SmallVec<[ast::GenericParam; 1]> {
1619 let mut param = configure!(self, param);
1621 if let Some(attr) = self.take_first_attr(&mut param) {
1625 Annotatable::GenericParam(param),
1626 AstFragmentKind::GenericParams,
1628 .make_generic_params();
1631 assign_id!(self, &mut param.id, || noop_flat_map_generic_param(param, self))
1634 fn visit_id(&mut self, id: &mut ast::NodeId) {
1635 // We may have already assigned a `NodeId`
1636 // by calling `assign_id`
1637 if self.monotonic && *id == ast::DUMMY_NODE_ID {
1638 *id = self.cx.resolver.next_node_id();
1643 pub struct ExpansionConfig<'feat> {
1644 pub crate_name: String,
1645 pub features: Option<&'feat Features>,
1646 pub recursion_limit: Limit,
1647 pub trace_mac: bool,
1648 pub should_test: bool, // If false, strip `#[test]` nodes
1649 pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
1650 pub proc_macro_backtrace: bool, // If true, show backtraces for proc-macro panics
1653 impl<'feat> ExpansionConfig<'feat> {
1654 pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1658 recursion_limit: Limit::new(1024),
1662 proc_macro_backtrace: false,
1666 fn proc_macro_hygiene(&self) -> bool {
1667 self.features.map_or(false, |features| features.proc_macro_hygiene)