]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_expand/src/expand.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / compiler / rustc_expand / src / expand.rs
CommitLineData
e74abb32 1use crate::base::*;
dfeec247 2use crate::config::StripUnconfigured;
ba9703b0 3use crate::configure;
6a06907d 4use crate::hygiene::SyntaxContext;
e74abb32 5use crate::mbe::macro_rules::annotate_err_with_kind;
6a06907d 6use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
e74abb32
XL
7use crate::placeholders::{placeholder, PlaceholderExpander};
8
6a06907d 9use rustc_ast as ast;
74b04a01
XL
10use rustc_ast::mut_visit::*;
11use rustc_ast::ptr::P;
12use rustc_ast::token;
13use rustc_ast::tokenstream::TokenStream;
74b04a01 14use rustc_ast::visit::{self, AssocCtxt, Visitor};
136023e0 15use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs};
6a06907d
XL
16use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
17use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
74b04a01 18use rustc_ast_pretty::pprust;
17df50a5 19use rustc_attr::is_builtin_attr;
ba9703b0 20use rustc_data_structures::map_in_place::MapInPlace;
3dfed10e 21use rustc_data_structures::stack::ensure_sufficient_stack;
6a06907d 22use rustc_data_structures::sync::Lrc;
cdc7bbd5 23use rustc_errors::{Applicability, FatalError, PResult};
60c5eb7d 24use rustc_feature::Features;
136023e0
XL
25use rustc_parse::parser::{
26 AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma,
27};
60c5eb7d 28use rustc_parse::validate_attr;
74b04a01
XL
29use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
30use rustc_session::lint::BuiltinLintDiagnostics;
31use rustc_session::parse::{feature_err, ParseSess};
f9f354fc 32use rustc_session::Limit;
17df50a5 33use rustc_span::symbol::{sym, Ident};
136023e0 34use rustc_span::{FileName, LocalExpnId, Span};
9fa01778 35
9fa01778 36use smallvec::{smallvec, SmallVec};
9fa01778 37use std::ops::DerefMut;
ff7c6d11 38use std::path::PathBuf;
dfeec247 39use std::rc::Rc;
17df50a5 40use std::{iter, mem};
9e0c209e 41
8faf50e0
XL
42macro_rules! ast_fragments {
43 (
44 $($Kind:ident($AstTy:ty) {
45 $kind_name:expr;
9fa01778 46 $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)?
74b04a01 47 $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)?
8faf50e0
XL
48 fn $make_ast:ident;
49 })*
50 ) => {
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>>),
55 $($Kind($AstTy),)*
56 }
57
58 /// "Discriminant" of an AST fragment.
9e0c209e 59 #[derive(Copy, Clone, PartialEq, Eq)]
8faf50e0
XL
60 pub enum AstFragmentKind {
61 OptExpr,
62 $($Kind,)*
63 }
9e0c209e 64
8faf50e0 65 impl AstFragmentKind {
9e0c209e
SL
66 pub fn name(self) -> &'static str {
67 match self {
8faf50e0
XL
68 AstFragmentKind::OptExpr => "expression",
69 $(AstFragmentKind::$Kind => $kind_name,)*
9e0c209e
SL
70 }
71 }
92a42be0 72
8faf50e0 73 fn make_from<'a>(self, result: Box<dyn MacResult + 'a>) -> Option<AstFragment> {
9e0c209e 74 match self {
8faf50e0
XL
75 AstFragmentKind::OptExpr =>
76 result.make_expr().map(Some).map(AstFragment::OptExpr),
77 $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
9e0c209e
SL
78 }
79 }
80 }
1a4d82fc 81
8faf50e0 82 impl AstFragment {
e74abb32
XL
83 pub fn add_placeholders(&mut self, placeholders: &[NodeId]) {
84 if placeholders.is_empty() {
85 return;
86 }
87 match self {
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.
e74abb32
XL
91 macro _repeating($flat_map_ast_elt) {}
92 placeholder(AstFragmentKind::$Kind, *id, None).$make_ast()
93 })),)?)*
94 _ => panic!("unexpected AST fragment kind")
95 }
96 }
97
9e0c209e
SL
98 pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
99 match self {
8faf50e0
XL
100 AstFragment::OptExpr(expr) => expr,
101 _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
9e0c209e
SL
102 }
103 }
8faf50e0
XL
104
105 $(pub fn $make_ast(self) -> $AstTy {
9e0c209e 106 match self {
8faf50e0
XL
107 AstFragment::$Kind(ast) => ast,
108 _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
9e0c209e 109 }
8faf50e0 110 })*
9e0c209e 111
9fa01778 112 pub fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) {
9e0c209e 113 match self {
9fa01778
XL
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)
118 } else {
119 None
120 }
121 });
122 }
dc9dc135 123 $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
8faf50e0 124 $($(AstFragment::$Kind(ast) =>
dc9dc135 125 ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)*
9e0c209e
SL
126 }
127 }
1a4d82fc 128
476ff2be 129 pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
9e0c209e 130 match *self {
8faf50e0
XL
131 AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
132 AstFragment::OptExpr(None) => {}
dc9dc135 133 $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
8faf50e0 134 $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
74b04a01 135 visitor.$visit_ast_elt(ast_elt, $($args)*);
dc9dc135 136 })?)*
9e0c209e 137 }
3157f602 138 }
9e0c209e
SL
139 }
140
e74abb32
XL
141 impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> {
142 $(fn $make_ast(self: Box<crate::mbe::macro_rules::ParserAnyMacro<'a>>)
8faf50e0
XL
143 -> Option<$AstTy> {
144 Some(self.make(AstFragmentKind::$Kind).$make_ast())
9e0c209e 145 })*
1a4d82fc 146 }
9e0c209e 147 }
3157f602 148}
1a4d82fc 149
8faf50e0 150ast_fragments! {
9fa01778
XL
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; }
0bf4aa26 154 Stmts(SmallVec<[ast::Stmt; 1]>) {
74b04a01 155 "statement"; many fn flat_map_stmt; fn visit_stmt(); fn make_stmts;
0bf4aa26
XL
156 }
157 Items(SmallVec<[P<ast::Item>; 1]>) {
74b04a01 158 "item"; many fn flat_map_item; fn visit_item(); fn make_items;
0bf4aa26 159 }
74b04a01
XL
160 TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
161 "trait item";
162 many fn flat_map_trait_item;
163 fn visit_assoc_item(AssocCtxt::Trait);
164 fn make_trait_items;
8faf50e0 165 }
74b04a01
XL
166 ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
167 "impl item";
168 many fn flat_map_impl_item;
169 fn visit_assoc_item(AssocCtxt::Impl);
170 fn make_impl_items;
8faf50e0 171 }
74b04a01 172 ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
e1599b0c
XL
173 "foreign item";
174 many fn flat_map_foreign_item;
74b04a01 175 fn visit_foreign_item();
e1599b0c
XL
176 fn make_foreign_items;
177 }
178 Arms(SmallVec<[ast::Arm; 1]>) {
74b04a01 179 "match arm"; many fn flat_map_arm; fn visit_arm(); fn make_arms;
e1599b0c 180 }
6a06907d
XL
181 Fields(SmallVec<[ast::ExprField; 1]>) {
182 "field expression"; many fn flat_map_expr_field; fn visit_expr_field(); fn make_expr_fields;
e1599b0c 183 }
6a06907d 184 FieldPats(SmallVec<[ast::PatField; 1]>) {
e1599b0c 185 "field pattern";
6a06907d
XL
186 many fn flat_map_pat_field;
187 fn visit_pat_field();
188 fn make_pat_fields;
e1599b0c
XL
189 }
190 GenericParams(SmallVec<[ast::GenericParam; 1]>) {
191 "generic parameter";
192 many fn flat_map_generic_param;
74b04a01 193 fn visit_generic_param();
e1599b0c
XL
194 fn make_generic_params;
195 }
196 Params(SmallVec<[ast::Param; 1]>) {
74b04a01 197 "function parameter"; many fn flat_map_param; fn visit_param(); fn make_params;
e1599b0c 198 }
6a06907d 199 StructFields(SmallVec<[ast::FieldDef; 1]>) {
e1599b0c 200 "field";
6a06907d
XL
201 many fn flat_map_field_def;
202 fn visit_field_def();
203 fn make_field_defs;
e1599b0c
XL
204 }
205 Variants(SmallVec<[ast::Variant; 1]>) {
74b04a01 206 "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
8faf50e0 207 }
3157f602 208}
c1a9b12d 209
cdc7bbd5
XL
210pub enum SupportsMacroExpansion {
211 No,
212 Yes { supports_inner_attrs: bool },
213}
214
8faf50e0 215impl AstFragmentKind {
ba9703b0 216 crate fn dummy(self, span: Span) -> AstFragment {
416331ca 217 self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment")
9e0c209e
SL
218 }
219
cdc7bbd5 220 pub fn supports_macro_expansion(self) -> SupportsMacroExpansion {
fc512014
XL
221 match self {
222 AstFragmentKind::OptExpr
223 | AstFragmentKind::Expr
fc512014 224 | AstFragmentKind::Stmts
cdc7bbd5
XL
225 | AstFragmentKind::Ty
226 | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false },
227 AstFragmentKind::Items
fc512014
XL
228 | AstFragmentKind::TraitItems
229 | AstFragmentKind::ImplItems
cdc7bbd5
XL
230 | AstFragmentKind::ForeignItems => {
231 SupportsMacroExpansion::Yes { supports_inner_attrs: true }
232 }
fc512014
XL
233 AstFragmentKind::Arms
234 | AstFragmentKind::Fields
235 | AstFragmentKind::FieldPats
236 | AstFragmentKind::GenericParams
237 | AstFragmentKind::Params
238 | AstFragmentKind::StructFields
cdc7bbd5 239 | AstFragmentKind::Variants => SupportsMacroExpansion::No,
fc512014
XL
240 }
241 }
242
dfeec247
XL
243 fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(
244 self,
245 items: I,
246 ) -> AstFragment {
0531ce1d 247 let mut items = items.into_iter();
9e0c209e 248 match self {
dfeec247
XL
249 AstFragmentKind::Arms => {
250 AstFragment::Arms(items.map(Annotatable::expect_arm).collect())
251 }
252 AstFragmentKind::Fields => {
6a06907d 253 AstFragment::Fields(items.map(Annotatable::expect_expr_field).collect())
dfeec247
XL
254 }
255 AstFragmentKind::FieldPats => {
6a06907d 256 AstFragment::FieldPats(items.map(Annotatable::expect_pat_field).collect())
dfeec247
XL
257 }
258 AstFragmentKind::GenericParams => {
259 AstFragment::GenericParams(items.map(Annotatable::expect_generic_param).collect())
260 }
261 AstFragmentKind::Params => {
262 AstFragment::Params(items.map(Annotatable::expect_param).collect())
263 }
264 AstFragmentKind::StructFields => {
6a06907d 265 AstFragment::StructFields(items.map(Annotatable::expect_field_def).collect())
dfeec247
XL
266 }
267 AstFragmentKind::Variants => {
268 AstFragment::Variants(items.map(Annotatable::expect_variant).collect())
269 }
270 AstFragmentKind::Items => {
271 AstFragment::Items(items.map(Annotatable::expect_item).collect())
272 }
273 AstFragmentKind::ImplItems => {
274 AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect())
275 }
276 AstFragmentKind::TraitItems => {
277 AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect())
278 }
279 AstFragmentKind::ForeignItems => {
280 AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect())
281 }
282 AstFragmentKind::Stmts => {
283 AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect())
284 }
8faf50e0 285 AstFragmentKind::Expr => AstFragment::Expr(
dfeec247 286 items.next().expect("expected exactly one expression").expect_expr(),
0531ce1d 287 ),
dfeec247
XL
288 AstFragmentKind::OptExpr => {
289 AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
290 }
291 AstFragmentKind::Pat | AstFragmentKind::Ty => {
292 panic!("patterns and types aren't annotatable")
293 }
9e0c209e 294 }
3157f602
XL
295 }
296}
297
9e0c209e
SL
298pub struct Invocation {
299 pub kind: InvocationKind,
e1599b0c 300 pub fragment_kind: AstFragmentKind,
8bb4bdeb 301 pub expansion_data: ExpansionData,
9e0c209e
SL
302}
303
304pub enum InvocationKind {
305 Bang {
ba9703b0 306 mac: ast::MacCall,
9e0c209e
SL
307 span: Span,
308 },
309 Attr {
416331ca 310 attr: ast::Attribute,
6a06907d
XL
311 // Re-insertion position for inert attributes.
312 pos: usize,
8bb4bdeb 313 item: Annotatable,
416331ca
XL
314 // Required for resolving derive helper attributes.
315 derives: Vec<Path>,
8bb4bdeb
XL
316 },
317 Derive {
cc61c64b 318 path: Path,
9e0c209e
SL
319 item: Annotatable,
320 },
321}
322
e74abb32
XL
323impl 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.
330 match self {
6a06907d
XL
331 InvocationKind::Attr { item: Annotatable::FieldDef(field), .. }
332 | InvocationKind::Derive { item: Annotatable::FieldDef(field), .. }
dfeec247
XL
333 if field.ident.is_none() =>
334 {
335 Some(field.vis.clone())
336 }
e74abb32
XL
337 _ => None,
338 }
339 }
340}
341
9e0c209e 342impl Invocation {
8faf50e0 343 pub fn span(&self) -> Span {
416331ca
XL
344 match &self.kind {
345 InvocationKind::Bang { span, .. } => *span,
346 InvocationKind::Attr { attr, .. } => attr.span,
347 InvocationKind::Derive { path, .. } => path.span,
c1a9b12d 348 }
5bcae85e
SL
349 }
350}
c1a9b12d 351
dc9dc135 352pub struct MacroExpander<'a, 'b> {
9e0c209e 353 pub cx: &'a mut ExtCtxt<'b>,
a1dfa0c6 354 monotonic: bool, // cf. `cx.monotonic_expander()`
9e0c209e
SL
355}
356
357impl<'a, 'b> MacroExpander<'a, 'b> {
358 pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
dc9dc135 359 MacroExpander { cx, monotonic }
9e0c209e
SL
360 }
361
6a06907d
XL
362 // FIXME: Avoid visiting the crate as a `Mod` item,
363 // make crate a first class expansion target instead.
c30ab7b3 364 pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
17df50a5
XL
365 let file_path = match self.cx.source_map().span_to_filename(krate.span) {
366 FileName::Real(name) => name
367 .into_local_path()
368 .expect("attempting to resolve a file path in an external file"),
369 other => PathBuf::from(other.prefer_local().to_string()),
c30ab7b3 370 };
6a06907d
XL
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],
376 dir_path,
377 });
cc61c64b 378
b7449926 379 let krate_item = AstFragment::Items(smallvec![P(ast::Item {
9e0c209e
SL
380 attrs: krate.attrs,
381 span: krate.span,
6a06907d
XL
382 kind: ast::ItemKind::Mod(
383 Unsafe::No,
384 ModKind::Loaded(krate.items, Inline::Yes, krate.span)
385 ),
dc9dc135 386 ident: Ident::invalid(),
5bcae85e 387 id: ast::DUMMY_NODE_ID,
1b1a35ee
XL
388 vis: ast::Visibility {
389 span: krate.span.shrink_to_lo(),
390 kind: ast::VisibilityKind::Public,
391 tokens: None,
392 },
3b2f2976 393 tokens: None,
b7449926 394 })]);
9e0c209e 395
e1599b0c 396 match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
6a06907d
XL
397 Some(ast::Item {
398 attrs,
399 kind: ast::ItemKind::Mod(_, ModKind::Loaded(items, ..)),
400 ..
401 }) => {
9e0c209e 402 krate.attrs = attrs;
6a06907d 403 krate.items = items;
dfeec247 404 }
cc61c64b
XL
405 None => {
406 // Resolution failed so we return an empty expansion
407 krate.attrs = vec![];
6a06907d 408 krate.items = vec![];
dfeec247 409 }
74b04a01
XL
410 Some(ast::Item { span, kind, .. }) => {
411 krate.attrs = vec![];
6a06907d 412 krate.items = vec![];
74b04a01
XL
413 self.cx.span_err(
414 span,
415 &format!(
416 "expected crate top-level item to be a module after macro expansion, found {} {}",
417 kind.article(), kind.descr()
418 ),
419 );
cdc7bbd5
XL
420 // FIXME: this workaround issue #84569
421 FatalError.raise();
74b04a01 422 }
9e0c209e 423 };
7cac9316 424 self.cx.trace_macros_diag();
9e0c209e 425 krate
5bcae85e 426 }
1a4d82fc 427
e1599b0c
XL
428 // Recursively expand all macro invocations in this AST fragment.
429 pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
9e0c209e 430 let orig_expansion_data = self.cx.current_expansion.clone();
fc512014 431 let orig_force_mode = self.cx.force_mode;
9e0c209e 432
8faf50e0 433 // Collect all macro invocations and replace them with placeholders.
dfeec247
XL
434 let (mut fragment_with_placeholders, mut invocations) =
435 self.collect_invocations(input_fragment, &[]);
8faf50e0
XL
436
437 // Optimization: if we resolve all imports now,
438 // we'll be able to immediately resolve most of imported macros.
476ff2be 439 self.resolve_imports();
9e0c209e 440
b7449926 441 // Resolve paths in all invocations and produce output expanded fragments for them, but
8faf50e0
XL
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();
c30ab7b3
SL
447 let mut undetermined_invocations = Vec::new();
448 let (mut progress, mut force) = (false, !self.monotonic);
449 loop {
6a06907d 450 let (invoc, ext) = if let Some(invoc) = invocations.pop() {
c30ab7b3 451 invoc
c30ab7b3 452 } else {
476ff2be 453 self.resolve_imports();
dfeec247
XL
454 if undetermined_invocations.is_empty() {
455 break;
456 }
416331ca 457 invocations = mem::take(&mut undetermined_invocations);
c30ab7b3 458 force = !mem::replace(&mut progress, false);
fc512014
XL
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",
463 );
464 }
dfeec247 465 continue;
c30ab7b3
SL
466 };
467
6a06907d
XL
468 let ext = match ext {
469 Some(ext) => ext,
ba9703b0
XL
470 None => {
471 let eager_expansion_root = if self.monotonic {
472 invoc.expansion_data.id
473 } else {
474 orig_expansion_data.id
475 };
476 match self.cx.resolver.resolve_macro_invocation(
477 &invoc,
478 eager_expansion_root,
479 force,
480 ) {
6a06907d 481 Ok(ext) => ext,
ba9703b0
XL
482 Err(Indeterminate) => {
483 // Cannot resolve, will retry this invocation later.
484 undetermined_invocations.push((invoc, None));
485 continue;
486 }
487 }
c30ab7b3
SL
488 }
489 };
490
416331ca 491 let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
136023e0 492 let depth = depth - orig_expansion_data.depth;
9e0c209e 493 self.cx.current_expansion = invoc.expansion_data.clone();
fc512014 494 self.cx.force_mode = force;
9e0c209e 495
fc512014 496 let fragment_kind = invoc.fragment_kind;
6a06907d
XL
497 let (expanded_fragment, new_invocations) = match self.expand_invoc(invoc, &ext.kind) {
498 ExpandResult::Ready(fragment) => {
cdc7bbd5 499 let mut derive_invocations = Vec::new();
6a06907d
XL
500 let derive_placeholders = self
501 .cx
502 .resolver
503 .take_derive_resolutions(expn_id)
504 .map(|derives| {
cdc7bbd5 505 derive_invocations.reserve(derives.len());
6a06907d
XL
506 derives
507 .into_iter()
136023e0 508 .map(|(path, item, _exts)| {
6a06907d
XL
509 // FIXME: Consider using the derive resolutions (`_exts`)
510 // instead of enqueuing the derives to be resolved again later.
136023e0 511 let expn_id = LocalExpnId::fresh_empty();
cdc7bbd5 512 derive_invocations.push((
6a06907d 513 Invocation {
136023e0 514 kind: InvocationKind::Derive { path, item },
6a06907d
XL
515 fragment_kind,
516 expansion_data: ExpansionData {
517 id: expn_id,
518 ..self.cx.current_expansion.clone()
519 },
fc512014 520 },
6a06907d
XL
521 None,
522 ));
523 NodeId::placeholder_from_expn_id(expn_id)
524 })
525 .collect::<Vec<_>>()
526 })
527 .unwrap_or_default();
ea8adc8c 528
cdc7bbd5
XL
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)
8bb4bdeb 535 }
6a06907d
XL
536 ExpandResult::Retry(invoc) => {
537 if force {
538 self.cx.span_bug(
539 invoc.span(),
540 "expansion entered force mode but is still stuck",
541 );
542 } else {
543 // Cannot expand, will retry this invocation later.
544 undetermined_invocations.push((invoc, Some(ext)));
545 continue;
546 }
547 }
9e0c209e
SL
548 };
549
ba9703b0 550 progress = true;
8faf50e0
XL
551 if expanded_fragments.len() < depth {
552 expanded_fragments.push(Vec::new());
9e0c209e 553 }
416331ca 554 expanded_fragments[depth - 1].push((expn_id, expanded_fragment));
ba9703b0 555 invocations.extend(new_invocations.into_iter().rev());
9e0c209e
SL
556 }
557
558 self.cx.current_expansion = orig_expansion_data;
fc512014 559 self.cx.force_mode = orig_force_mode;
9e0c209e 560
8faf50e0 561 // Finally incorporate all the expanded macros into the input AST fragment.
9e0c209e 562 let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
8faf50e0 563 while let Some(expanded_fragments) = expanded_fragments.pop() {
e1599b0c 564 for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
dfeec247
XL
565 placeholder_expander
566 .add(NodeId::placeholder_from_expn_id(expn_id), expanded_fragment);
9e0c209e
SL
567 }
568 }
9fa01778
XL
569 fragment_with_placeholders.mut_visit_with(&mut placeholder_expander);
570 fragment_with_placeholders
9e0c209e
SL
571 }
572
476ff2be
SL
573 fn resolve_imports(&mut self) {
574 if self.monotonic {
476ff2be 575 self.cx.resolver.resolve_imports();
476ff2be
SL
576 }
577 }
578
9fa01778 579 /// Collects all macro invocations reachable at this time in this AST fragment, and replace
8faf50e0
XL
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.
dfeec247
XL
583 fn collect_invocations(
584 &mut self,
585 mut fragment: AstFragment,
586 extra_placeholders: &[NodeId],
6a06907d 587 ) -> (AstFragment, Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>) {
9fa01778 588 // Resolve `$crate`s in the fragment for pretty-printing.
416331ca 589 self.cx.resolver.resolve_dollar_crates();
9fa01778
XL
590
591 let invocations = {
9e0c209e 592 let mut collector = InvocationCollector {
cdc7bbd5
XL
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`
5869c6ff
XL
598 cfg: StripUnconfigured {
599 sess: &self.cx.sess,
600 features: self.cx.ecfg.features,
cdc7bbd5 601 config_tokens: false,
5869c6ff 602 },
9e0c209e
SL
603 cx: self.cx,
604 invocations: Vec::new(),
605 monotonic: self.monotonic,
606 };
9fa01778 607 fragment.mut_visit_with(&mut collector);
e74abb32 608 fragment.add_placeholders(extra_placeholders);
9fa01778 609 collector.invocations
9e0c209e 610 };
9e0c209e
SL
611
612 if self.monotonic {
dfeec247
XL
613 self.cx
614 .resolver
615 .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);
9e0c209e
SL
616 }
617
9fa01778 618 (fragment, invocations)
9e0c209e
SL
619 }
620
74b04a01
XL
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;
624 self.cx
625 .struct_span_err(
dfeec247
XL
626 expn_data.call_site,
627 &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
74b04a01
XL
628 )
629 .help(&format!(
630 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
631 suggested_limit, self.cx.ecfg.crate_name,
632 ))
633 .emit();
634 self.cx.trace_macros_diag();
74b04a01
XL
635 }
636
637 /// A macro's expansion does not fit in this fragment kind.
638 /// For example, a non-type macro in a type position.
ba9703b0 639 fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
74b04a01
XL
640 let msg = format!(
641 "non-{kind} macro in {kind} position: {path}",
642 kind = kind.name(),
643 path = pprust::path_to_string(&mac.path),
644 );
645 self.cx.span_err(span, &msg);
646 self.cx.trace_macros_diag();
647 }
648
ba9703b0
XL
649 fn expand_invoc(
650 &mut self,
651 invoc: Invocation,
652 ext: &SyntaxExtensionKind,
653 ) -> ExpandResult<AstFragment, Invocation> {
654 let recursion_limit =
655 self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
f9f354fc 656 if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
ba9703b0
XL
657 if self.cx.reduced_recursion_limit.is_none() {
658 self.error_recursion_limit_reached();
659 }
660
661 // Reduce the recursion limit by half each time it triggers.
662 self.cx.reduced_recursion_limit = Some(recursion_limit / 2);
663
664 return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span()));
9e0c209e 665 }
cc61c64b 666
e74abb32 667 let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
ba9703b0 668 ExpandResult::Ready(match invoc.kind {
416331ca
XL
669 InvocationKind::Bang { mac, .. } => match ext {
670 SyntaxExtensionKind::Bang(expander) => {
ba9703b0
XL
671 let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) {
672 Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
673 Ok(ts) => ts,
674 };
e74abb32 675 self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
dc9dc135 676 }
416331ca
XL
677 SyntaxExtensionKind::LegacyBang(expander) => {
678 let prev = self.cx.current_expansion.prior_type_ascription;
e1599b0c 679 self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription;
60c5eb7d 680 let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
416331ca
XL
681 let result = if let Some(result) = fragment_kind.make_from(tok_result) {
682 result
683 } else {
74b04a01 684 self.error_wrong_fragment_kind(fragment_kind, &mac, span);
416331ca
XL
685 fragment_kind.dummy(span)
686 };
687 self.cx.current_expansion.prior_type_ascription = prev;
688 result
689 }
dfeec247
XL
690 _ => unreachable!(),
691 },
6a06907d 692 InvocationKind::Attr { attr, pos, mut item, derives } => match ext {
416331ca 693 SyntaxExtensionKind::Attr(expander) => {
e74abb32 694 self.gate_proc_macro_input(&item);
416331ca 695 self.gate_proc_macro_attr_item(span, &item);
cdc7bbd5
XL
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
705 // module
706 (item_inner.ident.name.is_empty() || !matches!(mod_kind, ast::ModKind::Loaded(_, Inline::Yes, _)));
707 }
708 }
709 let tokens = if fake_tokens {
710 rustc_parse::fake_token_stream(
5869c6ff
XL
711 &self.cx.sess.parse_sess,
712 &item.into_nonterminal(),
cdc7bbd5
XL
713 )
714 } else {
715 item.into_tokens(&self.cx.sess.parse_sess)
5869c6ff 716 };
74b04a01
XL
717 let attr_item = attr.unwrap_normal_item();
718 if let MacArgs::Eq(..) = attr_item.args {
60c5eb7d
XL
719 self.cx.span_err(span, "key-value macro attributes are not supported");
720 }
ba9703b0
XL
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)),
724 Ok(ts) => ts,
725 };
74b04a01 726 self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span)
416331ca
XL
727 }
728 SyntaxExtensionKind::LegacyAttr(expander) => {
3dfed10e 729 match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) {
416331ca 730 Ok(meta) => {
ba9703b0
XL
731 let items = match expander.expand(self.cx, span, &meta, item) {
732 ExpandResult::Ready(items) => items,
fc512014 733 ExpandResult::Retry(item) => {
ba9703b0 734 // Reassemble the original invocation for retrying.
fc512014 735 return ExpandResult::Retry(Invocation {
6a06907d 736 kind: InvocationKind::Attr { attr, pos, item, derives },
fc512014
XL
737 ..invoc
738 });
ba9703b0
XL
739 }
740 };
cdc7bbd5
XL
741 if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
742 let msg =
743 "removing an expression is not supported in this position";
744 self.cx.span_err(span, msg);
745 fragment_kind.dummy(span)
746 } else {
747 fragment_kind.expect_from_annotatables(items)
748 }
416331ca
XL
749 }
750 Err(mut err) => {
751 err.emit();
752 fragment_kind.dummy(span)
753 }
754 }
755 }
756 SyntaxExtensionKind::NonMacroAttr { mark_used } => {
3dfed10e 757 self.cx.sess.mark_attr_known(&attr);
416331ca 758 if *mark_used {
3dfed10e 759 self.cx.sess.mark_attr_used(&attr);
416331ca 760 }
6a06907d 761 item.visit_attrs(|attrs| attrs.insert(pos, attr));
416331ca
XL
762 fragment_kind.expect_from_annotatables(iter::once(item))
763 }
dfeec247
XL
764 _ => unreachable!(),
765 },
416331ca 766 InvocationKind::Derive { path, item } => match ext {
dfeec247
XL
767 SyntaxExtensionKind::Derive(expander)
768 | SyntaxExtensionKind::LegacyDerive(expander) => {
e74abb32
XL
769 if let SyntaxExtensionKind::Derive(..) = ext {
770 self.gate_proc_macro_input(&item);
771 }
772 let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
ba9703b0
XL
773 let items = match expander.expand(self.cx, span, &meta, item) {
774 ExpandResult::Ready(items) => items,
fc512014 775 ExpandResult::Retry(item) => {
ba9703b0 776 // Reassemble the original invocation for retrying.
fc512014
XL
777 return ExpandResult::Retry(Invocation {
778 kind: InvocationKind::Derive { path: meta.path, item },
779 ..invoc
780 });
ba9703b0
XL
781 }
782 };
416331ca
XL
783 fragment_kind.expect_from_annotatables(items)
784 }
dfeec247
XL
785 _ => unreachable!(),
786 },
ba9703b0 787 })
9e0c209e
SL
788 }
789
83c7162d 790 fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
e74abb32 791 let kind = match item {
dfeec247
XL
792 Annotatable::Item(_)
793 | Annotatable::TraitItem(_)
e74abb32
XL
794 | Annotatable::ImplItem(_)
795 | Annotatable::ForeignItem(_) => return,
fc512014
XL
796 Annotatable::Stmt(stmt) => {
797 // Attributes are stable on item statements,
798 // but unstable on all other kinds of statements
799 if stmt.is_item() {
800 return;
801 }
802 "statements"
803 }
e74abb32 804 Annotatable::Expr(_) => "expressions",
e1599b0c 805 Annotatable::Arm(..)
6a06907d
XL
806 | Annotatable::ExprField(..)
807 | Annotatable::PatField(..)
e1599b0c
XL
808 | Annotatable::GenericParam(..)
809 | Annotatable::Param(..)
6a06907d 810 | Annotatable::FieldDef(..)
dfeec247 811 | Annotatable::Variant(..) => panic!("unexpected annotatable"),
83c7162d 812 };
e74abb32 813 if self.cx.ecfg.proc_macro_hygiene() {
dfeec247 814 return;
e74abb32 815 }
60c5eb7d 816 feature_err(
3dfed10e 817 &self.cx.sess.parse_sess,
e74abb32 818 sym::proc_macro_hygiene,
83c7162d 819 span,
83c7162d 820 &format!("custom attributes cannot be applied to {}", kind),
60c5eb7d
XL
821 )
822 .emit();
83c7162d
XL
823 }
824
e74abb32
XL
825 fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
826 struct GateProcMacroInput<'a> {
94b46f34
XL
827 parse_sess: &'a ParseSess,
828 }
829
e74abb32
XL
830 impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
831 fn visit_item(&mut self, item: &'ast ast::Item) {
832 match &item.kind {
6a06907d
XL
833 ast::ItemKind::Mod(_, mod_kind)
834 if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
835 {
60c5eb7d 836 feature_err(
e74abb32
XL
837 self.parse_sess,
838 sym::proc_macro_hygiene,
839 item.span,
e74abb32 840 "non-inline modules in proc macro input are unstable",
60c5eb7d
XL
841 )
842 .emit();
e74abb32
XL
843 }
844 _ => {}
94b46f34 845 }
94b46f34 846
e74abb32 847 visit::walk_item(self, item);
94b46f34 848 }
e74abb32
XL
849 }
850
851 if !self.cx.ecfg.proc_macro_hygiene() {
3dfed10e
XL
852 annotatable
853 .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess });
94b46f34
XL
854 }
855 }
856
416331ca
XL
857 fn parse_ast_fragment(
858 &mut self,
859 toks: TokenStream,
860 kind: AstFragmentKind,
861 path: &Path,
862 span: Span,
863 ) -> AstFragment {
e1599b0c 864 let mut parser = self.cx.new_parser_from_tts(toks);
74b04a01 865 match parse_ast_fragment(&mut parser, kind) {
8faf50e0 866 Ok(fragment) => {
e74abb32 867 ensure_complete_parse(&mut parser, path, kind.name(), span);
416331ca 868 fragment
ff7c6d11 869 }
9e0c209e 870 Err(mut err) => {
5869c6ff
XL
871 if err.span.is_dummy() {
872 err.set_span(span);
873 }
416331ca 874 annotate_err_with_kind(&mut err, kind, span);
9cc50fc6 875 err.emit();
ea8adc8c 876 self.cx.trace_macros_diag();
ff7c6d11 877 kind.dummy(span)
1a4d82fc 878 }
ff7c6d11 879 }
9e0c209e
SL
880 }
881}
970d7e83 882
e74abb32
XL
883pub fn parse_ast_fragment<'a>(
884 this: &mut Parser<'a>,
885 kind: AstFragmentKind,
e74abb32
XL
886) -> PResult<'a, AstFragment> {
887 Ok(match kind {
888 AstFragmentKind::Items => {
889 let mut items = SmallVec::new();
5869c6ff 890 while let Some(item) = this.parse_item(ForceCollect::No)? {
e74abb32 891 items.push(item);
9e0c209e 892 }
e74abb32
XL
893 AstFragment::Items(items)
894 }
895 AstFragmentKind::TraitItems => {
896 let mut items = SmallVec::new();
cdc7bbd5 897 while let Some(item) = this.parse_trait_item(ForceCollect::No)? {
74b04a01 898 items.extend(item);
9e0c209e 899 }
e74abb32
XL
900 AstFragment::TraitItems(items)
901 }
902 AstFragmentKind::ImplItems => {
903 let mut items = SmallVec::new();
cdc7bbd5 904 while let Some(item) = this.parse_impl_item(ForceCollect::No)? {
74b04a01 905 items.extend(item);
9e0c209e 906 }
e74abb32
XL
907 AstFragment::ImplItems(items)
908 }
909 AstFragmentKind::ForeignItems => {
910 let mut items = SmallVec::new();
cdc7bbd5 911 while let Some(item) = this.parse_foreign_item(ForceCollect::No)? {
74b04a01 912 items.extend(item);
83c7162d 913 }
e74abb32
XL
914 AstFragment::ForeignItems(items)
915 }
916 AstFragmentKind::Stmts => {
917 let mut stmts = SmallVec::new();
74b04a01
XL
918 // Won't make progress on a `}`.
919 while this.token != token::Eof && this.token != token::CloseDelim(token::Brace) {
29967ef6 920 if let Some(stmt) = this.parse_full_stmt(AttemptLocalParseRecovery::Yes)? {
e74abb32 921 stmts.push(stmt);
9e0c209e 922 }
223e47cc 923 }
e74abb32
XL
924 AstFragment::Stmts(stmts)
925 }
926 AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
927 AstFragmentKind::OptExpr => {
928 if this.token != token::Eof {
929 AstFragment::OptExpr(Some(this.parse_expr()?))
930 } else {
931 AstFragment::OptExpr(None)
932 }
dfeec247 933 }
e74abb32 934 AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
136023e0
XL
935 AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_alt(
936 None,
937 RecoverComma::No,
938 RecoverColon::Yes,
939 )?),
e74abb32
XL
940 AstFragmentKind::Arms
941 | AstFragmentKind::Fields
942 | AstFragmentKind::FieldPats
943 | AstFragmentKind::GenericParams
944 | AstFragmentKind::Params
945 | AstFragmentKind::StructFields
dfeec247 946 | AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
e74abb32
XL
947 })
948}
a1dfa0c6 949
e74abb32
XL
950pub fn ensure_complete_parse<'a>(
951 this: &mut Parser<'a>,
952 macro_path: &Path,
953 kind_name: &str,
954 span: Span,
955) {
956 if this.token != token::Eof {
dfeec247
XL
957 let token = pprust::token_to_string(&this.token);
958 let msg = format!("macro expansion ignores token `{}` and any following", token);
e74abb32
XL
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");
963 let msg = format!(
964 "the usage of `{}!` is likely invalid in {} context",
965 pprust::path_to_string(macro_path),
966 kind_name,
967 );
968 err.note(&msg);
969 let semi_span = this.sess.source_map().next_point(span);
970
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" => {
974 err.span_suggestion(
975 semi_span,
976 "you might be missing a semicolon here",
977 ";".to_owned(),
978 Applicability::MaybeIncorrect,
979 );
a1dfa0c6 980 }
e74abb32 981 _ => {}
1a4d82fc 982 }
e74abb32 983 err.emit();
1a4d82fc 984 }
1a4d82fc
JJ
985}
986
dc9dc135 987struct InvocationCollector<'a, 'b> {
9e0c209e
SL
988 cx: &'a mut ExtCtxt<'b>,
989 cfg: StripUnconfigured<'a>,
6a06907d 990 invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
9e0c209e
SL
991 monotonic: bool,
992}
223e47cc 993
9e0c209e 994impl<'a, 'b> InvocationCollector<'a, 'b> {
8faf50e0 995 fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
136023e0 996 let expn_id = LocalExpnId::fresh_empty();
e74abb32 997 let vis = kind.placeholder_visibility();
ba9703b0
XL
998 self.invocations.push((
999 Invocation {
1000 kind,
1001 fragment_kind,
1002 expansion_data: ExpansionData {
1003 id: expn_id,
1004 depth: self.cx.current_expansion.depth + 1,
1005 ..self.cx.current_expansion.clone()
1006 },
c30ab7b3 1007 },
ba9703b0
XL
1008 None,
1009 ));
e74abb32 1010 placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
1a4d82fc 1011 }
223e47cc 1012
ba9703b0
XL
1013 fn collect_bang(
1014 &mut self,
1015 mac: ast::MacCall,
1016 span: Span,
1017 kind: AstFragmentKind,
1018 ) -> AstFragment {
416331ca 1019 self.collect(kind, InvocationKind::Bang { mac, span })
9e0c209e 1020 }
85aaf69f 1021
dfeec247
XL
1022 fn collect_attr(
1023 &mut self,
6a06907d 1024 (attr, pos, derives): (ast::Attribute, usize, Vec<Path>),
dfeec247
XL
1025 item: Annotatable,
1026 kind: AstFragmentKind,
dfeec247 1027 ) -> AstFragment {
6a06907d 1028 self.collect(kind, InvocationKind::Attr { attr, pos, item, derives })
b7449926
XL
1029 }
1030
6a06907d
XL
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).
fc512014 1034 fn take_first_attr(
dfeec247 1035 &mut self,
6a06907d
XL
1036 item: &mut impl AstLike,
1037 ) -> Option<(ast::Attribute, usize, Vec<Path>)> {
1038 let mut attr = None;
1039
1040 item.visit_attrs(|attrs| {
1041 attr = attrs
1042 .iter()
1043 .position(|a| !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a))
1044 .map(|attr_pos| {
1045 let attr = attrs.remove(attr_pos);
1046 let following_derives = attrs[attr_pos..]
1047 .iter()
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,
1053 path,
1054 ..
1055 }) => Some(path),
1056 _ => None,
1057 })
1058 .collect();
1059
1060 (attr, attr_pos, following_derives)
1061 })
0531ce1d
XL
1062 });
1063
6a06907d 1064 attr
0531ce1d
XL
1065 }
1066
6a06907d 1067 fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
9e0c209e 1068 self.cfg.configure(node)
d9579d0f 1069 }
32a655c1
SL
1070
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]) {
32a655c1 1074 let features = self.cx.ecfg.features.unwrap();
cdc7bbd5
XL
1075 let mut attrs = attrs.iter().peekable();
1076 let mut span: Option<Span> = None;
1077 while let Some(attr) = attrs.next() {
3dfed10e
XL
1078 rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
1079 validate_attr::check_meta(&self.cx.sess.parse_sess, attr);
cdc7bbd5
XL
1080
1081 let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
1082 span = Some(current_span);
1083
1084 if attrs.peek().map_or(false, |next_attr| next_attr.doc_str().is_some()) {
1085 continue;
1086 }
1087
74b04a01 1088 if attr.doc_str().is_some() {
3dfed10e 1089 self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
74b04a01 1090 &UNUSED_DOC_COMMENTS,
cdc7bbd5 1091 current_span,
74b04a01
XL
1092 ast::CRATE_NODE_ID,
1093 "unused doc comment",
1094 BuiltinLintDiagnostics::UnusedDocComment(attr.span),
1095 );
1096 }
32a655c1
SL
1097 }
1098 }
85aaf69f
SL
1099}
1100
136023e0
XL
1101/// Wraps a call to `noop_visit_*` / `noop_flat_map_*`
1102/// for an AST node that supports attributes
1103/// (see the `Annotatable` enum)
1104/// This method assigns a `NodeId`, and sets that `NodeId`
1105/// as our current 'lint node id'. If a macro call is found
1106/// inside this AST node, we will use this AST node's `NodeId`
1107/// to emit lints associated with that macro (allowing
1108/// `#[allow]` / `#[deny]` to be applied close to
1109/// the macro invocation).
1110///
1111/// Do *not* call this for a macro AST node
1112/// (e.g. `ExprKind::MacCall`) - we cannot emit lints
1113/// at these AST nodes, since they are removed and
1114/// replaced with the result of macro expansion.
1115///
1116/// All other `NodeId`s are assigned by `visit_id`.
1117/// * `self` is the 'self' parameter for the current method,
1118/// * `id` is a mutable reference to the `NodeId` field
1119/// of the current AST node.
1120/// * `closure` is a closure that executes the
1121/// `noop_visit_*` / `noop_flat_map_*` method
1122/// for the current AST node.
1123macro_rules! assign_id {
1124 ($self:ident, $id:expr, $closure:expr) => {{
1125 let old_id = $self.cx.current_expansion.lint_node_id;
1126 if $self.monotonic {
1127 debug_assert_eq!(*$id, ast::DUMMY_NODE_ID);
1128 let new_id = $self.cx.resolver.next_node_id();
1129 *$id = new_id;
1130 $self.cx.current_expansion.lint_node_id = new_id;
1131 }
1132 let ret = ($closure)();
1133 $self.cx.current_expansion.lint_node_id = old_id;
1134 ret
1135 }};
1136}
1137
9fa01778
XL
1138impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1139 fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
1140 self.cfg.configure_expr(expr);
1141 visit_clobber(expr.deref_mut(), |mut expr| {
6a06907d 1142 if let Some(attr) = self.take_first_attr(&mut expr) {
a1dfa0c6
XL
1143 // Collect the invoc regardless of whether or not attributes are permitted here
1144 // expansion will eat the attribute so it won't error later.
6a06907d 1145 self.cfg.maybe_emit_expr_attr_err(&attr.0);
a1dfa0c6
XL
1146
1147 // AstFragmentKind::Expr requires the macro to emit an expression.
dfeec247 1148 return self
fc512014 1149 .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::Expr)
a1dfa0c6 1150 .make_expr()
dfeec247 1151 .into_inner();
a1dfa0c6 1152 }
0531ce1d 1153
ba9703b0 1154 if let ast::ExprKind::MacCall(mac) = expr.kind {
a1dfa0c6 1155 self.check_attributes(&expr.attrs);
dfeec247 1156 self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
a1dfa0c6 1157 } else {
136023e0
XL
1158 assign_id!(self, &mut expr.id, || {
1159 ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self));
1160 });
9fa01778 1161 expr
a1dfa0c6 1162 }
9fa01778 1163 });
c34b1796 1164 }
223e47cc 1165
136023e0
XL
1166 // This is needed in order to set `lint_node_id` for `let` statements
1167 fn visit_local(&mut self, local: &mut P<Local>) {
1168 assign_id!(self, &mut local.id, || noop_visit_local(local, self));
1169 }
1170
e1599b0c
XL
1171 fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
1172 let mut arm = configure!(self, arm);
1173
fc512014 1174 if let Some(attr) = self.take_first_attr(&mut arm) {
dfeec247 1175 return self
fc512014 1176 .collect_attr(attr, Annotatable::Arm(arm), AstFragmentKind::Arms)
dfeec247 1177 .make_arms();
e1599b0c
XL
1178 }
1179
136023e0 1180 assign_id!(self, &mut arm.id, || noop_flat_map_arm(arm, self))
e1599b0c
XL
1181 }
1182
6a06907d 1183 fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
e1599b0c
XL
1184 let mut field = configure!(self, field);
1185
fc512014 1186 if let Some(attr) = self.take_first_attr(&mut field) {
dfeec247 1187 return self
6a06907d
XL
1188 .collect_attr(attr, Annotatable::ExprField(field), AstFragmentKind::Fields)
1189 .make_expr_fields();
e1599b0c
XL
1190 }
1191
136023e0 1192 assign_id!(self, &mut field.id, || noop_flat_map_expr_field(field, self))
e1599b0c
XL
1193 }
1194
6a06907d 1195 fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
e1599b0c
XL
1196 let mut fp = configure!(self, fp);
1197
fc512014 1198 if let Some(attr) = self.take_first_attr(&mut fp) {
dfeec247 1199 return self
6a06907d
XL
1200 .collect_attr(attr, Annotatable::PatField(fp), AstFragmentKind::FieldPats)
1201 .make_pat_fields();
e1599b0c
XL
1202 }
1203
136023e0 1204 assign_id!(self, &mut fp.id, || noop_flat_map_pat_field(fp, self))
e1599b0c
XL
1205 }
1206
1207 fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
1208 let mut p = configure!(self, p);
1209
fc512014 1210 if let Some(attr) = self.take_first_attr(&mut p) {
dfeec247 1211 return self
fc512014 1212 .collect_attr(attr, Annotatable::Param(p), AstFragmentKind::Params)
dfeec247 1213 .make_params();
e1599b0c
XL
1214 }
1215
136023e0 1216 assign_id!(self, &mut p.id, || noop_flat_map_param(p, self))
e1599b0c
XL
1217 }
1218
6a06907d 1219 fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
e1599b0c
XL
1220 let mut sf = configure!(self, sf);
1221
fc512014 1222 if let Some(attr) = self.take_first_attr(&mut sf) {
dfeec247 1223 return self
6a06907d
XL
1224 .collect_attr(attr, Annotatable::FieldDef(sf), AstFragmentKind::StructFields)
1225 .make_field_defs();
e1599b0c
XL
1226 }
1227
136023e0 1228 assign_id!(self, &mut sf.id, || noop_flat_map_field_def(sf, self))
e1599b0c
XL
1229 }
1230
1231 fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
1232 let mut variant = configure!(self, variant);
1233
fc512014 1234 if let Some(attr) = self.take_first_attr(&mut variant) {
dfeec247 1235 return self
fc512014 1236 .collect_attr(attr, Annotatable::Variant(variant), AstFragmentKind::Variants)
dfeec247 1237 .make_variants();
e1599b0c
XL
1238 }
1239
136023e0 1240 assign_id!(self, &mut variant.id, || noop_flat_map_variant(variant, self))
e1599b0c
XL
1241 }
1242
9fa01778 1243 fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
a1dfa0c6
XL
1244 let expr = configure!(self, expr);
1245 expr.filter_map(|mut expr| {
6a06907d
XL
1246 if let Some(attr) = self.take_first_attr(&mut expr) {
1247 self.cfg.maybe_emit_expr_attr_err(&attr.0);
0531ce1d 1248
dfeec247 1249 return self
fc512014 1250 .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr)
a1dfa0c6 1251 .make_opt_expr()
dfeec247 1252 .map(|expr| expr.into_inner());
a1dfa0c6 1253 }
0531ce1d 1254
ba9703b0 1255 if let ast::ExprKind::MacCall(mac) = expr.kind {
a1dfa0c6
XL
1256 self.check_attributes(&expr.attrs);
1257 self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr)
1258 .make_opt_expr()
1259 .map(|expr| expr.into_inner())
1260 } else {
136023e0
XL
1261 assign_id!(self, &mut expr.id, || {
1262 Some({
1263 noop_visit_expr(&mut expr, self);
1264 expr
1265 })
dfeec247 1266 })
a1dfa0c6
XL
1267 }
1268 })
3157f602 1269 }
3157f602 1270
9fa01778 1271 fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
e74abb32 1272 match pat.kind {
ba9703b0 1273 PatKind::MacCall(_) => {}
9fa01778 1274 _ => return noop_visit_pat(pat, self),
e9174d1e 1275 }
e9174d1e 1276
dfeec247 1277 visit_clobber(pat, |mut pat| match mem::replace(&mut pat.kind, PatKind::Wild) {
ba9703b0
XL
1278 PatKind::MacCall(mac) => {
1279 self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat()
1280 }
dfeec247 1281 _ => unreachable!(),
9fa01778 1282 });
9e0c209e 1283 }
e9174d1e 1284
9fa01778
XL
1285 fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
1286 let mut stmt = configure!(self, stmt);
1a4d82fc 1287
0531ce1d
XL
1288 // we'll expand attributes on expressions separately
1289 if !stmt.is_expr() {
6a06907d 1290 if let Some(attr) = self.take_first_attr(&mut stmt) {
dfeec247 1291 return self
fc512014 1292 .collect_attr(attr, Annotatable::Stmt(P(stmt)), AstFragmentKind::Stmts)
dfeec247 1293 .make_stmts();
0531ce1d 1294 }
0531ce1d 1295 }
9e0c209e 1296
ba9703b0 1297 if let StmtKind::MacCall(mac) = stmt.kind {
fc512014 1298 let MacCallStmt { mac, style, attrs, tokens: _ } = mac.into_inner();
0531ce1d 1299 self.check_attributes(&attrs);
dfeec247
XL
1300 let mut placeholder =
1301 self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts();
0531ce1d
XL
1302
1303 // If this is a macro invocation with a semicolon, then apply that
1304 // semicolon to the final statement produced by expansion.
1305 if style == MacStmtStyle::Semicolon {
1306 if let Some(stmt) = placeholder.pop() {
1307 placeholder.push(stmt.add_trailing_semicolon());
1308 }
9e0c209e 1309 }
0531ce1d
XL
1310
1311 return placeholder;
5bcae85e 1312 }
9e0c209e 1313
0531ce1d 1314 // The placeholder expander gives ids to statements, so we avoid folding the id here.
136023e0
XL
1315 // We don't use `assign_id!` - it will be called when we visit statement's contents
1316 // (e.g. an expression, item, or local)
fc512014 1317 let ast::Stmt { id, kind, span } = stmt;
dfeec247
XL
1318 noop_flat_map_stmt_kind(kind, self)
1319 .into_iter()
fc512014 1320 .map(|kind| ast::Stmt { id, kind, span })
dfeec247 1321 .collect()
1a4d82fc 1322 }
3157f602 1323
9fa01778 1324 fn visit_block(&mut self, block: &mut P<Block>) {
6a06907d
XL
1325 let orig_dir_ownership = mem::replace(
1326 &mut self.cx.current_expansion.dir_ownership,
1327 DirOwnership::UnownedViaBlock,
1328 );
9fa01778 1329 noop_visit_block(block, self);
6a06907d 1330 self.cx.current_expansion.dir_ownership = orig_dir_ownership;
3157f602
XL
1331 }
1332
9fa01778
XL
1333 fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
1334 let mut item = configure!(self, item);
9e0c209e 1335
fc512014 1336 if let Some(attr) = self.take_first_attr(&mut item) {
dfeec247 1337 return self
fc512014 1338 .collect_attr(attr, Annotatable::Item(item), AstFragmentKind::Items)
dfeec247 1339 .make_items();
3157f602
XL
1340 }
1341
ba9703b0
XL
1342 let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
1343 let ident = item.ident;
1344 let span = item.span;
1345
e74abb32 1346 match item.kind {
ba9703b0
XL
1347 ast::ItemKind::MacCall(..) => {
1348 item.attrs = attrs;
32a655c1 1349 self.check_attributes(&item.attrs);
e74abb32 1350 item.and_then(|item| match item.kind {
29967ef6
XL
1351 ItemKind::MacCall(mac) => {
1352 self.collect_bang(mac, span, AstFragmentKind::Items).make_items()
1353 }
9e0c209e
SL
1354 _ => unreachable!(),
1355 })
3157f602 1356 }
6a06907d
XL
1357 ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => {
1358 let (file_path, dir_path, dir_ownership) = match mod_kind {
1359 ModKind::Loaded(_, inline, _) => {
1360 // Inline `mod foo { ... }`, but we still need to push directories.
1361 let (dir_path, dir_ownership) = mod_dir_path(
1362 &self.cx.sess,
1363 ident,
1364 &attrs,
1365 &self.cx.current_expansion.module,
1366 self.cx.current_expansion.dir_ownership,
1367 *inline,
1368 );
1369 item.attrs = attrs;
1370 (None, dir_path, dir_ownership)
ba9703b0 1371 }
6a06907d
XL
1372 ModKind::Unloaded => {
1373 // We have an outline `mod foo;` so we need to parse the file.
1374 let old_attrs_len = attrs.len();
1375 let ParsedExternalMod {
1376 mut items,
1377 inner_span,
1378 file_path,
1379 dir_path,
1380 dir_ownership,
1381 } = parse_external_mod(
1382 &self.cx.sess,
1383 ident,
1384 span,
1385 &self.cx.current_expansion.module,
1386 self.cx.current_expansion.dir_ownership,
1387 &mut attrs,
1388 );
1389
1390 if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
1391 (attrs, items) = extern_mod_loaded(ident, attrs, items, inner_span);
1392 }
ba9703b0 1393
6a06907d
XL
1394 *mod_kind = ModKind::Loaded(items, Inline::No, inner_span);
1395 item.attrs = attrs;
1396 if item.attrs.len() > old_attrs_len {
1397 // If we loaded an out-of-line module and added some inner attributes,
1398 // then we need to re-configure it and re-collect attributes for
1399 // resolution and expansion.
1400 item = configure!(self, item);
1401
1402 if let Some(attr) = self.take_first_attr(&mut item) {
1403 return self
1404 .collect_attr(
1405 attr,
1406 Annotatable::Item(item),
1407 AstFragmentKind::Items,
1408 )
1409 .make_items();
ba9703b0 1410 }
ba9703b0 1411 }
6a06907d
XL
1412 (Some(file_path), dir_path, dir_ownership)
1413 }
ba9703b0 1414 };
3157f602 1415
ba9703b0 1416 // Set the module info before we flat map.
6a06907d 1417 let mut module = self.cx.current_expansion.module.with_dir_path(dir_path);
ba9703b0 1418 module.mod_path.push(ident);
6a06907d
XL
1419 if let Some(file_path) = file_path {
1420 module.file_path_stack.push(file_path);
1421 }
1422
9e0c209e
SL
1423 let orig_module =
1424 mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
6a06907d
XL
1425 let orig_dir_ownership =
1426 mem::replace(&mut self.cx.current_expansion.dir_ownership, dir_ownership);
ba9703b0 1427
136023e0 1428 let result = assign_id!(self, &mut item.id, || noop_flat_map_item(item, self));
ba9703b0
XL
1429
1430 // Restore the module info.
6a06907d 1431 self.cx.current_expansion.dir_ownership = orig_dir_ownership;
9e0c209e 1432 self.cx.current_expansion.module = orig_module;
6a06907d 1433
7cac9316 1434 result
9e0c209e 1435 }
ba9703b0
XL
1436 _ => {
1437 item.attrs = attrs;
136023e0
XL
1438 // The crate root is special - don't assign an ID to it.
1439 if !(matches!(item.kind, ast::ItemKind::Mod(..)) && ident == Ident::invalid()) {
1440 assign_id!(self, &mut item.id, || noop_flat_map_item(item, self))
1441 } else {
1442 noop_flat_map_item(item, self)
1443 }
ba9703b0 1444 }
9e0c209e 1445 }
1a4d82fc
JJ
1446 }
1447
74b04a01 1448 fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
9fa01778 1449 let mut item = configure!(self, item);
1a4d82fc 1450
fc512014 1451 if let Some(attr) = self.take_first_attr(&mut item) {
dfeec247 1452 return self
fc512014 1453 .collect_attr(attr, Annotatable::TraitItem(item), AstFragmentKind::TraitItems)
dfeec247 1454 .make_trait_items();
9e0c209e
SL
1455 }
1456
e74abb32 1457 match item.kind {
ba9703b0 1458 ast::AssocItemKind::MacCall(..) => {
74b04a01
XL
1459 self.check_attributes(&item.attrs);
1460 item.and_then(|item| match item.kind {
ba9703b0 1461 ast::AssocItemKind::MacCall(mac) => self
74b04a01
XL
1462 .collect_bang(mac, item.span, AstFragmentKind::TraitItems)
1463 .make_trait_items(),
1464 _ => unreachable!(),
1465 })
54a0048b 1466 }
136023e0
XL
1467 _ => {
1468 assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self))
1469 }
54a0048b 1470 }
1a4d82fc
JJ
1471 }
1472
74b04a01 1473 fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
9fa01778 1474 let mut item = configure!(self, item);
1a4d82fc 1475
fc512014 1476 if let Some(attr) = self.take_first_attr(&mut item) {
dfeec247 1477 return self
fc512014 1478 .collect_attr(attr, Annotatable::ImplItem(item), AstFragmentKind::ImplItems)
dfeec247 1479 .make_impl_items();
9e0c209e 1480 }
1a4d82fc 1481
e74abb32 1482 match item.kind {
ba9703b0 1483 ast::AssocItemKind::MacCall(..) => {
74b04a01
XL
1484 self.check_attributes(&item.attrs);
1485 item.and_then(|item| match item.kind {
ba9703b0 1486 ast::AssocItemKind::MacCall(mac) => self
74b04a01
XL
1487 .collect_bang(mac, item.span, AstFragmentKind::ImplItems)
1488 .make_impl_items(),
1489 _ => unreachable!(),
1490 })
9e0c209e 1491 }
136023e0
XL
1492 _ => {
1493 assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self))
1494 }
9e0c209e 1495 }
85aaf69f
SL
1496 }
1497
9fa01778 1498 fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
e74abb32 1499 match ty.kind {
ba9703b0 1500 ast::TyKind::MacCall(_) => {}
9fa01778 1501 _ => return noop_visit_ty(ty, self),
9e0c209e
SL
1502 };
1503
dfeec247 1504 visit_clobber(ty, |mut ty| match mem::replace(&mut ty.kind, ast::TyKind::Err) {
ba9703b0
XL
1505 ast::TyKind::MacCall(mac) => {
1506 self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty()
1507 }
dfeec247 1508 _ => unreachable!(),
9fa01778 1509 });
1a4d82fc
JJ
1510 }
1511
dfeec247
XL
1512 fn flat_map_foreign_item(
1513 &mut self,
6a06907d 1514 foreign_item: P<ast::ForeignItem>,
74b04a01 1515 ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
6a06907d
XL
1516 let mut foreign_item = configure!(self, foreign_item);
1517
fc512014 1518 if let Some(attr) = self.take_first_attr(&mut foreign_item) {
dfeec247
XL
1519 return self
1520 .collect_attr(
1521 attr,
74b04a01 1522 Annotatable::ForeignItem(foreign_item),
dfeec247 1523 AstFragmentKind::ForeignItems,
dfeec247
XL
1524 )
1525 .make_foreign_items();
83c7162d
XL
1526 }
1527
74b04a01 1528 match foreign_item.kind {
ba9703b0 1529 ast::ForeignItemKind::MacCall(..) => {
74b04a01
XL
1530 self.check_attributes(&foreign_item.attrs);
1531 foreign_item.and_then(|item| match item.kind {
ba9703b0 1532 ast::ForeignItemKind::MacCall(mac) => self
74b04a01
XL
1533 .collect_bang(mac, item.span, AstFragmentKind::ForeignItems)
1534 .make_foreign_items(),
1535 _ => unreachable!(),
1536 })
1537 }
136023e0
XL
1538 _ => {
1539 assign_id!(self, &mut foreign_item.id, || noop_flat_map_foreign_item(
1540 foreign_item,
1541 self
1542 ))
1543 }
83c7162d 1544 }
83c7162d
XL
1545 }
1546
e1599b0c
XL
1547 fn flat_map_generic_param(
1548 &mut self,
dfeec247
XL
1549 param: ast::GenericParam,
1550 ) -> SmallVec<[ast::GenericParam; 1]> {
e1599b0c
XL
1551 let mut param = configure!(self, param);
1552
fc512014 1553 if let Some(attr) = self.take_first_attr(&mut param) {
dfeec247
XL
1554 return self
1555 .collect_attr(
1556 attr,
dfeec247
XL
1557 Annotatable::GenericParam(param),
1558 AstFragmentKind::GenericParams,
dfeec247
XL
1559 )
1560 .make_generic_params();
e1599b0c
XL
1561 }
1562
136023e0 1563 assign_id!(self, &mut param.id, || noop_flat_map_generic_param(param, self))
83c7162d
XL
1564 }
1565
9fa01778 1566 fn visit_id(&mut self, id: &mut ast::NodeId) {
136023e0
XL
1567 // We may have already assigned a `NodeId`
1568 // by calling `assign_id`
1569 if self.monotonic && *id == ast::DUMMY_NODE_ID {
1570 *id = self.cx.resolver.next_node_id();
9e0c209e 1571 }
54a0048b
SL
1572 }
1573}
1574
85aaf69f 1575pub struct ExpansionConfig<'feat> {
1a4d82fc 1576 pub crate_name: String,
85aaf69f 1577 pub features: Option<&'feat Features>,
f9f354fc 1578 pub recursion_limit: Limit,
d9579d0f 1579 pub trace_mac: bool,
6a06907d
XL
1580 pub should_test: bool, // If false, strip `#[test]` nodes
1581 pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
1b1a35ee 1582 pub proc_macro_backtrace: bool, // If true, show backtraces for proc-macro panics
1a4d82fc
JJ
1583}
1584
85aaf69f
SL
1585impl<'feat> ExpansionConfig<'feat> {
1586 pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1a4d82fc 1587 ExpansionConfig {
3b2f2976 1588 crate_name,
85aaf69f 1589 features: None,
f9f354fc 1590 recursion_limit: Limit::new(1024),
d9579d0f 1591 trace_mac: false,
3157f602 1592 should_test: false,
f035d41b 1593 span_debug: false,
1b1a35ee 1594 proc_macro_backtrace: false,
1a4d82fc 1595 }
970d7e83 1596 }
85aaf69f 1597
416331ca
XL
1598 fn proc_macro_hygiene(&self) -> bool {
1599 self.features.map_or(false, |features| features.proc_macro_hygiene)
1600 }
970d7e83 1601}