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};
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, 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;
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;
208 Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; }
211 pub enum SupportsMacroExpansion {
213 Yes { supports_inner_attrs: bool },
216 impl AstFragmentKind {
217 crate fn dummy(self, span: Span) -> AstFragment {
218 self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment")
221 pub fn supports_macro_expansion(self) -> SupportsMacroExpansion {
223 AstFragmentKind::OptExpr
224 | AstFragmentKind::Expr
225 | AstFragmentKind::Stmts
226 | AstFragmentKind::Ty
227 | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false },
228 AstFragmentKind::Items
229 | AstFragmentKind::TraitItems
230 | AstFragmentKind::ImplItems
231 | AstFragmentKind::ForeignItems
232 | AstFragmentKind::Crate => 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::Crate => {
292 AstFragment::Crate(items.next().expect("expected exactly one crate").expect_crate())
294 AstFragmentKind::Pat | AstFragmentKind::Ty => {
295 panic!("patterns and types aren't annotatable")
301 pub struct Invocation {
302 pub kind: InvocationKind,
303 pub fragment_kind: AstFragmentKind,
304 pub expansion_data: ExpansionData,
307 pub enum InvocationKind {
313 attr: ast::Attribute,
314 // Re-insertion position for inert attributes.
317 // Required for resolving derive helper attributes.
326 impl InvocationKind {
327 fn placeholder_visibility(&self) -> Option<ast::Visibility> {
328 // HACK: For unnamed fields placeholders should have the same visibility as the actual
329 // fields because for tuple structs/variants resolve determines visibilities of their
330 // constructor using these field visibilities before attributes on them are are expanded.
331 // The assumption is that the attribute expansion cannot change field visibilities,
332 // and it holds because only inert attributes are supported in this position.
334 InvocationKind::Attr { item: Annotatable::FieldDef(field), .. }
335 | InvocationKind::Derive { item: Annotatable::FieldDef(field), .. }
336 if field.ident.is_none() =>
338 Some(field.vis.clone())
346 pub fn span(&self) -> Span {
348 InvocationKind::Bang { span, .. } => *span,
349 InvocationKind::Attr { attr, .. } => attr.span,
350 InvocationKind::Derive { path, .. } => path.span,
355 pub struct MacroExpander<'a, 'b> {
356 pub cx: &'a mut ExtCtxt<'b>,
357 monotonic: bool, // cf. `cx.monotonic_expander()`
360 impl<'a, 'b> MacroExpander<'a, 'b> {
361 pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
362 MacroExpander { cx, monotonic }
365 pub fn expand_crate(&mut self, krate: ast::Crate) -> ast::Crate {
366 let file_path = match self.cx.source_map().span_to_filename(krate.span) {
367 FileName::Real(name) => name
369 .expect("attempting to resolve a file path in an external file"),
370 other => PathBuf::from(other.prefer_local().to_string()),
372 let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
373 self.cx.root_path = dir_path.clone();
374 self.cx.current_expansion.module = Rc::new(ModuleData {
375 mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
376 file_path_stack: vec![file_path],
379 let krate = self.fully_expand_fragment(AstFragment::Crate(krate)).make_crate();
380 assert_eq!(krate.id, ast::CRATE_NODE_ID);
381 self.cx.trace_macros_diag();
385 // Recursively expand all macro invocations in this AST fragment.
386 pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
387 let orig_expansion_data = self.cx.current_expansion.clone();
388 let orig_force_mode = self.cx.force_mode;
390 // Collect all macro invocations and replace them with placeholders.
391 let (mut fragment_with_placeholders, mut invocations) =
392 self.collect_invocations(input_fragment, &[]);
394 // Optimization: if we resolve all imports now,
395 // we'll be able to immediately resolve most of imported macros.
396 self.resolve_imports();
398 // Resolve paths in all invocations and produce output expanded fragments for them, but
399 // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
400 // The output fragments also go through expansion recursively until no invocations are left.
401 // Unresolved macros produce dummy outputs as a recovery measure.
402 invocations.reverse();
403 let mut expanded_fragments = Vec::new();
404 let mut undetermined_invocations = Vec::new();
405 let (mut progress, mut force) = (false, !self.monotonic);
407 let Some((invoc, ext)) = invocations.pop() else {
408 self.resolve_imports();
409 if undetermined_invocations.is_empty() {
412 invocations = mem::take(&mut undetermined_invocations);
413 force = !mem::replace(&mut progress, false);
414 if force && self.monotonic {
415 self.cx.sess.delay_span_bug(
416 invocations.last().unwrap().0.span(),
417 "expansion entered force mode without producing any errors",
423 let ext = match ext {
426 let eager_expansion_root = if self.monotonic {
427 invoc.expansion_data.id
429 orig_expansion_data.id
431 match self.cx.resolver.resolve_macro_invocation(
433 eager_expansion_root,
437 Err(Indeterminate) => {
438 // Cannot resolve, will retry this invocation later.
439 undetermined_invocations.push((invoc, None));
446 let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
447 let depth = depth - orig_expansion_data.depth;
448 self.cx.current_expansion = invoc.expansion_data.clone();
449 self.cx.force_mode = force;
451 let fragment_kind = invoc.fragment_kind;
452 let (expanded_fragment, new_invocations) = match self.expand_invoc(invoc, &ext.kind) {
453 ExpandResult::Ready(fragment) => {
454 let mut derive_invocations = Vec::new();
455 let derive_placeholders = self
458 .take_derive_resolutions(expn_id)
460 derive_invocations.reserve(derives.len());
463 .map(|(path, item, _exts)| {
464 // FIXME: Consider using the derive resolutions (`_exts`)
465 // instead of enqueuing the derives to be resolved again later.
466 let expn_id = LocalExpnId::fresh_empty();
467 derive_invocations.push((
469 kind: InvocationKind::Derive { path, item },
471 expansion_data: ExpansionData {
473 ..self.cx.current_expansion.clone()
478 NodeId::placeholder_from_expn_id(expn_id)
482 .unwrap_or_default();
484 let (fragment, collected_invocations) =
485 self.collect_invocations(fragment, &derive_placeholders);
486 // We choose to expand any derive invocations associated with this macro invocation
487 // *before* any macro invocations collected from the output fragment
488 derive_invocations.extend(collected_invocations);
489 (fragment, derive_invocations)
491 ExpandResult::Retry(invoc) => {
495 "expansion entered force mode but is still stuck",
498 // Cannot expand, will retry this invocation later.
499 undetermined_invocations.push((invoc, Some(ext)));
506 if expanded_fragments.len() < depth {
507 expanded_fragments.push(Vec::new());
509 expanded_fragments[depth - 1].push((expn_id, expanded_fragment));
510 invocations.extend(new_invocations.into_iter().rev());
513 self.cx.current_expansion = orig_expansion_data;
514 self.cx.force_mode = orig_force_mode;
516 // Finally incorporate all the expanded macros into the input AST fragment.
517 let mut placeholder_expander = PlaceholderExpander::default();
518 while let Some(expanded_fragments) = expanded_fragments.pop() {
519 for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
521 .add(NodeId::placeholder_from_expn_id(expn_id), expanded_fragment);
524 fragment_with_placeholders.mut_visit_with(&mut placeholder_expander);
525 fragment_with_placeholders
528 fn resolve_imports(&mut self) {
530 self.cx.resolver.resolve_imports();
534 /// Collects all macro invocations reachable at this time in this AST fragment, and replace
535 /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
536 /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
537 /// prepares data for resolving paths of macro invocations.
538 fn collect_invocations(
540 mut fragment: AstFragment,
541 extra_placeholders: &[NodeId],
542 ) -> (AstFragment, Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>) {
543 // Resolve `$crate`s in the fragment for pretty-printing.
544 self.cx.resolver.resolve_dollar_crates();
546 let mut invocations = {
547 let mut collector = InvocationCollector {
548 // Non-derive macro invocations cannot see the results of cfg expansion - they
549 // will either be removed along with the item, or invoked before the cfg/cfg_attr
550 // attribute is expanded. Therefore, we don't need to configure the tokens
551 // Derive macros *can* see the results of cfg-expansion - they are handled
552 // specially in `fully_expand_fragment`
553 cfg: StripUnconfigured {
555 features: self.cx.ecfg.features,
556 config_tokens: false,
559 invocations: Vec::new(),
560 monotonic: self.monotonic,
562 fragment.mut_visit_with(&mut collector);
563 fragment.add_placeholders(extra_placeholders);
564 collector.invocations
570 .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);
572 if self.cx.sess.opts.debugging_opts.incremental_relative_spans {
573 for (invoc, _) in invocations.iter_mut() {
574 let expn_id = invoc.expansion_data.id;
575 let parent_def = self.cx.resolver.invocation_parent(expn_id);
576 let span = match &mut invoc.kind {
577 InvocationKind::Bang { ref mut span, .. } => span,
578 InvocationKind::Attr { attr, .. } => &mut attr.span,
579 InvocationKind::Derive { path, .. } => &mut path.span,
581 *span = span.with_parent(Some(parent_def));
586 (fragment, invocations)
589 fn error_recursion_limit_reached(&mut self) {
590 let expn_data = self.cx.current_expansion.id.expn_data();
591 let suggested_limit = match self.cx.ecfg.recursion_limit {
592 Limit(0) => Limit(2),
598 &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
601 "consider increasing the recursion limit by adding a \
602 `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
603 suggested_limit, self.cx.ecfg.crate_name,
606 self.cx.trace_macros_diag();
609 /// A macro's expansion does not fit in this fragment kind.
610 /// For example, a non-type macro in a type position.
611 fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
613 "non-{kind} macro in {kind} position: {path}",
615 path = pprust::path_to_string(&mac.path),
617 self.cx.span_err(span, &msg);
618 self.cx.trace_macros_diag();
624 ext: &SyntaxExtensionKind,
625 ) -> ExpandResult<AstFragment, Invocation> {
626 let recursion_limit =
627 self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
628 if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
629 if self.cx.reduced_recursion_limit.is_none() {
630 self.error_recursion_limit_reached();
633 // Reduce the recursion limit by half each time it triggers.
634 self.cx.reduced_recursion_limit = Some(recursion_limit / 2);
636 return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span()));
639 let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
640 ExpandResult::Ready(match invoc.kind {
641 InvocationKind::Bang { mac, .. } => match ext {
642 SyntaxExtensionKind::Bang(expander) => {
643 let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) {
644 Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
647 self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
649 SyntaxExtensionKind::LegacyBang(expander) => {
650 let prev = self.cx.current_expansion.prior_type_ascription;
651 self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription;
652 let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
653 let result = if let Some(result) = fragment_kind.make_from(tok_result) {
656 self.error_wrong_fragment_kind(fragment_kind, &mac, span);
657 fragment_kind.dummy(span)
659 self.cx.current_expansion.prior_type_ascription = prev;
664 InvocationKind::Attr { attr, pos, mut item, derives } => match ext {
665 SyntaxExtensionKind::Attr(expander) => {
666 self.gate_proc_macro_input(&item);
667 self.gate_proc_macro_attr_item(span, &item);
668 let tokens = match &item {
669 // FIXME: Collect tokens and use them instead of generating
670 // fake ones. These are unstable, so it needs to be
671 // fixed prior to stabilization
672 // Fake tokens when we are invoking an inner attribute, and
673 // we are invoking it on an out-of-line module or crate.
674 Annotatable::Crate(krate) => rustc_parse::fake_token_stream_for_crate(
675 &self.cx.sess.parse_sess,
678 Annotatable::Item(item_inner)
679 if matches!(attr.style, ast::AttrStyle::Inner)
684 ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _),
688 rustc_parse::fake_token_stream(
689 &self.cx.sess.parse_sess,
690 &item.into_nonterminal(),
693 _ => item.into_tokens(&self.cx.sess.parse_sess),
695 let attr_item = attr.unwrap_normal_item();
696 if let MacArgs::Eq(..) = attr_item.args {
697 self.cx.span_err(span, "key-value macro attributes are not supported");
699 let inner_tokens = attr_item.args.inner_tokens();
700 let tok_result = match expander.expand(self.cx, span, inner_tokens, tokens) {
701 Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
704 self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span)
706 SyntaxExtensionKind::LegacyAttr(expander) => {
707 match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) {
709 let items = match expander.expand(self.cx, span, &meta, item) {
710 ExpandResult::Ready(items) => items,
711 ExpandResult::Retry(item) => {
712 // Reassemble the original invocation for retrying.
713 return ExpandResult::Retry(Invocation {
714 kind: InvocationKind::Attr { attr, pos, item, derives },
719 if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
721 "removing an expression is not supported in this position";
722 self.cx.span_err(span, msg);
723 fragment_kind.dummy(span)
725 fragment_kind.expect_from_annotatables(items)
730 fragment_kind.dummy(span)
734 SyntaxExtensionKind::NonMacroAttr => {
735 self.cx.expanded_inert_attrs.mark(&attr);
736 item.visit_attrs(|attrs| attrs.insert(pos, attr));
737 fragment_kind.expect_from_annotatables(iter::once(item))
741 InvocationKind::Derive { path, item } => match ext {
742 SyntaxExtensionKind::Derive(expander)
743 | SyntaxExtensionKind::LegacyDerive(expander) => {
744 if let SyntaxExtensionKind::Derive(..) = ext {
745 self.gate_proc_macro_input(&item);
747 let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
748 let items = match expander.expand(self.cx, span, &meta, item) {
749 ExpandResult::Ready(items) => items,
750 ExpandResult::Retry(item) => {
751 // Reassemble the original invocation for retrying.
752 return ExpandResult::Retry(Invocation {
753 kind: InvocationKind::Derive { path: meta.path, item },
758 fragment_kind.expect_from_annotatables(items)
765 fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
766 let kind = match item {
768 | Annotatable::TraitItem(_)
769 | Annotatable::ImplItem(_)
770 | Annotatable::ForeignItem(_)
771 | Annotatable::Crate(..) => return,
772 Annotatable::Stmt(stmt) => {
773 // Attributes are stable on item statements,
774 // but unstable on all other kinds of statements
780 Annotatable::Expr(_) => "expressions",
782 | Annotatable::ExprField(..)
783 | Annotatable::PatField(..)
784 | Annotatable::GenericParam(..)
785 | Annotatable::Param(..)
786 | Annotatable::FieldDef(..)
787 | Annotatable::Variant(..) => panic!("unexpected annotatable"),
789 if self.cx.ecfg.proc_macro_hygiene() {
793 &self.cx.sess.parse_sess,
794 sym::proc_macro_hygiene,
796 &format!("custom attributes cannot be applied to {}", kind),
801 fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
802 struct GateProcMacroInput<'a> {
803 parse_sess: &'a ParseSess,
806 impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
807 fn visit_item(&mut self, item: &'ast ast::Item) {
809 ast::ItemKind::Mod(_, mod_kind)
810 if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
814 sym::proc_macro_hygiene,
816 "non-inline modules in proc macro input are unstable",
823 visit::walk_item(self, item);
827 if !self.cx.ecfg.proc_macro_hygiene() {
829 .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess });
833 fn parse_ast_fragment(
836 kind: AstFragmentKind,
840 let mut parser = self.cx.new_parser_from_tts(toks);
841 match parse_ast_fragment(&mut parser, kind) {
843 ensure_complete_parse(&mut parser, path, kind.name(), span);
847 if err.span.is_dummy() {
850 annotate_err_with_kind(&mut err, kind, span);
852 self.cx.trace_macros_diag();
859 pub fn parse_ast_fragment<'a>(
860 this: &mut Parser<'a>,
861 kind: AstFragmentKind,
862 ) -> PResult<'a, AstFragment> {
864 AstFragmentKind::Items => {
865 let mut items = SmallVec::new();
866 while let Some(item) = this.parse_item(ForceCollect::No)? {
869 AstFragment::Items(items)
871 AstFragmentKind::TraitItems => {
872 let mut items = SmallVec::new();
873 while let Some(item) = this.parse_trait_item(ForceCollect::No)? {
876 AstFragment::TraitItems(items)
878 AstFragmentKind::ImplItems => {
879 let mut items = SmallVec::new();
880 while let Some(item) = this.parse_impl_item(ForceCollect::No)? {
883 AstFragment::ImplItems(items)
885 AstFragmentKind::ForeignItems => {
886 let mut items = SmallVec::new();
887 while let Some(item) = this.parse_foreign_item(ForceCollect::No)? {
890 AstFragment::ForeignItems(items)
892 AstFragmentKind::Stmts => {
893 let mut stmts = SmallVec::new();
894 // Won't make progress on a `}`.
895 while this.token != token::Eof && this.token != token::CloseDelim(token::Brace) {
896 if let Some(stmt) = this.parse_full_stmt(AttemptLocalParseRecovery::Yes)? {
900 AstFragment::Stmts(stmts)
902 AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
903 AstFragmentKind::OptExpr => {
904 if this.token != token::Eof {
905 AstFragment::OptExpr(Some(this.parse_expr()?))
907 AstFragment::OptExpr(None)
910 AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
911 AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_alt(
916 AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?),
917 AstFragmentKind::Arms
918 | AstFragmentKind::Fields
919 | AstFragmentKind::FieldPats
920 | AstFragmentKind::GenericParams
921 | AstFragmentKind::Params
922 | AstFragmentKind::StructFields
923 | AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
927 pub fn ensure_complete_parse<'a>(
928 this: &mut Parser<'a>,
933 if this.token != token::Eof {
934 let token = pprust::token_to_string(&this.token);
935 let msg = format!("macro expansion ignores token `{}` and any following", token);
936 // Avoid emitting backtrace info twice.
937 let def_site_span = this.token.span.with_ctxt(SyntaxContext::root());
938 let mut err = this.struct_span_err(def_site_span, &msg);
939 err.span_label(span, "caused by the macro expansion here");
941 "the usage of `{}!` is likely invalid in {} context",
942 pprust::path_to_string(macro_path),
946 let semi_span = this.sess.source_map().next_point(span);
948 let semi_full_span = semi_span.to(this.sess.source_map().next_point(semi_span));
949 match this.sess.source_map().span_to_snippet(semi_full_span) {
950 Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
953 "you might be missing a semicolon here",
955 Applicability::MaybeIncorrect,
964 struct InvocationCollector<'a, 'b> {
965 cx: &'a mut ExtCtxt<'b>,
966 cfg: StripUnconfigured<'a>,
967 invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
971 impl<'a, 'b> InvocationCollector<'a, 'b> {
972 fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
973 let expn_id = LocalExpnId::fresh_empty();
974 let vis = kind.placeholder_visibility();
975 self.invocations.push((
979 expansion_data: ExpansionData {
981 depth: self.cx.current_expansion.depth + 1,
982 ..self.cx.current_expansion.clone()
987 placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
990 fn collect_bang(&mut self, mac: ast::MacCall, kind: AstFragmentKind) -> AstFragment {
991 // cache the macro call span so that it can be
992 // easily adjusted for incremental compilation
993 let span = mac.span();
994 self.collect(kind, InvocationKind::Bang { mac, span })
999 (attr, pos, derives): (ast::Attribute, usize, Vec<Path>),
1001 kind: AstFragmentKind,
1003 self.collect(kind, InvocationKind::Attr { attr, pos, item, derives })
1006 /// If `item` is an attribute invocation, remove the attribute and return it together with
1007 /// its position and derives following it. We have to collect the derives in order to resolve
1008 /// legacy derive helpers (helpers written before derives that introduce them).
1011 item: &mut impl AstLike,
1012 ) -> Option<(ast::Attribute, usize, Vec<Path>)> {
1013 let mut attr = None;
1015 item.visit_attrs(|attrs| {
1018 .position(|a| !self.cx.expanded_inert_attrs.is_marked(a) && !is_builtin_attr(a))
1020 let attr = attrs.remove(attr_pos);
1021 let following_derives = attrs[attr_pos..]
1023 .filter(|a| a.has_name(sym::derive))
1024 .flat_map(|a| a.meta_item_list().unwrap_or_default())
1025 .filter_map(|nested_meta| match nested_meta {
1026 NestedMetaItem::MetaItem(ast::MetaItem {
1027 kind: MetaItemKind::Word,
1035 (attr, attr_pos, following_derives)
1045 ) -> Result<(bool, MacCall, Vec<ast::Attribute>), ast::Stmt> {
1047 StmtKind::MacCall(mac) => {
1048 let MacCallStmt { mac, style, attrs, .. } = mac.into_inner();
1049 Ok((style == MacStmtStyle::Semicolon, mac, attrs.into()))
1051 StmtKind::Item(item) if matches!(item.kind, ItemKind::MacCall(..)) => {
1052 match item.into_inner() {
1053 ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => {
1054 Ok((mac.args.need_semicolon(), mac, attrs))
1056 _ => unreachable!(),
1059 StmtKind::Semi(expr) if matches!(expr.kind, ast::ExprKind::MacCall(..)) => {
1060 match expr.into_inner() {
1061 ast::Expr { kind: ast::ExprKind::MacCall(mac), attrs, .. } => {
1062 Ok((mac.args.need_semicolon(), mac, attrs.into()))
1064 _ => unreachable!(),
1067 StmtKind::Local(..) | StmtKind::Empty | StmtKind::Item(..) | StmtKind::Semi(..) => {
1070 StmtKind::Expr(..) => unreachable!(),
1074 fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
1075 self.cfg.configure(node)
1078 // Detect use of feature-gated or invalid attributes on macro invocations
1079 // since they will not be detected after macro expansion.
1080 fn check_attributes(&self, attrs: &[ast::Attribute], call: &MacCall) {
1081 let features = self.cx.ecfg.features.unwrap();
1082 let mut attrs = attrs.iter().peekable();
1083 let mut span: Option<Span> = None;
1084 while let Some(attr) = attrs.next() {
1085 rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
1086 validate_attr::check_meta(&self.cx.sess.parse_sess, attr);
1088 let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
1089 span = Some(current_span);
1091 if attrs.peek().map_or(false, |next_attr| next_attr.doc_str().is_some()) {
1095 if attr.is_doc_comment() {
1096 self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
1097 &UNUSED_DOC_COMMENTS,
1099 self.cx.current_expansion.lint_node_id,
1100 "unused doc comment",
1101 BuiltinLintDiagnostics::UnusedDocComment(attr.span),
1103 } else if rustc_attr::is_builtin_attr(attr) {
1104 let attr_name = attr.ident().unwrap().name;
1105 // `#[cfg]` and `#[cfg_attr]` are special - they are
1106 // eagerly evaluated.
1107 if attr_name != sym::cfg && attr_name != sym::cfg_attr {
1108 self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
1111 self.cx.current_expansion.lint_node_id,
1112 &format!("unused attribute `{}`", attr_name),
1113 BuiltinLintDiagnostics::UnusedBuiltinAttribute {
1115 macro_name: pprust::path_to_string(&call.path),
1116 invoc_span: call.path.span,
1125 /// Wraps a call to `noop_visit_*` / `noop_flat_map_*`
1126 /// for an AST node that supports attributes
1127 /// (see the `Annotatable` enum)
1128 /// This method assigns a `NodeId`, and sets that `NodeId`
1129 /// as our current 'lint node id'. If a macro call is found
1130 /// inside this AST node, we will use this AST node's `NodeId`
1131 /// to emit lints associated with that macro (allowing
1132 /// `#[allow]` / `#[deny]` to be applied close to
1133 /// the macro invocation).
1135 /// Do *not* call this for a macro AST node
1136 /// (e.g. `ExprKind::MacCall`) - we cannot emit lints
1137 /// at these AST nodes, since they are removed and
1138 /// replaced with the result of macro expansion.
1140 /// All other `NodeId`s are assigned by `visit_id`.
1141 /// * `self` is the 'self' parameter for the current method,
1142 /// * `id` is a mutable reference to the `NodeId` field
1143 /// of the current AST node.
1144 /// * `closure` is a closure that executes the
1145 /// `noop_visit_*` / `noop_flat_map_*` method
1146 /// for the current AST node.
1147 macro_rules! assign_id {
1148 ($self:ident, $id:expr, $closure:expr) => {{
1149 let old_id = $self.cx.current_expansion.lint_node_id;
1150 if $self.monotonic {
1151 debug_assert_eq!(*$id, ast::DUMMY_NODE_ID);
1152 let new_id = $self.cx.resolver.next_node_id();
1154 $self.cx.current_expansion.lint_node_id = new_id;
1156 let ret = ($closure)();
1157 $self.cx.current_expansion.lint_node_id = old_id;
1162 impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1163 fn visit_crate(&mut self, krate: &mut ast::Crate) {
1164 visit_clobber(krate, |krate| {
1165 let span = krate.span;
1166 let mut krate = match self.configure(krate) {
1167 Some(krate) => krate,
1173 id: self.cx.resolver.next_node_id(),
1174 is_placeholder: false,
1179 if let Some(attr) = self.take_first_attr(&mut krate) {
1181 .collect_attr(attr, Annotatable::Crate(krate), AstFragmentKind::Crate)
1185 assign_id!(self, &mut krate.id, || noop_visit_crate(&mut krate, self));
1190 fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
1191 self.cfg.configure_expr(expr);
1192 visit_clobber(expr.deref_mut(), |mut expr| {
1193 if let Some(attr) = self.take_first_attr(&mut expr) {
1194 // Collect the invoc regardless of whether or not attributes are permitted here
1195 // expansion will eat the attribute so it won't error later.
1196 self.cfg.maybe_emit_expr_attr_err(&attr.0);
1198 // AstFragmentKind::Expr requires the macro to emit an expression.
1200 .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::Expr)
1205 if let ast::ExprKind::MacCall(mac) = expr.kind {
1206 self.check_attributes(&expr.attrs, &mac);
1207 self.collect_bang(mac, AstFragmentKind::Expr).make_expr().into_inner()
1209 assign_id!(self, &mut expr.id, || {
1210 ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self));
1217 fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
1218 let mut arm = configure!(self, arm);
1220 if let Some(attr) = self.take_first_attr(&mut arm) {
1222 .collect_attr(attr, Annotatable::Arm(arm), AstFragmentKind::Arms)
1226 assign_id!(self, &mut arm.id, || noop_flat_map_arm(arm, self))
1229 fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
1230 let mut field = configure!(self, field);
1232 if let Some(attr) = self.take_first_attr(&mut field) {
1234 .collect_attr(attr, Annotatable::ExprField(field), AstFragmentKind::Fields)
1235 .make_expr_fields();
1238 assign_id!(self, &mut field.id, || noop_flat_map_expr_field(field, self))
1241 fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
1242 let mut fp = configure!(self, fp);
1244 if let Some(attr) = self.take_first_attr(&mut fp) {
1246 .collect_attr(attr, Annotatable::PatField(fp), AstFragmentKind::FieldPats)
1250 assign_id!(self, &mut fp.id, || noop_flat_map_pat_field(fp, self))
1253 fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
1254 let mut p = configure!(self, p);
1256 if let Some(attr) = self.take_first_attr(&mut p) {
1258 .collect_attr(attr, Annotatable::Param(p), AstFragmentKind::Params)
1262 assign_id!(self, &mut p.id, || noop_flat_map_param(p, self))
1265 fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
1266 let mut sf = configure!(self, sf);
1268 if let Some(attr) = self.take_first_attr(&mut sf) {
1270 .collect_attr(attr, Annotatable::FieldDef(sf), AstFragmentKind::StructFields)
1274 assign_id!(self, &mut sf.id, || noop_flat_map_field_def(sf, self))
1277 fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
1278 let mut variant = configure!(self, variant);
1280 if let Some(attr) = self.take_first_attr(&mut variant) {
1282 .collect_attr(attr, Annotatable::Variant(variant), AstFragmentKind::Variants)
1286 assign_id!(self, &mut variant.id, || noop_flat_map_variant(variant, self))
1289 fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
1290 let expr = configure!(self, expr);
1291 expr.filter_map(|mut expr| {
1292 if let Some(attr) = self.take_first_attr(&mut expr) {
1293 self.cfg.maybe_emit_expr_attr_err(&attr.0);
1296 .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr)
1298 .map(|expr| expr.into_inner());
1301 if let ast::ExprKind::MacCall(mac) = expr.kind {
1302 self.check_attributes(&expr.attrs, &mac);
1303 self.collect_bang(mac, AstFragmentKind::OptExpr)
1305 .map(|expr| expr.into_inner())
1307 assign_id!(self, &mut expr.id, || {
1309 noop_visit_expr(&mut expr, self);
1317 fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
1319 PatKind::MacCall(_) => {}
1320 _ => return noop_visit_pat(pat, self),
1323 visit_clobber(pat, |mut pat| match mem::replace(&mut pat.kind, PatKind::Wild) {
1324 PatKind::MacCall(mac) => self.collect_bang(mac, AstFragmentKind::Pat).make_pat(),
1325 _ => unreachable!(),
1329 fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
1330 let mut stmt = configure!(self, stmt);
1332 // We pull macro invocations (both attributes and fn-like macro calls) out of their
1333 // `StmtKind`s and treat them as statement macro invocations, not as items or expressions.
1334 // FIXME: invocations in semicolon-less expressions positions are expanded as expressions,
1335 // changing that requires some compatibility measures.
1336 let mut stmt = if !stmt.is_expr() {
1337 if let Some(attr) = self.take_first_attr(&mut stmt) {
1339 .collect_attr(attr, Annotatable::Stmt(P(stmt)), AstFragmentKind::Stmts)
1343 match self.take_stmt_bang(stmt) {
1344 Ok((add_semicolon, mac, attrs)) => {
1345 self.check_attributes(&attrs, &mac);
1346 let mut stmts = self.collect_bang(mac, AstFragmentKind::Stmts).make_stmts();
1348 // If this is a macro invocation with a semicolon, then apply that
1349 // semicolon to the final statement produced by expansion.
1351 if let Some(stmt) = stmts.pop() {
1352 stmts.push(stmt.add_trailing_semicolon());
1364 // The only way that we can end up with a `MacCall` expression statement,
1365 // (as opposed to a `StmtKind::MacCall`) is if we have a macro as the
1366 // traiing expression in a block (e.g. `fn foo() { my_macro!() }`).
1367 // Record this information, so that we can report a more specific
1368 // `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` lint if needed.
1369 // See #78991 for an investigation of treating macros in this position
1370 // as statements, rather than expressions, during parsing.
1371 let res = match &stmt.kind {
1372 StmtKind::Expr(expr)
1373 if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) =>
1375 self.cx.current_expansion.is_trailing_mac = true;
1376 // Don't use `assign_id` for this statement - it may get removed
1377 // entirely due to a `#[cfg]` on the contained expression
1378 noop_flat_map_stmt(stmt, self)
1380 _ => assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self)),
1382 self.cx.current_expansion.is_trailing_mac = false;
1386 fn visit_block(&mut self, block: &mut P<Block>) {
1387 let orig_dir_ownership = mem::replace(
1388 &mut self.cx.current_expansion.dir_ownership,
1389 DirOwnership::UnownedViaBlock,
1391 noop_visit_block(block, self);
1392 self.cx.current_expansion.dir_ownership = orig_dir_ownership;
1395 fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
1396 let mut item = configure!(self, item);
1398 if let Some(attr) = self.take_first_attr(&mut item) {
1400 .collect_attr(attr, Annotatable::Item(item), AstFragmentKind::Items)
1404 let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
1405 let ident = item.ident;
1406 let span = item.span;
1409 ast::ItemKind::MacCall(ref mac) => {
1410 self.check_attributes(&attrs, &mac);
1412 item.and_then(|item| match item.kind {
1413 ItemKind::MacCall(mac) => {
1414 self.collect_bang(mac, AstFragmentKind::Items).make_items()
1416 _ => unreachable!(),
1419 ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::empty() => {
1420 let (file_path, dir_path, dir_ownership) = match mod_kind {
1421 ModKind::Loaded(_, inline, _) => {
1422 // Inline `mod foo { ... }`, but we still need to push directories.
1423 let (dir_path, dir_ownership) = mod_dir_path(
1427 &self.cx.current_expansion.module,
1428 self.cx.current_expansion.dir_ownership,
1432 (None, dir_path, dir_ownership)
1434 ModKind::Unloaded => {
1435 // We have an outline `mod foo;` so we need to parse the file.
1436 let old_attrs_len = attrs.len();
1437 let ParsedExternalMod {
1443 } = parse_external_mod(
1447 &self.cx.current_expansion.module,
1448 self.cx.current_expansion.dir_ownership,
1452 if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
1453 (attrs, items) = extern_mod_loaded(ident, attrs, items, inner_span);
1456 *mod_kind = ModKind::Loaded(items, Inline::No, inner_span);
1458 if item.attrs.len() > old_attrs_len {
1459 // If we loaded an out-of-line module and added some inner attributes,
1460 // then we need to re-configure it and re-collect attributes for
1461 // resolution and expansion.
1462 item = configure!(self, item);
1464 if let Some(attr) = self.take_first_attr(&mut item) {
1468 Annotatable::Item(item),
1469 AstFragmentKind::Items,
1474 (Some(file_path), dir_path, dir_ownership)
1478 // Set the module info before we flat map.
1479 let mut module = self.cx.current_expansion.module.with_dir_path(dir_path);
1480 module.mod_path.push(ident);
1481 if let Some(file_path) = file_path {
1482 module.file_path_stack.push(file_path);
1486 mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
1487 let orig_dir_ownership =
1488 mem::replace(&mut self.cx.current_expansion.dir_ownership, dir_ownership);
1490 let result = assign_id!(self, &mut item.id, || noop_flat_map_item(item, self));
1492 // Restore the module info.
1493 self.cx.current_expansion.dir_ownership = orig_dir_ownership;
1494 self.cx.current_expansion.module = orig_module;
1500 // The crate root is special - don't assign an ID to it.
1501 if !(matches!(item.kind, ast::ItemKind::Mod(..)) && ident == Ident::empty()) {
1502 assign_id!(self, &mut item.id, || noop_flat_map_item(item, self))
1504 noop_flat_map_item(item, self)
1510 fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
1511 let mut item = configure!(self, item);
1513 if let Some(attr) = self.take_first_attr(&mut item) {
1515 .collect_attr(attr, Annotatable::TraitItem(item), AstFragmentKind::TraitItems)
1516 .make_trait_items();
1520 ast::AssocItemKind::MacCall(ref mac) => {
1521 self.check_attributes(&item.attrs, &mac);
1522 item.and_then(|item| match item.kind {
1523 ast::AssocItemKind::MacCall(mac) => {
1524 self.collect_bang(mac, AstFragmentKind::TraitItems).make_trait_items()
1526 _ => unreachable!(),
1530 assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self))
1535 fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
1536 let mut item = configure!(self, item);
1538 if let Some(attr) = self.take_first_attr(&mut item) {
1540 .collect_attr(attr, Annotatable::ImplItem(item), AstFragmentKind::ImplItems)
1545 ast::AssocItemKind::MacCall(ref mac) => {
1546 self.check_attributes(&item.attrs, &mac);
1547 item.and_then(|item| match item.kind {
1548 ast::AssocItemKind::MacCall(mac) => {
1549 self.collect_bang(mac, AstFragmentKind::ImplItems).make_impl_items()
1551 _ => unreachable!(),
1555 assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self))
1560 fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
1562 ast::TyKind::MacCall(_) => {}
1563 _ => return noop_visit_ty(ty, self),
1566 visit_clobber(ty, |mut ty| match mem::replace(&mut ty.kind, ast::TyKind::Err) {
1567 ast::TyKind::MacCall(mac) => self.collect_bang(mac, AstFragmentKind::Ty).make_ty(),
1568 _ => unreachable!(),
1572 fn flat_map_foreign_item(
1574 foreign_item: P<ast::ForeignItem>,
1575 ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
1576 let mut foreign_item = configure!(self, foreign_item);
1578 if let Some(attr) = self.take_first_attr(&mut foreign_item) {
1582 Annotatable::ForeignItem(foreign_item),
1583 AstFragmentKind::ForeignItems,
1585 .make_foreign_items();
1588 match foreign_item.kind {
1589 ast::ForeignItemKind::MacCall(ref mac) => {
1590 self.check_attributes(&foreign_item.attrs, &mac);
1591 foreign_item.and_then(|item| match item.kind {
1592 ast::ForeignItemKind::MacCall(mac) => {
1593 self.collect_bang(mac, AstFragmentKind::ForeignItems).make_foreign_items()
1595 _ => unreachable!(),
1599 assign_id!(self, &mut foreign_item.id, || noop_flat_map_foreign_item(
1607 fn flat_map_generic_param(
1609 param: ast::GenericParam,
1610 ) -> SmallVec<[ast::GenericParam; 1]> {
1611 let mut param = configure!(self, param);
1613 if let Some(attr) = self.take_first_attr(&mut param) {
1617 Annotatable::GenericParam(param),
1618 AstFragmentKind::GenericParams,
1620 .make_generic_params();
1623 assign_id!(self, &mut param.id, || noop_flat_map_generic_param(param, self))
1626 fn visit_id(&mut self, id: &mut ast::NodeId) {
1627 // We may have already assigned a `NodeId`
1628 // by calling `assign_id`
1629 if self.monotonic && *id == ast::DUMMY_NODE_ID {
1630 *id = self.cx.resolver.next_node_id();
1635 pub struct ExpansionConfig<'feat> {
1636 pub crate_name: String,
1637 pub features: Option<&'feat Features>,
1638 pub recursion_limit: Limit,
1639 pub trace_mac: bool,
1640 pub should_test: bool, // If false, strip `#[test]` nodes
1641 pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
1642 pub proc_macro_backtrace: bool, // If true, show backtraces for proc-macro panics
1645 impl<'feat> ExpansionConfig<'feat> {
1646 pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1650 recursion_limit: Limit::new(1024),
1654 proc_macro_backtrace: false,
1658 fn proc_macro_hygiene(&self) -> bool {
1659 self.features.map_or(false, |features| features.proc_macro_hygiene)