]> git.proxmox.com Git - rustc.git/blob - src/librustc_expand/expand.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_expand / expand.rs
1 use crate::base::*;
2 use crate::config::StripUnconfigured;
3 use crate::configure;
4 use crate::hygiene::{ExpnData, ExpnKind, SyntaxContext};
5 use crate::mbe::macro_rules::annotate_err_with_kind;
6 use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership};
7 use crate::placeholders::{placeholder, PlaceholderExpander};
8 use crate::proc_macro::collect_derives;
9
10 use rustc_ast::mut_visit::*;
11 use rustc_ast::ptr::P;
12 use rustc_ast::token;
13 use rustc_ast::tokenstream::TokenStream;
14 use rustc_ast::visit::{self, AssocCtxt, Visitor};
15 use rustc_ast::{self as ast, AttrItem, Block, LitKind, NodeId, PatKind, Path};
16 use rustc_ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
17 use rustc_ast_pretty::pprust;
18 use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
19 use rustc_data_structures::map_in_place::MapInPlace;
20 use rustc_data_structures::stack::ensure_sufficient_stack;
21 use rustc_errors::{Applicability, PResult};
22 use rustc_feature::Features;
23 use rustc_parse::parser::Parser;
24 use rustc_parse::validate_attr;
25 use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
26 use rustc_session::lint::BuiltinLintDiagnostics;
27 use rustc_session::parse::{feature_err, ParseSess};
28 use rustc_session::Limit;
29 use rustc_span::source_map::respan;
30 use rustc_span::symbol::{sym, Ident, Symbol};
31 use rustc_span::{ExpnId, FileName, Span, DUMMY_SP};
32
33 use smallvec::{smallvec, SmallVec};
34 use std::io::ErrorKind;
35 use std::ops::DerefMut;
36 use std::path::PathBuf;
37 use std::rc::Rc;
38 use std::{iter, mem, slice};
39
40 macro_rules! ast_fragments {
41 (
42 $($Kind:ident($AstTy:ty) {
43 $kind_name:expr;
44 $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)?
45 $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)?
46 fn $make_ast:ident;
47 })*
48 ) => {
49 /// A fragment of AST that can be produced by a single macro expansion.
50 /// Can also serve as an input and intermediate result for macro expansion operations.
51 pub enum AstFragment {
52 OptExpr(Option<P<ast::Expr>>),
53 $($Kind($AstTy),)*
54 }
55
56 /// "Discriminant" of an AST fragment.
57 #[derive(Copy, Clone, PartialEq, Eq)]
58 pub enum AstFragmentKind {
59 OptExpr,
60 $($Kind,)*
61 }
62
63 impl AstFragmentKind {
64 pub fn name(self) -> &'static str {
65 match self {
66 AstFragmentKind::OptExpr => "expression",
67 $(AstFragmentKind::$Kind => $kind_name,)*
68 }
69 }
70
71 fn make_from<'a>(self, result: Box<dyn MacResult + 'a>) -> Option<AstFragment> {
72 match self {
73 AstFragmentKind::OptExpr =>
74 result.make_expr().map(Some).map(AstFragment::OptExpr),
75 $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
76 }
77 }
78 }
79
80 impl AstFragment {
81 pub fn add_placeholders(&mut self, placeholders: &[NodeId]) {
82 if placeholders.is_empty() {
83 return;
84 }
85 match self {
86 $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| {
87 // We are repeating through arguments with `many`, to do that we have to
88 // mention some macro variable from those arguments even if it's not used.
89 macro _repeating($flat_map_ast_elt) {}
90 placeholder(AstFragmentKind::$Kind, *id, None).$make_ast()
91 })),)?)*
92 _ => panic!("unexpected AST fragment kind")
93 }
94 }
95
96 pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
97 match self {
98 AstFragment::OptExpr(expr) => expr,
99 _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
100 }
101 }
102
103 $(pub fn $make_ast(self) -> $AstTy {
104 match self {
105 AstFragment::$Kind(ast) => ast,
106 _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
107 }
108 })*
109
110 pub fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) {
111 match self {
112 AstFragment::OptExpr(opt_expr) => {
113 visit_clobber(opt_expr, |opt_expr| {
114 if let Some(expr) = opt_expr {
115 vis.filter_map_expr(expr)
116 } else {
117 None
118 }
119 });
120 }
121 $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
122 $($(AstFragment::$Kind(ast) =>
123 ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)*
124 }
125 }
126
127 pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
128 match *self {
129 AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
130 AstFragment::OptExpr(None) => {}
131 $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
132 $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
133 visitor.$visit_ast_elt(ast_elt, $($args)*);
134 })?)*
135 }
136 }
137 }
138
139 impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> {
140 $(fn $make_ast(self: Box<crate::mbe::macro_rules::ParserAnyMacro<'a>>)
141 -> Option<$AstTy> {
142 Some(self.make(AstFragmentKind::$Kind).$make_ast())
143 })*
144 }
145 }
146 }
147
148 ast_fragments! {
149 Expr(P<ast::Expr>) { "expression"; one fn visit_expr; fn visit_expr; fn make_expr; }
150 Pat(P<ast::Pat>) { "pattern"; one fn visit_pat; fn visit_pat; fn make_pat; }
151 Ty(P<ast::Ty>) { "type"; one fn visit_ty; fn visit_ty; fn make_ty; }
152 Stmts(SmallVec<[ast::Stmt; 1]>) {
153 "statement"; many fn flat_map_stmt; fn visit_stmt(); fn make_stmts;
154 }
155 Items(SmallVec<[P<ast::Item>; 1]>) {
156 "item"; many fn flat_map_item; fn visit_item(); fn make_items;
157 }
158 TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
159 "trait item";
160 many fn flat_map_trait_item;
161 fn visit_assoc_item(AssocCtxt::Trait);
162 fn make_trait_items;
163 }
164 ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
165 "impl item";
166 many fn flat_map_impl_item;
167 fn visit_assoc_item(AssocCtxt::Impl);
168 fn make_impl_items;
169 }
170 ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
171 "foreign item";
172 many fn flat_map_foreign_item;
173 fn visit_foreign_item();
174 fn make_foreign_items;
175 }
176 Arms(SmallVec<[ast::Arm; 1]>) {
177 "match arm"; many fn flat_map_arm; fn visit_arm(); fn make_arms;
178 }
179 Fields(SmallVec<[ast::Field; 1]>) {
180 "field expression"; many fn flat_map_field; fn visit_field(); fn make_fields;
181 }
182 FieldPats(SmallVec<[ast::FieldPat; 1]>) {
183 "field pattern";
184 many fn flat_map_field_pattern;
185 fn visit_field_pattern();
186 fn make_field_patterns;
187 }
188 GenericParams(SmallVec<[ast::GenericParam; 1]>) {
189 "generic parameter";
190 many fn flat_map_generic_param;
191 fn visit_generic_param();
192 fn make_generic_params;
193 }
194 Params(SmallVec<[ast::Param; 1]>) {
195 "function parameter"; many fn flat_map_param; fn visit_param(); fn make_params;
196 }
197 StructFields(SmallVec<[ast::StructField; 1]>) {
198 "field";
199 many fn flat_map_struct_field;
200 fn visit_struct_field();
201 fn make_struct_fields;
202 }
203 Variants(SmallVec<[ast::Variant; 1]>) {
204 "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
205 }
206 }
207
208 impl AstFragmentKind {
209 crate fn dummy(self, span: Span) -> AstFragment {
210 self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment")
211 }
212
213 fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(
214 self,
215 items: I,
216 ) -> AstFragment {
217 let mut items = items.into_iter();
218 match self {
219 AstFragmentKind::Arms => {
220 AstFragment::Arms(items.map(Annotatable::expect_arm).collect())
221 }
222 AstFragmentKind::Fields => {
223 AstFragment::Fields(items.map(Annotatable::expect_field).collect())
224 }
225 AstFragmentKind::FieldPats => {
226 AstFragment::FieldPats(items.map(Annotatable::expect_field_pattern).collect())
227 }
228 AstFragmentKind::GenericParams => {
229 AstFragment::GenericParams(items.map(Annotatable::expect_generic_param).collect())
230 }
231 AstFragmentKind::Params => {
232 AstFragment::Params(items.map(Annotatable::expect_param).collect())
233 }
234 AstFragmentKind::StructFields => {
235 AstFragment::StructFields(items.map(Annotatable::expect_struct_field).collect())
236 }
237 AstFragmentKind::Variants => {
238 AstFragment::Variants(items.map(Annotatable::expect_variant).collect())
239 }
240 AstFragmentKind::Items => {
241 AstFragment::Items(items.map(Annotatable::expect_item).collect())
242 }
243 AstFragmentKind::ImplItems => {
244 AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect())
245 }
246 AstFragmentKind::TraitItems => {
247 AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect())
248 }
249 AstFragmentKind::ForeignItems => {
250 AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect())
251 }
252 AstFragmentKind::Stmts => {
253 AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect())
254 }
255 AstFragmentKind::Expr => AstFragment::Expr(
256 items.next().expect("expected exactly one expression").expect_expr(),
257 ),
258 AstFragmentKind::OptExpr => {
259 AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
260 }
261 AstFragmentKind::Pat | AstFragmentKind::Ty => {
262 panic!("patterns and types aren't annotatable")
263 }
264 }
265 }
266 }
267
268 pub struct Invocation {
269 pub kind: InvocationKind,
270 pub fragment_kind: AstFragmentKind,
271 pub expansion_data: ExpansionData,
272 }
273
274 pub enum InvocationKind {
275 Bang {
276 mac: ast::MacCall,
277 span: Span,
278 },
279 Attr {
280 attr: ast::Attribute,
281 item: Annotatable,
282 // Required for resolving derive helper attributes.
283 derives: Vec<Path>,
284 // We temporarily report errors for attribute macros placed after derives
285 after_derive: bool,
286 },
287 Derive {
288 path: Path,
289 item: Annotatable,
290 },
291 /// "Invocation" that contains all derives from an item,
292 /// broken into multiple `Derive` invocations when expanded.
293 /// FIXME: Find a way to remove it.
294 DeriveContainer {
295 derives: Vec<Path>,
296 item: Annotatable,
297 },
298 }
299
300 impl InvocationKind {
301 fn placeholder_visibility(&self) -> Option<ast::Visibility> {
302 // HACK: For unnamed fields placeholders should have the same visibility as the actual
303 // fields because for tuple structs/variants resolve determines visibilities of their
304 // constructor using these field visibilities before attributes on them are are expanded.
305 // The assumption is that the attribute expansion cannot change field visibilities,
306 // and it holds because only inert attributes are supported in this position.
307 match self {
308 InvocationKind::Attr { item: Annotatable::StructField(field), .. }
309 | InvocationKind::Derive { item: Annotatable::StructField(field), .. }
310 | InvocationKind::DeriveContainer { item: Annotatable::StructField(field), .. }
311 if field.ident.is_none() =>
312 {
313 Some(field.vis.clone())
314 }
315 _ => None,
316 }
317 }
318 }
319
320 impl Invocation {
321 pub fn span(&self) -> Span {
322 match &self.kind {
323 InvocationKind::Bang { span, .. } => *span,
324 InvocationKind::Attr { attr, .. } => attr.span,
325 InvocationKind::Derive { path, .. } => path.span,
326 InvocationKind::DeriveContainer { item, .. } => item.span(),
327 }
328 }
329 }
330
331 pub struct MacroExpander<'a, 'b> {
332 pub cx: &'a mut ExtCtxt<'b>,
333 monotonic: bool, // cf. `cx.monotonic_expander()`
334 }
335
336 impl<'a, 'b> MacroExpander<'a, 'b> {
337 pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
338 MacroExpander { cx, monotonic }
339 }
340
341 pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
342 let mut module = ModuleData {
343 mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
344 directory: match self.cx.source_map().span_to_unmapped_path(krate.span) {
345 FileName::Real(name) => name.into_local_path(),
346 other => PathBuf::from(other.to_string()),
347 },
348 };
349 module.directory.pop();
350 self.cx.root_path = module.directory.clone();
351 self.cx.current_expansion.module = Rc::new(module);
352
353 let orig_mod_span = krate.module.inner;
354
355 let krate_item = AstFragment::Items(smallvec![P(ast::Item {
356 attrs: krate.attrs,
357 span: krate.span,
358 kind: ast::ItemKind::Mod(krate.module),
359 ident: Ident::invalid(),
360 id: ast::DUMMY_NODE_ID,
361 vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
362 tokens: None,
363 })]);
364
365 match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
366 Some(ast::Item { attrs, kind: ast::ItemKind::Mod(module), .. }) => {
367 krate.attrs = attrs;
368 krate.module = module;
369 }
370 None => {
371 // Resolution failed so we return an empty expansion
372 krate.attrs = vec![];
373 krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true };
374 }
375 Some(ast::Item { span, kind, .. }) => {
376 krate.attrs = vec![];
377 krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true };
378 self.cx.span_err(
379 span,
380 &format!(
381 "expected crate top-level item to be a module after macro expansion, found {} {}",
382 kind.article(), kind.descr()
383 ),
384 );
385 }
386 };
387 self.cx.trace_macros_diag();
388 krate
389 }
390
391 // Recursively expand all macro invocations in this AST fragment.
392 pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
393 let orig_expansion_data = self.cx.current_expansion.clone();
394 self.cx.current_expansion.depth = 0;
395
396 // Collect all macro invocations and replace them with placeholders.
397 let (mut fragment_with_placeholders, mut invocations) =
398 self.collect_invocations(input_fragment, &[]);
399
400 // Optimization: if we resolve all imports now,
401 // we'll be able to immediately resolve most of imported macros.
402 self.resolve_imports();
403
404 // Resolve paths in all invocations and produce output expanded fragments for them, but
405 // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
406 // The output fragments also go through expansion recursively until no invocations are left.
407 // Unresolved macros produce dummy outputs as a recovery measure.
408 invocations.reverse();
409 let mut expanded_fragments = Vec::new();
410 let mut undetermined_invocations = Vec::new();
411 let (mut progress, mut force) = (false, !self.monotonic);
412 loop {
413 let (invoc, res) = if let Some(invoc) = invocations.pop() {
414 invoc
415 } else {
416 self.resolve_imports();
417 if undetermined_invocations.is_empty() {
418 break;
419 }
420 invocations = mem::take(&mut undetermined_invocations);
421 force = !mem::replace(&mut progress, false);
422 continue;
423 };
424
425 let res = match res {
426 Some(res) => res,
427 None => {
428 let eager_expansion_root = if self.monotonic {
429 invoc.expansion_data.id
430 } else {
431 orig_expansion_data.id
432 };
433 match self.cx.resolver.resolve_macro_invocation(
434 &invoc,
435 eager_expansion_root,
436 force,
437 ) {
438 Ok(res) => res,
439 Err(Indeterminate) => {
440 // Cannot resolve, will retry this invocation later.
441 undetermined_invocations.push((invoc, None));
442 continue;
443 }
444 }
445 }
446 };
447
448 let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
449 self.cx.current_expansion = invoc.expansion_data.clone();
450
451 // FIXME(jseyfried): Refactor out the following logic
452 let (expanded_fragment, new_invocations) = match res {
453 InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) {
454 ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]),
455 ExpandResult::Retry(invoc, explanation) => {
456 if force {
457 // We are stuck, stop retrying and produce a dummy fragment.
458 let span = invoc.span();
459 self.cx.span_err(span, &explanation);
460 let fragment = invoc.fragment_kind.dummy(span);
461 self.collect_invocations(fragment, &[])
462 } else {
463 // Cannot expand, will retry this invocation later.
464 undetermined_invocations
465 .push((invoc, Some(InvocationRes::Single(ext))));
466 continue;
467 }
468 }
469 },
470 InvocationRes::DeriveContainer(_exts) => {
471 // FIXME: Consider using the derive resolutions (`_exts`) immediately,
472 // instead of enqueuing the derives to be resolved again later.
473 let (derives, item) = match invoc.kind {
474 InvocationKind::DeriveContainer { derives, item } => (derives, item),
475 _ => unreachable!(),
476 };
477 if !item.derive_allowed() {
478 self.error_derive_forbidden_on_non_adt(&derives, &item);
479 }
480
481 let mut item = self.fully_configure(item);
482 item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
483
484 let mut derive_placeholders = Vec::with_capacity(derives.len());
485 invocations.reserve(derives.len());
486 for path in derives {
487 let expn_id = ExpnId::fresh(None);
488 derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id));
489 invocations.push((
490 Invocation {
491 kind: InvocationKind::Derive { path, item: item.clone() },
492 fragment_kind: invoc.fragment_kind,
493 expansion_data: ExpansionData {
494 id: expn_id,
495 ..invoc.expansion_data.clone()
496 },
497 },
498 None,
499 ));
500 }
501 let fragment =
502 invoc.fragment_kind.expect_from_annotatables(::std::iter::once(item));
503 self.collect_invocations(fragment, &derive_placeholders)
504 }
505 };
506
507 progress = true;
508 if expanded_fragments.len() < depth {
509 expanded_fragments.push(Vec::new());
510 }
511 expanded_fragments[depth - 1].push((expn_id, expanded_fragment));
512 invocations.extend(new_invocations.into_iter().rev());
513 }
514
515 self.cx.current_expansion = orig_expansion_data;
516
517 // Finally incorporate all the expanded macros into the input AST fragment.
518 let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
519 while let Some(expanded_fragments) = expanded_fragments.pop() {
520 for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
521 placeholder_expander
522 .add(NodeId::placeholder_from_expn_id(expn_id), expanded_fragment);
523 }
524 }
525 fragment_with_placeholders.mut_visit_with(&mut placeholder_expander);
526 fragment_with_placeholders
527 }
528
529 fn error_derive_forbidden_on_non_adt(&self, derives: &[Path], item: &Annotatable) {
530 let attr = self.cx.sess.find_by_name(item.attrs(), sym::derive);
531 let span = attr.map_or(item.span(), |attr| attr.span);
532 let mut err = self
533 .cx
534 .struct_span_err(span, "`derive` may only be applied to structs, enums and unions");
535 if let Some(ast::Attribute { style: ast::AttrStyle::Inner, .. }) = attr {
536 let trait_list = derives.iter().map(|t| pprust::path_to_string(t)).collect::<Vec<_>>();
537 let suggestion = format!("#[derive({})]", trait_list.join(", "));
538 err.span_suggestion(
539 span,
540 "try an outer attribute",
541 suggestion,
542 // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
543 Applicability::MaybeIncorrect,
544 );
545 }
546 err.emit();
547 }
548
549 fn resolve_imports(&mut self) {
550 if self.monotonic {
551 self.cx.resolver.resolve_imports();
552 }
553 }
554
555 /// Collects all macro invocations reachable at this time in this AST fragment, and replace
556 /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
557 /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
558 /// prepares data for resolving paths of macro invocations.
559 fn collect_invocations(
560 &mut self,
561 mut fragment: AstFragment,
562 extra_placeholders: &[NodeId],
563 ) -> (AstFragment, Vec<(Invocation, Option<InvocationRes>)>) {
564 // Resolve `$crate`s in the fragment for pretty-printing.
565 self.cx.resolver.resolve_dollar_crates();
566
567 let invocations = {
568 let mut collector = InvocationCollector {
569 cfg: StripUnconfigured { sess: &self.cx.sess, features: self.cx.ecfg.features },
570 cx: self.cx,
571 invocations: Vec::new(),
572 monotonic: self.monotonic,
573 };
574 fragment.mut_visit_with(&mut collector);
575 fragment.add_placeholders(extra_placeholders);
576 collector.invocations
577 };
578
579 if self.monotonic {
580 self.cx
581 .resolver
582 .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);
583 }
584
585 (fragment, invocations)
586 }
587
588 fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
589 let mut cfg = StripUnconfigured { sess: &self.cx.sess, features: self.cx.ecfg.features };
590 // Since the item itself has already been configured by the InvocationCollector,
591 // we know that fold result vector will contain exactly one element
592 match item {
593 Annotatable::Item(item) => Annotatable::Item(cfg.flat_map_item(item).pop().unwrap()),
594 Annotatable::TraitItem(item) => {
595 Annotatable::TraitItem(cfg.flat_map_trait_item(item).pop().unwrap())
596 }
597 Annotatable::ImplItem(item) => {
598 Annotatable::ImplItem(cfg.flat_map_impl_item(item).pop().unwrap())
599 }
600 Annotatable::ForeignItem(item) => {
601 Annotatable::ForeignItem(cfg.flat_map_foreign_item(item).pop().unwrap())
602 }
603 Annotatable::Stmt(stmt) => {
604 Annotatable::Stmt(stmt.map(|stmt| cfg.flat_map_stmt(stmt).pop().unwrap()))
605 }
606 Annotatable::Expr(mut expr) => Annotatable::Expr({
607 cfg.visit_expr(&mut expr);
608 expr
609 }),
610 Annotatable::Arm(arm) => Annotatable::Arm(cfg.flat_map_arm(arm).pop().unwrap()),
611 Annotatable::Field(field) => {
612 Annotatable::Field(cfg.flat_map_field(field).pop().unwrap())
613 }
614 Annotatable::FieldPat(fp) => {
615 Annotatable::FieldPat(cfg.flat_map_field_pattern(fp).pop().unwrap())
616 }
617 Annotatable::GenericParam(param) => {
618 Annotatable::GenericParam(cfg.flat_map_generic_param(param).pop().unwrap())
619 }
620 Annotatable::Param(param) => {
621 Annotatable::Param(cfg.flat_map_param(param).pop().unwrap())
622 }
623 Annotatable::StructField(sf) => {
624 Annotatable::StructField(cfg.flat_map_struct_field(sf).pop().unwrap())
625 }
626 Annotatable::Variant(v) => Annotatable::Variant(cfg.flat_map_variant(v).pop().unwrap()),
627 }
628 }
629
630 fn error_recursion_limit_reached(&mut self) {
631 let expn_data = self.cx.current_expansion.id.expn_data();
632 let suggested_limit = self.cx.ecfg.recursion_limit * 2;
633 self.cx
634 .struct_span_err(
635 expn_data.call_site,
636 &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
637 )
638 .help(&format!(
639 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
640 suggested_limit, self.cx.ecfg.crate_name,
641 ))
642 .emit();
643 self.cx.trace_macros_diag();
644 }
645
646 /// A macro's expansion does not fit in this fragment kind.
647 /// For example, a non-type macro in a type position.
648 fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
649 let msg = format!(
650 "non-{kind} macro in {kind} position: {path}",
651 kind = kind.name(),
652 path = pprust::path_to_string(&mac.path),
653 );
654 self.cx.span_err(span, &msg);
655 self.cx.trace_macros_diag();
656 }
657
658 fn expand_invoc(
659 &mut self,
660 invoc: Invocation,
661 ext: &SyntaxExtensionKind,
662 ) -> ExpandResult<AstFragment, Invocation> {
663 let recursion_limit =
664 self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
665 if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
666 if self.cx.reduced_recursion_limit.is_none() {
667 self.error_recursion_limit_reached();
668 }
669
670 // Reduce the recursion limit by half each time it triggers.
671 self.cx.reduced_recursion_limit = Some(recursion_limit / 2);
672
673 return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span()));
674 }
675
676 let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
677 ExpandResult::Ready(match invoc.kind {
678 InvocationKind::Bang { mac, .. } => match ext {
679 SyntaxExtensionKind::Bang(expander) => {
680 let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) {
681 Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
682 Ok(ts) => ts,
683 };
684 self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
685 }
686 SyntaxExtensionKind::LegacyBang(expander) => {
687 let prev = self.cx.current_expansion.prior_type_ascription;
688 self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription;
689 let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
690 let result = if let Some(result) = fragment_kind.make_from(tok_result) {
691 result
692 } else {
693 self.error_wrong_fragment_kind(fragment_kind, &mac, span);
694 fragment_kind.dummy(span)
695 };
696 self.cx.current_expansion.prior_type_ascription = prev;
697 result
698 }
699 _ => unreachable!(),
700 },
701 InvocationKind::Attr { attr, mut item, derives, after_derive } => match ext {
702 SyntaxExtensionKind::Attr(expander) => {
703 self.gate_proc_macro_input(&item);
704 self.gate_proc_macro_attr_item(span, &item);
705 let tokens = item.into_tokens(&self.cx.sess.parse_sess);
706 let attr_item = attr.unwrap_normal_item();
707 if let MacArgs::Eq(..) = attr_item.args {
708 self.cx.span_err(span, "key-value macro attributes are not supported");
709 }
710 let inner_tokens = attr_item.args.inner_tokens();
711 let tok_result = match expander.expand(self.cx, span, inner_tokens, tokens) {
712 Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
713 Ok(ts) => ts,
714 };
715 self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span)
716 }
717 SyntaxExtensionKind::LegacyAttr(expander) => {
718 match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) {
719 Ok(meta) => {
720 let items = match expander.expand(self.cx, span, &meta, item) {
721 ExpandResult::Ready(items) => items,
722 ExpandResult::Retry(item, explanation) => {
723 // Reassemble the original invocation for retrying.
724 return ExpandResult::Retry(
725 Invocation {
726 kind: InvocationKind::Attr {
727 attr,
728 item,
729 derives,
730 after_derive,
731 },
732 ..invoc
733 },
734 explanation,
735 );
736 }
737 };
738 fragment_kind.expect_from_annotatables(items)
739 }
740 Err(mut err) => {
741 err.emit();
742 fragment_kind.dummy(span)
743 }
744 }
745 }
746 SyntaxExtensionKind::NonMacroAttr { mark_used } => {
747 self.cx.sess.mark_attr_known(&attr);
748 if *mark_used {
749 self.cx.sess.mark_attr_used(&attr);
750 }
751 item.visit_attrs(|attrs| attrs.push(attr));
752 fragment_kind.expect_from_annotatables(iter::once(item))
753 }
754 _ => unreachable!(),
755 },
756 InvocationKind::Derive { path, item } => match ext {
757 SyntaxExtensionKind::Derive(expander)
758 | SyntaxExtensionKind::LegacyDerive(expander) => {
759 if !item.derive_allowed() {
760 return ExpandResult::Ready(fragment_kind.dummy(span));
761 }
762 if let SyntaxExtensionKind::Derive(..) = ext {
763 self.gate_proc_macro_input(&item);
764 }
765 let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
766 let items = match expander.expand(self.cx, span, &meta, item) {
767 ExpandResult::Ready(items) => items,
768 ExpandResult::Retry(item, explanation) => {
769 // Reassemble the original invocation for retrying.
770 return ExpandResult::Retry(
771 Invocation {
772 kind: InvocationKind::Derive { path: meta.path, item },
773 ..invoc
774 },
775 explanation,
776 );
777 }
778 };
779 fragment_kind.expect_from_annotatables(items)
780 }
781 _ => unreachable!(),
782 },
783 InvocationKind::DeriveContainer { .. } => unreachable!(),
784 })
785 }
786
787 fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
788 let kind = match item {
789 Annotatable::Item(_)
790 | Annotatable::TraitItem(_)
791 | Annotatable::ImplItem(_)
792 | Annotatable::ForeignItem(_) => return,
793 Annotatable::Stmt(_) => "statements",
794 Annotatable::Expr(_) => "expressions",
795 Annotatable::Arm(..)
796 | Annotatable::Field(..)
797 | Annotatable::FieldPat(..)
798 | Annotatable::GenericParam(..)
799 | Annotatable::Param(..)
800 | Annotatable::StructField(..)
801 | Annotatable::Variant(..) => panic!("unexpected annotatable"),
802 };
803 if self.cx.ecfg.proc_macro_hygiene() {
804 return;
805 }
806 feature_err(
807 &self.cx.sess.parse_sess,
808 sym::proc_macro_hygiene,
809 span,
810 &format!("custom attributes cannot be applied to {}", kind),
811 )
812 .emit();
813 }
814
815 fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
816 struct GateProcMacroInput<'a> {
817 parse_sess: &'a ParseSess,
818 }
819
820 impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
821 fn visit_item(&mut self, item: &'ast ast::Item) {
822 match &item.kind {
823 ast::ItemKind::Mod(module) if !module.inline => {
824 feature_err(
825 self.parse_sess,
826 sym::proc_macro_hygiene,
827 item.span,
828 "non-inline modules in proc macro input are unstable",
829 )
830 .emit();
831 }
832 _ => {}
833 }
834
835 visit::walk_item(self, item);
836 }
837
838 fn visit_mac(&mut self, _: &'ast ast::MacCall) {}
839 }
840
841 if !self.cx.ecfg.proc_macro_hygiene() {
842 annotatable
843 .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess });
844 }
845 }
846
847 fn parse_ast_fragment(
848 &mut self,
849 toks: TokenStream,
850 kind: AstFragmentKind,
851 path: &Path,
852 span: Span,
853 ) -> AstFragment {
854 let mut parser = self.cx.new_parser_from_tts(toks);
855 match parse_ast_fragment(&mut parser, kind) {
856 Ok(fragment) => {
857 ensure_complete_parse(&mut parser, path, kind.name(), span);
858 fragment
859 }
860 Err(mut err) => {
861 err.set_span(span);
862 annotate_err_with_kind(&mut err, kind, span);
863 err.emit();
864 self.cx.trace_macros_diag();
865 kind.dummy(span)
866 }
867 }
868 }
869 }
870
871 pub fn parse_ast_fragment<'a>(
872 this: &mut Parser<'a>,
873 kind: AstFragmentKind,
874 ) -> PResult<'a, AstFragment> {
875 Ok(match kind {
876 AstFragmentKind::Items => {
877 let mut items = SmallVec::new();
878 while let Some(item) = this.parse_item()? {
879 items.push(item);
880 }
881 AstFragment::Items(items)
882 }
883 AstFragmentKind::TraitItems => {
884 let mut items = SmallVec::new();
885 while let Some(item) = this.parse_trait_item()? {
886 items.extend(item);
887 }
888 AstFragment::TraitItems(items)
889 }
890 AstFragmentKind::ImplItems => {
891 let mut items = SmallVec::new();
892 while let Some(item) = this.parse_impl_item()? {
893 items.extend(item);
894 }
895 AstFragment::ImplItems(items)
896 }
897 AstFragmentKind::ForeignItems => {
898 let mut items = SmallVec::new();
899 while let Some(item) = this.parse_foreign_item()? {
900 items.extend(item);
901 }
902 AstFragment::ForeignItems(items)
903 }
904 AstFragmentKind::Stmts => {
905 let mut stmts = SmallVec::new();
906 // Won't make progress on a `}`.
907 while this.token != token::Eof && this.token != token::CloseDelim(token::Brace) {
908 if let Some(stmt) = this.parse_full_stmt()? {
909 stmts.push(stmt);
910 }
911 }
912 AstFragment::Stmts(stmts)
913 }
914 AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
915 AstFragmentKind::OptExpr => {
916 if this.token != token::Eof {
917 AstFragment::OptExpr(Some(this.parse_expr()?))
918 } else {
919 AstFragment::OptExpr(None)
920 }
921 }
922 AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
923 AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat(None)?),
924 AstFragmentKind::Arms
925 | AstFragmentKind::Fields
926 | AstFragmentKind::FieldPats
927 | AstFragmentKind::GenericParams
928 | AstFragmentKind::Params
929 | AstFragmentKind::StructFields
930 | AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
931 })
932 }
933
934 pub fn ensure_complete_parse<'a>(
935 this: &mut Parser<'a>,
936 macro_path: &Path,
937 kind_name: &str,
938 span: Span,
939 ) {
940 if this.token != token::Eof {
941 let token = pprust::token_to_string(&this.token);
942 let msg = format!("macro expansion ignores token `{}` and any following", token);
943 // Avoid emitting backtrace info twice.
944 let def_site_span = this.token.span.with_ctxt(SyntaxContext::root());
945 let mut err = this.struct_span_err(def_site_span, &msg);
946 err.span_label(span, "caused by the macro expansion here");
947 let msg = format!(
948 "the usage of `{}!` is likely invalid in {} context",
949 pprust::path_to_string(macro_path),
950 kind_name,
951 );
952 err.note(&msg);
953 let semi_span = this.sess.source_map().next_point(span);
954
955 let semi_full_span = semi_span.to(this.sess.source_map().next_point(semi_span));
956 match this.sess.source_map().span_to_snippet(semi_full_span) {
957 Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
958 err.span_suggestion(
959 semi_span,
960 "you might be missing a semicolon here",
961 ";".to_owned(),
962 Applicability::MaybeIncorrect,
963 );
964 }
965 _ => {}
966 }
967 err.emit();
968 }
969 }
970
971 struct InvocationCollector<'a, 'b> {
972 cx: &'a mut ExtCtxt<'b>,
973 cfg: StripUnconfigured<'a>,
974 invocations: Vec<(Invocation, Option<InvocationRes>)>,
975 monotonic: bool,
976 }
977
978 impl<'a, 'b> InvocationCollector<'a, 'b> {
979 fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
980 // Expansion data for all the collected invocations is set upon their resolution,
981 // with exception of the derive container case which is not resolved and can get
982 // its expansion data immediately.
983 let expn_data = match &kind {
984 InvocationKind::DeriveContainer { item, .. } => Some(ExpnData {
985 parent: self.cx.current_expansion.id,
986 ..ExpnData::default(
987 ExpnKind::Macro(MacroKind::Attr, sym::derive),
988 item.span(),
989 self.cx.sess.parse_sess.edition,
990 None,
991 )
992 }),
993 _ => None,
994 };
995 let expn_id = ExpnId::fresh(expn_data);
996 let vis = kind.placeholder_visibility();
997 self.invocations.push((
998 Invocation {
999 kind,
1000 fragment_kind,
1001 expansion_data: ExpansionData {
1002 id: expn_id,
1003 depth: self.cx.current_expansion.depth + 1,
1004 ..self.cx.current_expansion.clone()
1005 },
1006 },
1007 None,
1008 ));
1009 placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
1010 }
1011
1012 fn collect_bang(
1013 &mut self,
1014 mac: ast::MacCall,
1015 span: Span,
1016 kind: AstFragmentKind,
1017 ) -> AstFragment {
1018 self.collect(kind, InvocationKind::Bang { mac, span })
1019 }
1020
1021 fn collect_attr(
1022 &mut self,
1023 attr: Option<ast::Attribute>,
1024 derives: Vec<Path>,
1025 item: Annotatable,
1026 kind: AstFragmentKind,
1027 after_derive: bool,
1028 ) -> AstFragment {
1029 self.collect(
1030 kind,
1031 match attr {
1032 Some(attr) => InvocationKind::Attr { attr, item, derives, after_derive },
1033 None => InvocationKind::DeriveContainer { derives, item },
1034 },
1035 )
1036 }
1037
1038 fn find_attr_invoc(
1039 &self,
1040 attrs: &mut Vec<ast::Attribute>,
1041 after_derive: &mut bool,
1042 ) -> Option<ast::Attribute> {
1043 let attr = attrs
1044 .iter()
1045 .position(|a| {
1046 if a.has_name(sym::derive) {
1047 *after_derive = true;
1048 }
1049 !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a)
1050 })
1051 .map(|i| attrs.remove(i));
1052 if let Some(attr) = &attr {
1053 if !self.cx.ecfg.custom_inner_attributes()
1054 && attr.style == ast::AttrStyle::Inner
1055 && !attr.has_name(sym::test)
1056 {
1057 feature_err(
1058 &self.cx.sess.parse_sess,
1059 sym::custom_inner_attributes,
1060 attr.span,
1061 "non-builtin inner attributes are unstable",
1062 )
1063 .emit();
1064 }
1065 }
1066 attr
1067 }
1068
1069 /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
1070 fn classify_item(
1071 &mut self,
1072 item: &mut impl HasAttrs,
1073 ) -> (Option<ast::Attribute>, Vec<Path>, /* after_derive */ bool) {
1074 let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false);
1075
1076 item.visit_attrs(|mut attrs| {
1077 attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
1078 traits = collect_derives(&mut self.cx, &mut attrs);
1079 });
1080
1081 (attr, traits, after_derive)
1082 }
1083
1084 /// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough
1085 /// to the unused-attributes lint (making it an error on statements and expressions
1086 /// is a breaking change)
1087 fn classify_nonitem(
1088 &mut self,
1089 nonitem: &mut impl HasAttrs,
1090 ) -> (Option<ast::Attribute>, /* after_derive */ bool) {
1091 let (mut attr, mut after_derive) = (None, false);
1092
1093 nonitem.visit_attrs(|mut attrs| {
1094 attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
1095 });
1096
1097 (attr, after_derive)
1098 }
1099
1100 fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
1101 self.cfg.configure(node)
1102 }
1103
1104 // Detect use of feature-gated or invalid attributes on macro invocations
1105 // since they will not be detected after macro expansion.
1106 fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
1107 let features = self.cx.ecfg.features.unwrap();
1108 for attr in attrs.iter() {
1109 rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
1110 validate_attr::check_meta(&self.cx.sess.parse_sess, attr);
1111
1112 // macros are expanded before any lint passes so this warning has to be hardcoded
1113 if attr.has_name(sym::derive) {
1114 self.cx
1115 .parse_sess()
1116 .span_diagnostic
1117 .struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations")
1118 .note("this may become a hard error in a future release")
1119 .emit();
1120 }
1121
1122 if attr.doc_str().is_some() {
1123 self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
1124 &UNUSED_DOC_COMMENTS,
1125 attr.span,
1126 ast::CRATE_NODE_ID,
1127 "unused doc comment",
1128 BuiltinLintDiagnostics::UnusedDocComment(attr.span),
1129 );
1130 }
1131 }
1132 }
1133 }
1134
1135 impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1136 fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
1137 self.cfg.configure_expr(expr);
1138 visit_clobber(expr.deref_mut(), |mut expr| {
1139 self.cfg.configure_expr_kind(&mut expr.kind);
1140
1141 // ignore derives so they remain unused
1142 let (attr, after_derive) = self.classify_nonitem(&mut expr);
1143
1144 if let Some(ref attr_value) = attr {
1145 // Collect the invoc regardless of whether or not attributes are permitted here
1146 // expansion will eat the attribute so it won't error later.
1147 self.cfg.maybe_emit_expr_attr_err(attr_value);
1148
1149 // AstFragmentKind::Expr requires the macro to emit an expression.
1150 return self
1151 .collect_attr(
1152 attr,
1153 vec![],
1154 Annotatable::Expr(P(expr)),
1155 AstFragmentKind::Expr,
1156 after_derive,
1157 )
1158 .make_expr()
1159 .into_inner();
1160 }
1161
1162 if let ast::ExprKind::MacCall(mac) = expr.kind {
1163 self.check_attributes(&expr.attrs);
1164 self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
1165 } else {
1166 ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self));
1167 expr
1168 }
1169 });
1170 }
1171
1172 fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
1173 let mut arm = configure!(self, arm);
1174
1175 let (attr, traits, after_derive) = self.classify_item(&mut arm);
1176 if attr.is_some() || !traits.is_empty() {
1177 return self
1178 .collect_attr(
1179 attr,
1180 traits,
1181 Annotatable::Arm(arm),
1182 AstFragmentKind::Arms,
1183 after_derive,
1184 )
1185 .make_arms();
1186 }
1187
1188 noop_flat_map_arm(arm, self)
1189 }
1190
1191 fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
1192 let mut field = configure!(self, field);
1193
1194 let (attr, traits, after_derive) = self.classify_item(&mut field);
1195 if attr.is_some() || !traits.is_empty() {
1196 return self
1197 .collect_attr(
1198 attr,
1199 traits,
1200 Annotatable::Field(field),
1201 AstFragmentKind::Fields,
1202 after_derive,
1203 )
1204 .make_fields();
1205 }
1206
1207 noop_flat_map_field(field, self)
1208 }
1209
1210 fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
1211 let mut fp = configure!(self, fp);
1212
1213 let (attr, traits, after_derive) = self.classify_item(&mut fp);
1214 if attr.is_some() || !traits.is_empty() {
1215 return self
1216 .collect_attr(
1217 attr,
1218 traits,
1219 Annotatable::FieldPat(fp),
1220 AstFragmentKind::FieldPats,
1221 after_derive,
1222 )
1223 .make_field_patterns();
1224 }
1225
1226 noop_flat_map_field_pattern(fp, self)
1227 }
1228
1229 fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
1230 let mut p = configure!(self, p);
1231
1232 let (attr, traits, after_derive) = self.classify_item(&mut p);
1233 if attr.is_some() || !traits.is_empty() {
1234 return self
1235 .collect_attr(
1236 attr,
1237 traits,
1238 Annotatable::Param(p),
1239 AstFragmentKind::Params,
1240 after_derive,
1241 )
1242 .make_params();
1243 }
1244
1245 noop_flat_map_param(p, self)
1246 }
1247
1248 fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
1249 let mut sf = configure!(self, sf);
1250
1251 let (attr, traits, after_derive) = self.classify_item(&mut sf);
1252 if attr.is_some() || !traits.is_empty() {
1253 return self
1254 .collect_attr(
1255 attr,
1256 traits,
1257 Annotatable::StructField(sf),
1258 AstFragmentKind::StructFields,
1259 after_derive,
1260 )
1261 .make_struct_fields();
1262 }
1263
1264 noop_flat_map_struct_field(sf, self)
1265 }
1266
1267 fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
1268 let mut variant = configure!(self, variant);
1269
1270 let (attr, traits, after_derive) = self.classify_item(&mut variant);
1271 if attr.is_some() || !traits.is_empty() {
1272 return self
1273 .collect_attr(
1274 attr,
1275 traits,
1276 Annotatable::Variant(variant),
1277 AstFragmentKind::Variants,
1278 after_derive,
1279 )
1280 .make_variants();
1281 }
1282
1283 noop_flat_map_variant(variant, self)
1284 }
1285
1286 fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
1287 let expr = configure!(self, expr);
1288 expr.filter_map(|mut expr| {
1289 self.cfg.configure_expr_kind(&mut expr.kind);
1290
1291 // Ignore derives so they remain unused.
1292 let (attr, after_derive) = self.classify_nonitem(&mut expr);
1293
1294 if let Some(ref attr_value) = attr {
1295 self.cfg.maybe_emit_expr_attr_err(attr_value);
1296
1297 return self
1298 .collect_attr(
1299 attr,
1300 vec![],
1301 Annotatable::Expr(P(expr)),
1302 AstFragmentKind::OptExpr,
1303 after_derive,
1304 )
1305 .make_opt_expr()
1306 .map(|expr| expr.into_inner());
1307 }
1308
1309 if let ast::ExprKind::MacCall(mac) = expr.kind {
1310 self.check_attributes(&expr.attrs);
1311 self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr)
1312 .make_opt_expr()
1313 .map(|expr| expr.into_inner())
1314 } else {
1315 Some({
1316 noop_visit_expr(&mut expr, self);
1317 expr
1318 })
1319 }
1320 })
1321 }
1322
1323 fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
1324 self.cfg.configure_pat(pat);
1325 match pat.kind {
1326 PatKind::MacCall(_) => {}
1327 _ => return noop_visit_pat(pat, self),
1328 }
1329
1330 visit_clobber(pat, |mut pat| match mem::replace(&mut pat.kind, PatKind::Wild) {
1331 PatKind::MacCall(mac) => {
1332 self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat()
1333 }
1334 _ => unreachable!(),
1335 });
1336 }
1337
1338 fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
1339 let mut stmt = configure!(self, stmt);
1340
1341 // we'll expand attributes on expressions separately
1342 if !stmt.is_expr() {
1343 let (attr, derives, after_derive) = if stmt.is_item() {
1344 self.classify_item(&mut stmt)
1345 } else {
1346 // ignore derives on non-item statements so it falls through
1347 // to the unused-attributes lint
1348 let (attr, after_derive) = self.classify_nonitem(&mut stmt);
1349 (attr, vec![], after_derive)
1350 };
1351
1352 if attr.is_some() || !derives.is_empty() {
1353 return self
1354 .collect_attr(
1355 attr,
1356 derives,
1357 Annotatable::Stmt(P(stmt)),
1358 AstFragmentKind::Stmts,
1359 after_derive,
1360 )
1361 .make_stmts();
1362 }
1363 }
1364
1365 if let StmtKind::MacCall(mac) = stmt.kind {
1366 let (mac, style, attrs) = mac.into_inner();
1367 self.check_attributes(&attrs);
1368 let mut placeholder =
1369 self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts();
1370
1371 // If this is a macro invocation with a semicolon, then apply that
1372 // semicolon to the final statement produced by expansion.
1373 if style == MacStmtStyle::Semicolon {
1374 if let Some(stmt) = placeholder.pop() {
1375 placeholder.push(stmt.add_trailing_semicolon());
1376 }
1377 }
1378
1379 return placeholder;
1380 }
1381
1382 // The placeholder expander gives ids to statements, so we avoid folding the id here.
1383 let ast::Stmt { id, kind, span } = stmt;
1384 noop_flat_map_stmt_kind(kind, self)
1385 .into_iter()
1386 .map(|kind| ast::Stmt { id, kind, span })
1387 .collect()
1388 }
1389
1390 fn visit_block(&mut self, block: &mut P<Block>) {
1391 let old_directory_ownership = self.cx.current_expansion.directory_ownership;
1392 self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
1393 noop_visit_block(block, self);
1394 self.cx.current_expansion.directory_ownership = old_directory_ownership;
1395 }
1396
1397 fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
1398 let mut item = configure!(self, item);
1399
1400 let (attr, traits, after_derive) = self.classify_item(&mut item);
1401 if attr.is_some() || !traits.is_empty() {
1402 return self
1403 .collect_attr(
1404 attr,
1405 traits,
1406 Annotatable::Item(item),
1407 AstFragmentKind::Items,
1408 after_derive,
1409 )
1410 .make_items();
1411 }
1412
1413 let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
1414 let ident = item.ident;
1415 let span = item.span;
1416
1417 match item.kind {
1418 ast::ItemKind::MacCall(..) => {
1419 item.attrs = attrs;
1420 self.check_attributes(&item.attrs);
1421 item.and_then(|item| match item.kind {
1422 ItemKind::MacCall(mac) => self
1423 .collect(AstFragmentKind::Items, InvocationKind::Bang { mac, span })
1424 .make_items(),
1425 _ => unreachable!(),
1426 })
1427 }
1428 ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => {
1429 let sess = &self.cx.sess.parse_sess;
1430 let orig_ownership = self.cx.current_expansion.directory_ownership;
1431 let mut module = (*self.cx.current_expansion.module).clone();
1432
1433 let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
1434 let dir = Directory { ownership: orig_ownership, path: module.directory };
1435 let Directory { ownership, path } = if old_mod.inline {
1436 // Inline `mod foo { ... }`, but we still need to push directories.
1437 item.attrs = attrs;
1438 push_directory(&self.cx.sess, ident, &item.attrs, dir)
1439 } else {
1440 // We have an outline `mod foo;` so we need to parse the file.
1441 let (new_mod, dir) =
1442 parse_external_mod(&self.cx.sess, ident, span, dir, &mut attrs, pushed);
1443
1444 let krate = ast::Crate {
1445 span: new_mod.inner,
1446 module: new_mod,
1447 attrs,
1448 proc_macros: vec![],
1449 };
1450 if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
1451 extern_mod_loaded(&krate);
1452 }
1453
1454 *old_mod = krate.module;
1455 item.attrs = krate.attrs;
1456 // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1457 item = match self.configure(item) {
1458 Some(node) => node,
1459 None => {
1460 if *pushed {
1461 sess.included_mod_stack.borrow_mut().pop();
1462 }
1463 return Default::default();
1464 }
1465 };
1466 dir
1467 };
1468
1469 // Set the module info before we flat map.
1470 self.cx.current_expansion.directory_ownership = ownership;
1471 module.directory = path;
1472 module.mod_path.push(ident);
1473 let orig_module =
1474 mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
1475
1476 let result = noop_flat_map_item(item, self);
1477
1478 // Restore the module info.
1479 self.cx.current_expansion.module = orig_module;
1480 self.cx.current_expansion.directory_ownership = orig_ownership;
1481 if *pushed {
1482 sess.included_mod_stack.borrow_mut().pop();
1483 }
1484 result
1485 }
1486 _ => {
1487 item.attrs = attrs;
1488 noop_flat_map_item(item, self)
1489 }
1490 }
1491 }
1492
1493 fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
1494 let mut item = configure!(self, item);
1495
1496 let (attr, traits, after_derive) = self.classify_item(&mut item);
1497 if attr.is_some() || !traits.is_empty() {
1498 return self
1499 .collect_attr(
1500 attr,
1501 traits,
1502 Annotatable::TraitItem(item),
1503 AstFragmentKind::TraitItems,
1504 after_derive,
1505 )
1506 .make_trait_items();
1507 }
1508
1509 match item.kind {
1510 ast::AssocItemKind::MacCall(..) => {
1511 self.check_attributes(&item.attrs);
1512 item.and_then(|item| match item.kind {
1513 ast::AssocItemKind::MacCall(mac) => self
1514 .collect_bang(mac, item.span, AstFragmentKind::TraitItems)
1515 .make_trait_items(),
1516 _ => unreachable!(),
1517 })
1518 }
1519 _ => noop_flat_map_assoc_item(item, self),
1520 }
1521 }
1522
1523 fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
1524 let mut item = configure!(self, item);
1525
1526 let (attr, traits, after_derive) = self.classify_item(&mut item);
1527 if attr.is_some() || !traits.is_empty() {
1528 return self
1529 .collect_attr(
1530 attr,
1531 traits,
1532 Annotatable::ImplItem(item),
1533 AstFragmentKind::ImplItems,
1534 after_derive,
1535 )
1536 .make_impl_items();
1537 }
1538
1539 match item.kind {
1540 ast::AssocItemKind::MacCall(..) => {
1541 self.check_attributes(&item.attrs);
1542 item.and_then(|item| match item.kind {
1543 ast::AssocItemKind::MacCall(mac) => self
1544 .collect_bang(mac, item.span, AstFragmentKind::ImplItems)
1545 .make_impl_items(),
1546 _ => unreachable!(),
1547 })
1548 }
1549 _ => noop_flat_map_assoc_item(item, self),
1550 }
1551 }
1552
1553 fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
1554 match ty.kind {
1555 ast::TyKind::MacCall(_) => {}
1556 _ => return noop_visit_ty(ty, self),
1557 };
1558
1559 visit_clobber(ty, |mut ty| match mem::replace(&mut ty.kind, ast::TyKind::Err) {
1560 ast::TyKind::MacCall(mac) => {
1561 self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty()
1562 }
1563 _ => unreachable!(),
1564 });
1565 }
1566
1567 fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
1568 self.cfg.configure_foreign_mod(foreign_mod);
1569 noop_visit_foreign_mod(foreign_mod, self);
1570 }
1571
1572 fn flat_map_foreign_item(
1573 &mut self,
1574 mut foreign_item: P<ast::ForeignItem>,
1575 ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
1576 let (attr, traits, after_derive) = self.classify_item(&mut foreign_item);
1577
1578 if attr.is_some() || !traits.is_empty() {
1579 return self
1580 .collect_attr(
1581 attr,
1582 traits,
1583 Annotatable::ForeignItem(foreign_item),
1584 AstFragmentKind::ForeignItems,
1585 after_derive,
1586 )
1587 .make_foreign_items();
1588 }
1589
1590 match foreign_item.kind {
1591 ast::ForeignItemKind::MacCall(..) => {
1592 self.check_attributes(&foreign_item.attrs);
1593 foreign_item.and_then(|item| match item.kind {
1594 ast::ForeignItemKind::MacCall(mac) => self
1595 .collect_bang(mac, item.span, AstFragmentKind::ForeignItems)
1596 .make_foreign_items(),
1597 _ => unreachable!(),
1598 })
1599 }
1600 _ => noop_flat_map_foreign_item(foreign_item, self),
1601 }
1602 }
1603
1604 fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
1605 match item {
1606 ast::ItemKind::MacroDef(..) => {}
1607 _ => {
1608 self.cfg.configure_item_kind(item);
1609 noop_visit_item_kind(item, self);
1610 }
1611 }
1612 }
1613
1614 fn flat_map_generic_param(
1615 &mut self,
1616 param: ast::GenericParam,
1617 ) -> SmallVec<[ast::GenericParam; 1]> {
1618 let mut param = configure!(self, param);
1619
1620 let (attr, traits, after_derive) = self.classify_item(&mut param);
1621 if attr.is_some() || !traits.is_empty() {
1622 return self
1623 .collect_attr(
1624 attr,
1625 traits,
1626 Annotatable::GenericParam(param),
1627 AstFragmentKind::GenericParams,
1628 after_derive,
1629 )
1630 .make_generic_params();
1631 }
1632
1633 noop_flat_map_generic_param(param, self)
1634 }
1635
1636 fn visit_attribute(&mut self, at: &mut ast::Attribute) {
1637 // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
1638 // contents="file contents")]` attributes
1639 if !self.cx.sess.check_name(at, sym::doc) {
1640 return noop_visit_attribute(at, self);
1641 }
1642
1643 if let Some(list) = at.meta_item_list() {
1644 if !list.iter().any(|it| it.has_name(sym::include)) {
1645 return noop_visit_attribute(at, self);
1646 }
1647
1648 let mut items = vec![];
1649
1650 for mut it in list {
1651 if !it.has_name(sym::include) {
1652 items.push({
1653 noop_visit_meta_list_item(&mut it, self);
1654 it
1655 });
1656 continue;
1657 }
1658
1659 if let Some(file) = it.value_str() {
1660 let err_count = self.cx.sess.parse_sess.span_diagnostic.err_count();
1661 self.check_attributes(slice::from_ref(at));
1662 if self.cx.sess.parse_sess.span_diagnostic.err_count() > err_count {
1663 // avoid loading the file if they haven't enabled the feature
1664 return noop_visit_attribute(at, self);
1665 }
1666
1667 let filename = match self.cx.resolve_path(&*file.as_str(), it.span()) {
1668 Ok(filename) => filename,
1669 Err(mut err) => {
1670 err.emit();
1671 continue;
1672 }
1673 };
1674
1675 match self.cx.source_map().load_file(&filename) {
1676 Ok(source_file) => {
1677 let src = source_file
1678 .src
1679 .as_ref()
1680 .expect("freshly loaded file should have a source");
1681 let src_interned = Symbol::intern(src.as_str());
1682
1683 let include_info = vec![
1684 ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str(
1685 Ident::with_dummy_span(sym::file),
1686 file,
1687 DUMMY_SP,
1688 )),
1689 ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str(
1690 Ident::with_dummy_span(sym::contents),
1691 src_interned,
1692 DUMMY_SP,
1693 )),
1694 ];
1695
1696 let include_ident = Ident::with_dummy_span(sym::include);
1697 let item = attr::mk_list_item(include_ident, include_info);
1698 items.push(ast::NestedMetaItem::MetaItem(item));
1699 }
1700 Err(e) => {
1701 let lit =
1702 it.meta_item().and_then(|item| item.name_value_literal()).unwrap();
1703
1704 if e.kind() == ErrorKind::InvalidData {
1705 self.cx
1706 .struct_span_err(
1707 lit.span,
1708 &format!("{} wasn't a utf-8 file", filename.display()),
1709 )
1710 .span_label(lit.span, "contains invalid utf-8")
1711 .emit();
1712 } else {
1713 let mut err = self.cx.struct_span_err(
1714 lit.span,
1715 &format!("couldn't read {}: {}", filename.display(), e),
1716 );
1717 err.span_label(lit.span, "couldn't read file");
1718
1719 err.emit();
1720 }
1721 }
1722 }
1723 } else {
1724 let mut err = self
1725 .cx
1726 .struct_span_err(it.span(), "expected path to external documentation");
1727
1728 // Check if the user erroneously used `doc(include(...))` syntax.
1729 let literal = it.meta_item_list().and_then(|list| {
1730 if list.len() == 1 {
1731 list[0].literal().map(|literal| &literal.kind)
1732 } else {
1733 None
1734 }
1735 });
1736
1737 let (path, applicability) = match &literal {
1738 Some(LitKind::Str(path, ..)) => {
1739 (path.to_string(), Applicability::MachineApplicable)
1740 }
1741 _ => (String::from("<path>"), Applicability::HasPlaceholders),
1742 };
1743
1744 err.span_suggestion(
1745 it.span(),
1746 "provide a file path with `=`",
1747 format!("include = \"{}\"", path),
1748 applicability,
1749 );
1750
1751 err.emit();
1752 }
1753 }
1754
1755 let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
1756 *at = ast::Attribute {
1757 kind: ast::AttrKind::Normal(AttrItem {
1758 path: meta.path,
1759 args: meta.kind.mac_args(meta.span),
1760 }),
1761 span: at.span,
1762 id: at.id,
1763 style: at.style,
1764 };
1765 } else {
1766 noop_visit_attribute(at, self)
1767 }
1768 }
1769
1770 fn visit_id(&mut self, id: &mut ast::NodeId) {
1771 if self.monotonic {
1772 debug_assert_eq!(*id, ast::DUMMY_NODE_ID);
1773 *id = self.cx.resolver.next_node_id()
1774 }
1775 }
1776
1777 fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) {
1778 self.cfg.configure_fn_decl(&mut fn_decl);
1779 noop_visit_fn_decl(fn_decl, self);
1780 }
1781 }
1782
1783 pub struct ExpansionConfig<'feat> {
1784 pub crate_name: String,
1785 pub features: Option<&'feat Features>,
1786 pub recursion_limit: Limit,
1787 pub trace_mac: bool,
1788 pub should_test: bool, // If false, strip `#[test]` nodes
1789 pub keep_macs: bool,
1790 pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
1791 }
1792
1793 impl<'feat> ExpansionConfig<'feat> {
1794 pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1795 ExpansionConfig {
1796 crate_name,
1797 features: None,
1798 recursion_limit: Limit::new(1024),
1799 trace_mac: false,
1800 should_test: false,
1801 keep_macs: false,
1802 span_debug: false,
1803 }
1804 }
1805
1806 fn proc_macro_hygiene(&self) -> bool {
1807 self.features.map_or(false, |features| features.proc_macro_hygiene)
1808 }
1809 fn custom_inner_attributes(&self) -> bool {
1810 self.features.map_or(false, |features| features.custom_inner_attributes)
1811 }
1812 }