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};
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_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::invalid(),
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 (invoc, ext) = if let Some(invoc) = invocations.pop() {
453 self.resolve_imports();
454 if undetermined_invocations.is_empty() {
457 invocations = mem::take(&mut undetermined_invocations);
458 force = !mem::replace(&mut progress, false);
459 if force && self.monotonic {
460 self.cx.sess.delay_span_bug(
461 invocations.last().unwrap().0.span(),
462 "expansion entered force mode without producing any errors",
468 let ext = match ext {
471 let eager_expansion_root = if self.monotonic {
472 invoc.expansion_data.id
474 orig_expansion_data.id
476 match self.cx.resolver.resolve_macro_invocation(
478 eager_expansion_root,
482 Err(Indeterminate) => {
483 // Cannot resolve, will retry this invocation later.
484 undetermined_invocations.push((invoc, None));
491 let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
492 let depth = depth - orig_expansion_data.depth;
493 self.cx.current_expansion = invoc.expansion_data.clone();
494 self.cx.force_mode = force;
496 let fragment_kind = invoc.fragment_kind;
497 let (expanded_fragment, new_invocations) = match self.expand_invoc(invoc, &ext.kind) {
498 ExpandResult::Ready(fragment) => {
499 let mut derive_invocations = Vec::new();
500 let derive_placeholders = self
503 .take_derive_resolutions(expn_id)
505 derive_invocations.reserve(derives.len());
508 .map(|(path, item, _exts)| {
509 // FIXME: Consider using the derive resolutions (`_exts`)
510 // instead of enqueuing the derives to be resolved again later.
511 let expn_id = LocalExpnId::fresh_empty();
512 derive_invocations.push((
514 kind: InvocationKind::Derive { path, item },
516 expansion_data: ExpansionData {
518 ..self.cx.current_expansion.clone()
523 NodeId::placeholder_from_expn_id(expn_id)
527 .unwrap_or_default();
529 let (fragment, collected_invocations) =
530 self.collect_invocations(fragment, &derive_placeholders);
531 // We choose to expand any derive invocations associated with this macro invocation
532 // *before* any macro invocations collected from the output fragment
533 derive_invocations.extend(collected_invocations);
534 (fragment, derive_invocations)
536 ExpandResult::Retry(invoc) => {
540 "expansion entered force mode but is still stuck",
543 // Cannot expand, will retry this invocation later.
544 undetermined_invocations.push((invoc, Some(ext)));
551 if expanded_fragments.len() < depth {
552 expanded_fragments.push(Vec::new());
554 expanded_fragments[depth - 1].push((expn_id, expanded_fragment));
555 invocations.extend(new_invocations.into_iter().rev());
558 self.cx.current_expansion = orig_expansion_data;
559 self.cx.force_mode = orig_force_mode;
561 // Finally incorporate all the expanded macros into the input AST fragment.
562 let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
563 while let Some(expanded_fragments) = expanded_fragments.pop() {
564 for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
566 .add(NodeId::placeholder_from_expn_id(expn_id), expanded_fragment);
569 fragment_with_placeholders.mut_visit_with(&mut placeholder_expander);
570 fragment_with_placeholders
573 fn resolve_imports(&mut self) {
575 self.cx.resolver.resolve_imports();
579 /// Collects all macro invocations reachable at this time in this AST fragment, and replace
580 /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
581 /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
582 /// prepares data for resolving paths of macro invocations.
583 fn collect_invocations(
585 mut fragment: AstFragment,
586 extra_placeholders: &[NodeId],
587 ) -> (AstFragment, Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>) {
588 // Resolve `$crate`s in the fragment for pretty-printing.
589 self.cx.resolver.resolve_dollar_crates();
592 let mut collector = InvocationCollector {
593 // Non-derive macro invocations cannot see the results of cfg expansion - they
594 // will either be removed along with the item, or invoked before the cfg/cfg_attr
595 // attribute is expanded. Therefore, we don't need to configure the tokens
596 // Derive macros *can* see the results of cfg-expansion - they are handled
597 // specially in `fully_expand_fragment`
598 cfg: StripUnconfigured {
600 features: self.cx.ecfg.features,
601 config_tokens: false,
604 invocations: Vec::new(),
605 monotonic: self.monotonic,
607 fragment.mut_visit_with(&mut collector);
608 fragment.add_placeholders(extra_placeholders);
609 collector.invocations
615 .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);
618 (fragment, invocations)
621 fn error_recursion_limit_reached(&mut self) {
622 let expn_data = self.cx.current_expansion.id.expn_data();
623 let suggested_limit = self.cx.ecfg.recursion_limit * 2;
627 &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
630 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
631 suggested_limit, self.cx.ecfg.crate_name,
634 self.cx.trace_macros_diag();
637 /// A macro's expansion does not fit in this fragment kind.
638 /// For example, a non-type macro in a type position.
639 fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
641 "non-{kind} macro in {kind} position: {path}",
643 path = pprust::path_to_string(&mac.path),
645 self.cx.span_err(span, &msg);
646 self.cx.trace_macros_diag();
652 ext: &SyntaxExtensionKind,
653 ) -> ExpandResult<AstFragment, Invocation> {
654 let recursion_limit =
655 self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
656 if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
657 if self.cx.reduced_recursion_limit.is_none() {
658 self.error_recursion_limit_reached();
661 // Reduce the recursion limit by half each time it triggers.
662 self.cx.reduced_recursion_limit = Some(recursion_limit / 2);
664 return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span()));
667 let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
668 ExpandResult::Ready(match invoc.kind {
669 InvocationKind::Bang { mac, .. } => match ext {
670 SyntaxExtensionKind::Bang(expander) => {
671 let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) {
672 Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
675 self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
677 SyntaxExtensionKind::LegacyBang(expander) => {
678 let prev = self.cx.current_expansion.prior_type_ascription;
679 self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription;
680 let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
681 let result = if let Some(result) = fragment_kind.make_from(tok_result) {
684 self.error_wrong_fragment_kind(fragment_kind, &mac, span);
685 fragment_kind.dummy(span)
687 self.cx.current_expansion.prior_type_ascription = prev;
692 InvocationKind::Attr { attr, pos, mut item, derives } => match ext {
693 SyntaxExtensionKind::Attr(expander) => {
694 self.gate_proc_macro_input(&item);
695 self.gate_proc_macro_attr_item(span, &item);
696 let mut fake_tokens = false;
697 if let Annotatable::Item(item_inner) = &item {
698 if let ItemKind::Mod(_, mod_kind) = &item_inner.kind {
699 // FIXME: Collect tokens and use them instead of generating
700 // fake ones. These are unstable, so it needs to be
701 // fixed prior to stabilization
702 // Fake tokens when we are invoking an inner attribute, and:
703 fake_tokens = matches!(attr.style, ast::AttrStyle::Inner) &&
704 // We are invoking an attribute on the crate root, or an outline
706 (item_inner.ident.name.is_empty() || !matches!(mod_kind, ast::ModKind::Loaded(_, Inline::Yes, _)));
709 let tokens = if fake_tokens {
710 rustc_parse::fake_token_stream(
711 &self.cx.sess.parse_sess,
712 &item.into_nonterminal(),
715 item.into_tokens(&self.cx.sess.parse_sess)
717 let attr_item = attr.unwrap_normal_item();
718 if let MacArgs::Eq(..) = attr_item.args {
719 self.cx.span_err(span, "key-value macro attributes are not supported");
721 let inner_tokens = attr_item.args.inner_tokens();
722 let tok_result = match expander.expand(self.cx, span, inner_tokens, tokens) {
723 Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
726 self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span)
728 SyntaxExtensionKind::LegacyAttr(expander) => {
729 match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) {
731 let items = match expander.expand(self.cx, span, &meta, item) {
732 ExpandResult::Ready(items) => items,
733 ExpandResult::Retry(item) => {
734 // Reassemble the original invocation for retrying.
735 return ExpandResult::Retry(Invocation {
736 kind: InvocationKind::Attr { attr, pos, item, derives },
741 if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
743 "removing an expression is not supported in this position";
744 self.cx.span_err(span, msg);
745 fragment_kind.dummy(span)
747 fragment_kind.expect_from_annotatables(items)
752 fragment_kind.dummy(span)
756 SyntaxExtensionKind::NonMacroAttr { mark_used } => {
757 self.cx.sess.mark_attr_known(&attr);
759 self.cx.sess.mark_attr_used(&attr);
761 item.visit_attrs(|attrs| attrs.insert(pos, attr));
762 fragment_kind.expect_from_annotatables(iter::once(item))
766 InvocationKind::Derive { path, item } => match ext {
767 SyntaxExtensionKind::Derive(expander)
768 | SyntaxExtensionKind::LegacyDerive(expander) => {
769 if let SyntaxExtensionKind::Derive(..) = ext {
770 self.gate_proc_macro_input(&item);
772 let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
773 let items = match expander.expand(self.cx, span, &meta, item) {
774 ExpandResult::Ready(items) => items,
775 ExpandResult::Retry(item) => {
776 // Reassemble the original invocation for retrying.
777 return ExpandResult::Retry(Invocation {
778 kind: InvocationKind::Derive { path: meta.path, item },
783 fragment_kind.expect_from_annotatables(items)
790 fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
791 let kind = match item {
793 | Annotatable::TraitItem(_)
794 | Annotatable::ImplItem(_)
795 | Annotatable::ForeignItem(_) => return,
796 Annotatable::Stmt(stmt) => {
797 // Attributes are stable on item statements,
798 // but unstable on all other kinds of statements
804 Annotatable::Expr(_) => "expressions",
806 | Annotatable::ExprField(..)
807 | Annotatable::PatField(..)
808 | Annotatable::GenericParam(..)
809 | Annotatable::Param(..)
810 | Annotatable::FieldDef(..)
811 | Annotatable::Variant(..) => panic!("unexpected annotatable"),
813 if self.cx.ecfg.proc_macro_hygiene() {
817 &self.cx.sess.parse_sess,
818 sym::proc_macro_hygiene,
820 &format!("custom attributes cannot be applied to {}", kind),
825 fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
826 struct GateProcMacroInput<'a> {
827 parse_sess: &'a ParseSess,
830 impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
831 fn visit_item(&mut self, item: &'ast ast::Item) {
833 ast::ItemKind::Mod(_, mod_kind)
834 if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
838 sym::proc_macro_hygiene,
840 "non-inline modules in proc macro input are unstable",
847 visit::walk_item(self, item);
851 if !self.cx.ecfg.proc_macro_hygiene() {
853 .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess });
857 fn parse_ast_fragment(
860 kind: AstFragmentKind,
864 let mut parser = self.cx.new_parser_from_tts(toks);
865 match parse_ast_fragment(&mut parser, kind) {
867 ensure_complete_parse(&mut parser, path, kind.name(), span);
871 if err.span.is_dummy() {
874 annotate_err_with_kind(&mut err, kind, span);
876 self.cx.trace_macros_diag();
883 pub fn parse_ast_fragment<'a>(
884 this: &mut Parser<'a>,
885 kind: AstFragmentKind,
886 ) -> PResult<'a, AstFragment> {
888 AstFragmentKind::Items => {
889 let mut items = SmallVec::new();
890 while let Some(item) = this.parse_item(ForceCollect::No)? {
893 AstFragment::Items(items)
895 AstFragmentKind::TraitItems => {
896 let mut items = SmallVec::new();
897 while let Some(item) = this.parse_trait_item(ForceCollect::No)? {
900 AstFragment::TraitItems(items)
902 AstFragmentKind::ImplItems => {
903 let mut items = SmallVec::new();
904 while let Some(item) = this.parse_impl_item(ForceCollect::No)? {
907 AstFragment::ImplItems(items)
909 AstFragmentKind::ForeignItems => {
910 let mut items = SmallVec::new();
911 while let Some(item) = this.parse_foreign_item(ForceCollect::No)? {
914 AstFragment::ForeignItems(items)
916 AstFragmentKind::Stmts => {
917 let mut stmts = SmallVec::new();
918 // Won't make progress on a `}`.
919 while this.token != token::Eof && this.token != token::CloseDelim(token::Brace) {
920 if let Some(stmt) = this.parse_full_stmt(AttemptLocalParseRecovery::Yes)? {
924 AstFragment::Stmts(stmts)
926 AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
927 AstFragmentKind::OptExpr => {
928 if this.token != token::Eof {
929 AstFragment::OptExpr(Some(this.parse_expr()?))
931 AstFragment::OptExpr(None)
934 AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
935 AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_alt(
940 AstFragmentKind::Arms
941 | AstFragmentKind::Fields
942 | AstFragmentKind::FieldPats
943 | AstFragmentKind::GenericParams
944 | AstFragmentKind::Params
945 | AstFragmentKind::StructFields
946 | AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
950 pub fn ensure_complete_parse<'a>(
951 this: &mut Parser<'a>,
956 if this.token != token::Eof {
957 let token = pprust::token_to_string(&this.token);
958 let msg = format!("macro expansion ignores token `{}` and any following", token);
959 // Avoid emitting backtrace info twice.
960 let def_site_span = this.token.span.with_ctxt(SyntaxContext::root());
961 let mut err = this.struct_span_err(def_site_span, &msg);
962 err.span_label(span, "caused by the macro expansion here");
964 "the usage of `{}!` is likely invalid in {} context",
965 pprust::path_to_string(macro_path),
969 let semi_span = this.sess.source_map().next_point(span);
971 let semi_full_span = semi_span.to(this.sess.source_map().next_point(semi_span));
972 match this.sess.source_map().span_to_snippet(semi_full_span) {
973 Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
976 "you might be missing a semicolon here",
978 Applicability::MaybeIncorrect,
987 struct InvocationCollector<'a, 'b> {
988 cx: &'a mut ExtCtxt<'b>,
989 cfg: StripUnconfigured<'a>,
990 invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
994 impl<'a, 'b> InvocationCollector<'a, 'b> {
995 fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
996 let expn_id = LocalExpnId::fresh_empty();
997 let vis = kind.placeholder_visibility();
998 self.invocations.push((
1002 expansion_data: ExpansionData {
1004 depth: self.cx.current_expansion.depth + 1,
1005 ..self.cx.current_expansion.clone()
1010 placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
1017 kind: AstFragmentKind,
1019 self.collect(kind, InvocationKind::Bang { mac, span })
1024 (attr, pos, derives): (ast::Attribute, usize, Vec<Path>),
1026 kind: AstFragmentKind,
1028 self.collect(kind, InvocationKind::Attr { attr, pos, item, derives })
1031 /// If `item` is an attribute invocation, remove the attribute and return it together with
1032 /// its position and derives following it. We have to collect the derives in order to resolve
1033 /// legacy derive helpers (helpers written before derives that introduce them).
1036 item: &mut impl AstLike,
1037 ) -> Option<(ast::Attribute, usize, Vec<Path>)> {
1038 let mut attr = None;
1040 item.visit_attrs(|attrs| {
1043 .position(|a| !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a))
1045 let attr = attrs.remove(attr_pos);
1046 let following_derives = attrs[attr_pos..]
1048 .filter(|a| a.has_name(sym::derive))
1049 .flat_map(|a| a.meta_item_list().unwrap_or_default())
1050 .filter_map(|nested_meta| match nested_meta {
1051 NestedMetaItem::MetaItem(ast::MetaItem {
1052 kind: MetaItemKind::Word,
1060 (attr, attr_pos, following_derives)
1067 fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
1068 self.cfg.configure(node)
1071 // Detect use of feature-gated or invalid attributes on macro invocations
1072 // since they will not be detected after macro expansion.
1073 fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
1074 let features = self.cx.ecfg.features.unwrap();
1075 let mut attrs = attrs.iter().peekable();
1076 let mut span: Option<Span> = None;
1077 while let Some(attr) = attrs.next() {
1078 rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
1079 validate_attr::check_meta(&self.cx.sess.parse_sess, attr);
1081 let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
1082 span = Some(current_span);
1084 if attrs.peek().map_or(false, |next_attr| next_attr.doc_str().is_some()) {
1088 if attr.doc_str().is_some() {
1089 self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
1090 &UNUSED_DOC_COMMENTS,
1093 "unused doc comment",
1094 BuiltinLintDiagnostics::UnusedDocComment(attr.span),
1101 impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1102 fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
1103 self.cfg.configure_expr(expr);
1104 visit_clobber(expr.deref_mut(), |mut expr| {
1105 if let Some(attr) = self.take_first_attr(&mut expr) {
1106 // Collect the invoc regardless of whether or not attributes are permitted here
1107 // expansion will eat the attribute so it won't error later.
1108 self.cfg.maybe_emit_expr_attr_err(&attr.0);
1110 // AstFragmentKind::Expr requires the macro to emit an expression.
1112 .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::Expr)
1117 if let ast::ExprKind::MacCall(mac) = expr.kind {
1118 self.check_attributes(&expr.attrs);
1119 self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
1121 ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self));
1127 fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
1128 let mut arm = configure!(self, arm);
1130 if let Some(attr) = self.take_first_attr(&mut arm) {
1132 .collect_attr(attr, Annotatable::Arm(arm), AstFragmentKind::Arms)
1136 noop_flat_map_arm(arm, self)
1139 fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
1140 let mut field = configure!(self, field);
1142 if let Some(attr) = self.take_first_attr(&mut field) {
1144 .collect_attr(attr, Annotatable::ExprField(field), AstFragmentKind::Fields)
1145 .make_expr_fields();
1148 noop_flat_map_expr_field(field, self)
1151 fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
1152 let mut fp = configure!(self, fp);
1154 if let Some(attr) = self.take_first_attr(&mut fp) {
1156 .collect_attr(attr, Annotatable::PatField(fp), AstFragmentKind::FieldPats)
1160 noop_flat_map_pat_field(fp, self)
1163 fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
1164 let mut p = configure!(self, p);
1166 if let Some(attr) = self.take_first_attr(&mut p) {
1168 .collect_attr(attr, Annotatable::Param(p), AstFragmentKind::Params)
1172 noop_flat_map_param(p, self)
1175 fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
1176 let mut sf = configure!(self, sf);
1178 if let Some(attr) = self.take_first_attr(&mut sf) {
1180 .collect_attr(attr, Annotatable::FieldDef(sf), AstFragmentKind::StructFields)
1184 noop_flat_map_field_def(sf, self)
1187 fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
1188 let mut variant = configure!(self, variant);
1190 if let Some(attr) = self.take_first_attr(&mut variant) {
1192 .collect_attr(attr, Annotatable::Variant(variant), AstFragmentKind::Variants)
1196 noop_flat_map_variant(variant, self)
1199 fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
1200 let expr = configure!(self, expr);
1201 expr.filter_map(|mut expr| {
1202 if let Some(attr) = self.take_first_attr(&mut expr) {
1203 self.cfg.maybe_emit_expr_attr_err(&attr.0);
1206 .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr)
1208 .map(|expr| expr.into_inner());
1211 if let ast::ExprKind::MacCall(mac) = expr.kind {
1212 self.check_attributes(&expr.attrs);
1213 self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr)
1215 .map(|expr| expr.into_inner())
1218 noop_visit_expr(&mut expr, self);
1225 fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
1227 PatKind::MacCall(_) => {}
1228 _ => return noop_visit_pat(pat, self),
1231 visit_clobber(pat, |mut pat| match mem::replace(&mut pat.kind, PatKind::Wild) {
1232 PatKind::MacCall(mac) => {
1233 self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat()
1235 _ => unreachable!(),
1239 fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
1240 let mut stmt = configure!(self, stmt);
1242 // we'll expand attributes on expressions separately
1243 if !stmt.is_expr() {
1244 if let Some(attr) = self.take_first_attr(&mut stmt) {
1246 .collect_attr(attr, Annotatable::Stmt(P(stmt)), AstFragmentKind::Stmts)
1251 if let StmtKind::MacCall(mac) = stmt.kind {
1252 let MacCallStmt { mac, style, attrs, tokens: _ } = mac.into_inner();
1253 self.check_attributes(&attrs);
1254 let mut placeholder =
1255 self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts();
1257 // If this is a macro invocation with a semicolon, then apply that
1258 // semicolon to the final statement produced by expansion.
1259 if style == MacStmtStyle::Semicolon {
1260 if let Some(stmt) = placeholder.pop() {
1261 placeholder.push(stmt.add_trailing_semicolon());
1268 // The placeholder expander gives ids to statements, so we avoid folding the id here.
1269 let ast::Stmt { id, kind, span } = stmt;
1270 noop_flat_map_stmt_kind(kind, self)
1272 .map(|kind| ast::Stmt { id, kind, span })
1276 fn visit_block(&mut self, block: &mut P<Block>) {
1277 let orig_dir_ownership = mem::replace(
1278 &mut self.cx.current_expansion.dir_ownership,
1279 DirOwnership::UnownedViaBlock,
1281 noop_visit_block(block, self);
1282 self.cx.current_expansion.dir_ownership = orig_dir_ownership;
1285 fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
1286 let mut item = configure!(self, item);
1288 if let Some(attr) = self.take_first_attr(&mut item) {
1290 .collect_attr(attr, Annotatable::Item(item), AstFragmentKind::Items)
1294 let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
1295 let ident = item.ident;
1296 let span = item.span;
1299 ast::ItemKind::MacCall(..) => {
1301 self.check_attributes(&item.attrs);
1302 item.and_then(|item| match item.kind {
1303 ItemKind::MacCall(mac) => {
1304 self.collect_bang(mac, span, AstFragmentKind::Items).make_items()
1306 _ => unreachable!(),
1309 ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => {
1310 let (file_path, dir_path, dir_ownership) = match mod_kind {
1311 ModKind::Loaded(_, inline, _) => {
1312 // Inline `mod foo { ... }`, but we still need to push directories.
1313 let (dir_path, dir_ownership) = mod_dir_path(
1317 &self.cx.current_expansion.module,
1318 self.cx.current_expansion.dir_ownership,
1322 (None, dir_path, dir_ownership)
1324 ModKind::Unloaded => {
1325 // We have an outline `mod foo;` so we need to parse the file.
1326 let old_attrs_len = attrs.len();
1327 let ParsedExternalMod {
1333 } = parse_external_mod(
1337 &self.cx.current_expansion.module,
1338 self.cx.current_expansion.dir_ownership,
1342 if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
1343 (attrs, items) = extern_mod_loaded(ident, attrs, items, inner_span);
1346 *mod_kind = ModKind::Loaded(items, Inline::No, inner_span);
1348 if item.attrs.len() > old_attrs_len {
1349 // If we loaded an out-of-line module and added some inner attributes,
1350 // then we need to re-configure it and re-collect attributes for
1351 // resolution and expansion.
1352 item = configure!(self, item);
1354 if let Some(attr) = self.take_first_attr(&mut item) {
1358 Annotatable::Item(item),
1359 AstFragmentKind::Items,
1364 (Some(file_path), dir_path, dir_ownership)
1368 // Set the module info before we flat map.
1369 let mut module = self.cx.current_expansion.module.with_dir_path(dir_path);
1370 module.mod_path.push(ident);
1371 if let Some(file_path) = file_path {
1372 module.file_path_stack.push(file_path);
1376 mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
1377 let orig_dir_ownership =
1378 mem::replace(&mut self.cx.current_expansion.dir_ownership, dir_ownership);
1380 let result = noop_flat_map_item(item, self);
1382 // Restore the module info.
1383 self.cx.current_expansion.dir_ownership = orig_dir_ownership;
1384 self.cx.current_expansion.module = orig_module;
1390 noop_flat_map_item(item, self)
1395 fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
1396 let mut item = configure!(self, item);
1398 if let Some(attr) = self.take_first_attr(&mut item) {
1400 .collect_attr(attr, Annotatable::TraitItem(item), AstFragmentKind::TraitItems)
1401 .make_trait_items();
1405 ast::AssocItemKind::MacCall(..) => {
1406 self.check_attributes(&item.attrs);
1407 item.and_then(|item| match item.kind {
1408 ast::AssocItemKind::MacCall(mac) => self
1409 .collect_bang(mac, item.span, AstFragmentKind::TraitItems)
1410 .make_trait_items(),
1411 _ => unreachable!(),
1414 _ => noop_flat_map_assoc_item(item, self),
1418 fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
1419 let mut item = configure!(self, item);
1421 if let Some(attr) = self.take_first_attr(&mut item) {
1423 .collect_attr(attr, Annotatable::ImplItem(item), AstFragmentKind::ImplItems)
1428 ast::AssocItemKind::MacCall(..) => {
1429 self.check_attributes(&item.attrs);
1430 item.and_then(|item| match item.kind {
1431 ast::AssocItemKind::MacCall(mac) => self
1432 .collect_bang(mac, item.span, AstFragmentKind::ImplItems)
1434 _ => unreachable!(),
1437 _ => noop_flat_map_assoc_item(item, self),
1441 fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
1443 ast::TyKind::MacCall(_) => {}
1444 _ => return noop_visit_ty(ty, self),
1447 visit_clobber(ty, |mut ty| match mem::replace(&mut ty.kind, ast::TyKind::Err) {
1448 ast::TyKind::MacCall(mac) => {
1449 self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty()
1451 _ => unreachable!(),
1455 fn flat_map_foreign_item(
1457 foreign_item: P<ast::ForeignItem>,
1458 ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
1459 let mut foreign_item = configure!(self, foreign_item);
1461 if let Some(attr) = self.take_first_attr(&mut foreign_item) {
1465 Annotatable::ForeignItem(foreign_item),
1466 AstFragmentKind::ForeignItems,
1468 .make_foreign_items();
1471 match foreign_item.kind {
1472 ast::ForeignItemKind::MacCall(..) => {
1473 self.check_attributes(&foreign_item.attrs);
1474 foreign_item.and_then(|item| match item.kind {
1475 ast::ForeignItemKind::MacCall(mac) => self
1476 .collect_bang(mac, item.span, AstFragmentKind::ForeignItems)
1477 .make_foreign_items(),
1478 _ => unreachable!(),
1481 _ => noop_flat_map_foreign_item(foreign_item, self),
1485 fn flat_map_generic_param(
1487 param: ast::GenericParam,
1488 ) -> SmallVec<[ast::GenericParam; 1]> {
1489 let mut param = configure!(self, param);
1491 if let Some(attr) = self.take_first_attr(&mut param) {
1495 Annotatable::GenericParam(param),
1496 AstFragmentKind::GenericParams,
1498 .make_generic_params();
1501 noop_flat_map_generic_param(param, self)
1504 fn visit_id(&mut self, id: &mut ast::NodeId) {
1506 debug_assert_eq!(*id, ast::DUMMY_NODE_ID);
1507 *id = self.cx.resolver.next_node_id()
1512 pub struct ExpansionConfig<'feat> {
1513 pub crate_name: String,
1514 pub features: Option<&'feat Features>,
1515 pub recursion_limit: Limit,
1516 pub trace_mac: bool,
1517 pub should_test: bool, // If false, strip `#[test]` nodes
1518 pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
1519 pub proc_macro_backtrace: bool, // If true, show backtraces for proc-macro panics
1522 impl<'feat> ExpansionConfig<'feat> {
1523 pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1527 recursion_limit: Limit::new(1024),
1531 proc_macro_backtrace: false,
1535 fn proc_macro_hygiene(&self) -> bool {
1536 self.features.map_or(false, |features| features.proc_macro_hygiene)