2 use crate::config
::StripUnconfigured
;
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
;
10 use rustc_ast
::mut_visit
::*;
11 use rustc_ast
::ptr
::P
;
13 use rustc_ast
::tokenstream
::TokenStream
;
14 use rustc_ast
::visit
::{self, AssocCtxt, Visitor}
;
15 use rustc_ast
::{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}
;
33 use smallvec
::{smallvec, SmallVec}
;
34 use std
::io
::ErrorKind
;
35 use std
::ops
::DerefMut
;
36 use std
::path
::PathBuf
;
38 use std
::{iter, mem, slice}
;
40 macro_rules
! ast_fragments
{
42 $
($Kind
:ident($AstTy
:ty
) {
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
)*);)?
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
>>),
56 /// "Discriminant" of an AST fragment.
57 #[derive(Copy, Clone, PartialEq, Eq)]
58 pub enum AstFragmentKind
{
63 impl AstFragmentKind
{
64 pub fn name(self) -> &'
static str {
66 AstFragmentKind
::OptExpr
=> "expression",
67 $
(AstFragmentKind
::$Kind
=> $kind_name
,)*
71 fn make_from
<'a
>(self, result
: Box
<dyn MacResult
+ 'a
>) -> Option
<AstFragment
> {
73 AstFragmentKind
::OptExpr
=>
74 result
.make_expr().map(Some
).map(AstFragment
::OptExpr
),
75 $
(AstFragmentKind
::$Kind
=> result
.$
make_ast().map(AstFragment
::$Kind
),)*
81 pub fn add_placeholders(&mut self, placeholders
: &[NodeId
]) {
82 if placeholders
.is_empty() {
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()
92 _
=> panic
!("unexpected AST fragment kind")
96 pub fn make_opt_expr(self) -> Option
<P
<ast
::Expr
>> {
98 AstFragment
::OptExpr(expr
) => expr
,
99 _
=> panic
!("AstFragment::make_* called on the wrong kind of fragment"),
103 $
(pub fn $
make_ast(self) -> $AstTy
{
105 AstFragment
::$
Kind(ast
) => ast
,
106 _
=> panic
!("AstFragment::make_* called on the wrong kind of fragment"),
110 pub fn mut_visit_with
<F
: MutVisitor
>(&mut self, vis
: &mut F
) {
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
)
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
)),)?
)*
127 pub fn visit_with
<'a
, V
: Visitor
<'a
>>(&'a
self, visitor
: &mut V
) {
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
)*);
139 impl<'a
> MacResult
for crate::mbe
::macro_rules
::ParserAnyMacro
<'a
> {
140 $
(fn $
make_ast(self: Box
<crate::mbe
::macro_rules
::ParserAnyMacro
<'a
>>)
142 Some(self.make(AstFragmentKind
::$Kind
).$
make_ast())
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
;
155 Items(SmallVec
<[P
<ast
::Item
>; 1]>) {
156 "item"; many
fn flat_map_item
; fn visit_item(); fn make_items
;
158 TraitItems(SmallVec
<[P
<ast
::AssocItem
>; 1]>) {
160 many
fn flat_map_trait_item
;
161 fn visit_assoc_item(AssocCtxt
::Trait
);
164 ImplItems(SmallVec
<[P
<ast
::AssocItem
>; 1]>) {
166 many
fn flat_map_impl_item
;
167 fn visit_assoc_item(AssocCtxt
::Impl
);
170 ForeignItems(SmallVec
<[P
<ast
::ForeignItem
>; 1]>) {
172 many
fn flat_map_foreign_item
;
173 fn visit_foreign_item();
174 fn make_foreign_items
;
176 Arms(SmallVec
<[ast
::Arm
; 1]>) {
177 "match arm"; many
fn flat_map_arm
; fn visit_arm(); fn make_arms
;
179 Fields(SmallVec
<[ast
::Field
; 1]>) {
180 "field expression"; many
fn flat_map_field
; fn visit_field(); fn make_fields
;
182 FieldPats(SmallVec
<[ast
::FieldPat
; 1]>) {
184 many
fn flat_map_field_pattern
;
185 fn visit_field_pattern();
186 fn make_field_patterns
;
188 GenericParams(SmallVec
<[ast
::GenericParam
; 1]>) {
190 many
fn flat_map_generic_param
;
191 fn visit_generic_param();
192 fn make_generic_params
;
194 Params(SmallVec
<[ast
::Param
; 1]>) {
195 "function parameter"; many
fn flat_map_param
; fn visit_param(); fn make_params
;
197 StructFields(SmallVec
<[ast
::StructField
; 1]>) {
199 many
fn flat_map_struct_field
;
200 fn visit_struct_field();
201 fn make_struct_fields
;
203 Variants(SmallVec
<[ast
::Variant
; 1]>) {
204 "variant"; many
fn flat_map_variant
; fn visit_variant(); fn make_variants
;
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")
213 fn expect_from_annotatables
<I
: IntoIterator
<Item
= Annotatable
>>(
217 let mut items
= items
.into_iter();
219 AstFragmentKind
::Arms
=> {
220 AstFragment
::Arms(items
.map(Annotatable
::expect_arm
).collect())
222 AstFragmentKind
::Fields
=> {
223 AstFragment
::Fields(items
.map(Annotatable
::expect_field
).collect())
225 AstFragmentKind
::FieldPats
=> {
226 AstFragment
::FieldPats(items
.map(Annotatable
::expect_field_pattern
).collect())
228 AstFragmentKind
::GenericParams
=> {
229 AstFragment
::GenericParams(items
.map(Annotatable
::expect_generic_param
).collect())
231 AstFragmentKind
::Params
=> {
232 AstFragment
::Params(items
.map(Annotatable
::expect_param
).collect())
234 AstFragmentKind
::StructFields
=> {
235 AstFragment
::StructFields(items
.map(Annotatable
::expect_struct_field
).collect())
237 AstFragmentKind
::Variants
=> {
238 AstFragment
::Variants(items
.map(Annotatable
::expect_variant
).collect())
240 AstFragmentKind
::Items
=> {
241 AstFragment
::Items(items
.map(Annotatable
::expect_item
).collect())
243 AstFragmentKind
::ImplItems
=> {
244 AstFragment
::ImplItems(items
.map(Annotatable
::expect_impl_item
).collect())
246 AstFragmentKind
::TraitItems
=> {
247 AstFragment
::TraitItems(items
.map(Annotatable
::expect_trait_item
).collect())
249 AstFragmentKind
::ForeignItems
=> {
250 AstFragment
::ForeignItems(items
.map(Annotatable
::expect_foreign_item
).collect())
252 AstFragmentKind
::Stmts
=> {
253 AstFragment
::Stmts(items
.map(Annotatable
::expect_stmt
).collect())
255 AstFragmentKind
::Expr
=> AstFragment
::Expr(
256 items
.next().expect("expected exactly one expression").expect_expr(),
258 AstFragmentKind
::OptExpr
=> {
259 AstFragment
::OptExpr(items
.next().map(Annotatable
::expect_expr
))
261 AstFragmentKind
::Pat
| AstFragmentKind
::Ty
=> {
262 panic
!("patterns and types aren't annotatable")
268 pub struct Invocation
{
269 pub kind
: InvocationKind
,
270 pub fragment_kind
: AstFragmentKind
,
271 pub expansion_data
: ExpansionData
,
274 pub enum InvocationKind
{
280 attr
: ast
::Attribute
,
282 // Required for resolving derive helper attributes.
284 // We temporarily report errors for attribute macros placed after derives
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.
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.
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() =>
313 Some(field
.vis
.clone())
321 pub fn span(&self) -> Span
{
323 InvocationKind
::Bang { span, .. }
=> *span
,
324 InvocationKind
::Attr { attr, .. }
=> attr
.span
,
325 InvocationKind
::Derive { path, .. }
=> path
.span
,
326 InvocationKind
::DeriveContainer { item, .. }
=> item
.span(),
331 pub struct MacroExpander
<'a
, 'b
> {
332 pub cx
: &'a
mut ExtCtxt
<'b
>,
333 monotonic
: bool
, // cf. `cx.monotonic_expander()`
336 impl<'a
, 'b
> MacroExpander
<'a
, 'b
> {
337 pub fn new(cx
: &'a
mut ExtCtxt
<'b
>, monotonic
: bool
) -> Self {
338 MacroExpander { cx, monotonic }
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()),
349 module
.directory
.pop();
350 self.cx
.root_path
= module
.directory
.clone();
351 self.cx
.current_expansion
.module
= Rc
::new(module
);
353 let orig_mod_span
= krate
.module
.inner
;
355 let krate_item
= AstFragment
::Items(smallvec
![P(ast
::Item
{
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
),
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), .. }
) => {
368 krate
.module
= module
;
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 }
;
375 Some(ast
::Item { span, kind, .. }
) => {
376 krate
.attrs
= vec
![];
377 krate
.module
= ast
::Mod { inner: orig_mod_span, items: vec![], inline: true }
;
381 "expected crate top-level item to be a module after macro expansion, found {} {}",
382 kind
.article(), kind
.descr()
387 self.cx
.trace_macros_diag();
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;
396 // Collect all macro invocations and replace them with placeholders.
397 let (mut fragment_with_placeholders
, mut invocations
) =
398 self.collect_invocations(input_fragment
, &[]);
400 // Optimization: if we resolve all imports now,
401 // we'll be able to immediately resolve most of imported macros.
402 self.resolve_imports();
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
);
413 let (invoc
, res
) = if let Some(invoc
) = invocations
.pop() {
416 self.resolve_imports();
417 if undetermined_invocations
.is_empty() {
420 invocations
= mem
::take(&mut undetermined_invocations
);
421 force
= !mem
::replace(&mut progress
, false);
425 let res
= match res
{
428 let eager_expansion_root
= if self.monotonic
{
429 invoc
.expansion_data
.id
431 orig_expansion_data
.id
433 match self.cx
.resolver
.resolve_macro_invocation(
435 eager_expansion_root
,
439 Err(Indeterminate
) => {
440 // Cannot resolve, will retry this invocation later.
441 undetermined_invocations
.push((invoc
, None
));
448 let ExpansionData { depth, id: expn_id, .. }
= invoc
.expansion_data
;
449 self.cx
.current_expansion
= invoc
.expansion_data
.clone();
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
) => {
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
, &[])
463 // Cannot expand, will retry this invocation later.
464 undetermined_invocations
465 .push((invoc
, Some(InvocationRes
::Single(ext
))));
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
),
477 if !item
.derive_allowed() {
478 self.error_derive_forbidden_on_non_adt(&derives
, &item
);
481 let mut item
= self.fully_configure(item
);
482 item
.visit_attrs(|attrs
| attrs
.retain(|a
| !a
.has_name(sym
::derive
)));
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
));
491 kind
: InvocationKind
::Derive { path, item: item.clone() }
,
492 fragment_kind
: invoc
.fragment_kind
,
493 expansion_data
: ExpansionData
{
495 ..invoc
.expansion_data
.clone()
502 invoc
.fragment_kind
.expect_from_annotatables(::std
::iter
::once(item
));
503 self.collect_invocations(fragment
, &derive_placeholders
)
508 if expanded_fragments
.len() < depth
{
509 expanded_fragments
.push(Vec
::new());
511 expanded_fragments
[depth
- 1].push((expn_id
, expanded_fragment
));
512 invocations
.extend(new_invocations
.into_iter().rev());
515 self.cx
.current_expansion
= orig_expansion_data
;
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() {
522 .add(NodeId
::placeholder_from_expn_id(expn_id
), expanded_fragment
);
525 fragment_with_placeholders
.mut_visit_with(&mut placeholder_expander
);
526 fragment_with_placeholders
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
);
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(", "));
540 "try an outer attribute",
542 // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
543 Applicability
::MaybeIncorrect
,
549 fn resolve_imports(&mut self) {
551 self.cx
.resolver
.resolve_imports();
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(
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();
568 let mut collector
= InvocationCollector
{
569 cfg
: StripUnconfigured { sess: &self.cx.sess, features: self.cx.ecfg.features }
,
571 invocations
: Vec
::new(),
572 monotonic
: self.monotonic
,
574 fragment
.mut_visit_with(&mut collector
);
575 fragment
.add_placeholders(extra_placeholders
);
576 collector
.invocations
582 .visit_ast_fragment_with_placeholders(self.cx
.current_expansion
.id
, &fragment
);
585 (fragment
, invocations
)
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
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())
597 Annotatable
::ImplItem(item
) => {
598 Annotatable
::ImplItem(cfg
.flat_map_impl_item(item
).pop().unwrap())
600 Annotatable
::ForeignItem(item
) => {
601 Annotatable
::ForeignItem(cfg
.flat_map_foreign_item(item
).pop().unwrap())
603 Annotatable
::Stmt(stmt
) => {
604 Annotatable
::Stmt(stmt
.map(|stmt
| cfg
.flat_map_stmt(stmt
).pop().unwrap()))
606 Annotatable
::Expr(mut expr
) => Annotatable
::Expr({
607 cfg
.visit_expr(&mut expr
);
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())
614 Annotatable
::FieldPat(fp
) => {
615 Annotatable
::FieldPat(cfg
.flat_map_field_pattern(fp
).pop().unwrap())
617 Annotatable
::GenericParam(param
) => {
618 Annotatable
::GenericParam(cfg
.flat_map_generic_param(param
).pop().unwrap())
620 Annotatable
::Param(param
) => {
621 Annotatable
::Param(cfg
.flat_map_param(param
).pop().unwrap())
623 Annotatable
::StructField(sf
) => {
624 Annotatable
::StructField(cfg
.flat_map_struct_field(sf
).pop().unwrap())
626 Annotatable
::Variant(v
) => Annotatable
::Variant(cfg
.flat_map_variant(v
).pop().unwrap()),
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;
636 &format
!("recursion limit reached while expanding `{}`", expn_data
.kind
.descr()),
639 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
640 suggested_limit
, self.cx
.ecfg
.crate_name
,
643 self.cx
.trace_macros_diag();
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
) {
650 "non-{kind} macro in {kind} position: {path}",
652 path
= pprust
::path_to_string(&mac
.path
),
654 self.cx
.span_err(span
, &msg
);
655 self.cx
.trace_macros_diag();
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();
670 // Reduce the recursion limit by half each time it triggers.
671 self.cx
.reduced_recursion_limit
= Some(recursion_limit
/ 2);
673 return ExpandResult
::Ready(invoc
.fragment_kind
.dummy(invoc
.span()));
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
)),
684 self.parse_ast_fragment(tok_result
, fragment_kind
, &mac
.path
, span
)
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
) {
693 self.error_wrong_fragment_kind(fragment_kind
, &mac
, span
);
694 fragment_kind
.dummy(span
)
696 self.cx
.current_expansion
.prior_type_ascription
= prev
;
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");
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
)),
715 self.parse_ast_fragment(tok_result
, fragment_kind
, &attr_item
.path
, span
)
717 SyntaxExtensionKind
::LegacyAttr(expander
) => {
718 match validate_attr
::parse_meta(&self.cx
.sess
.parse_sess
, &attr
) {
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(
726 kind
: InvocationKind
::Attr
{
738 fragment_kind
.expect_from_annotatables(items
)
742 fragment_kind
.dummy(span
)
746 SyntaxExtensionKind
::NonMacroAttr { mark_used }
=> {
747 self.cx
.sess
.mark_attr_known(&attr
);
749 self.cx
.sess
.mark_attr_used(&attr
);
751 item
.visit_attrs(|attrs
| attrs
.push(attr
));
752 fragment_kind
.expect_from_annotatables(iter
::once(item
))
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
));
762 if let SyntaxExtensionKind
::Derive(..) = ext
{
763 self.gate_proc_macro_input(&item
);
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(
772 kind
: InvocationKind
::Derive { path: meta.path, item }
,
779 fragment_kind
.expect_from_annotatables(items
)
783 InvocationKind
::DeriveContainer { .. }
=> unreachable
!(),
787 fn gate_proc_macro_attr_item(&self, span
: Span
, item
: &Annotatable
) {
788 let kind
= match item
{
790 | Annotatable
::TraitItem(_
)
791 | Annotatable
::ImplItem(_
)
792 | Annotatable
::ForeignItem(_
) => return,
793 Annotatable
::Stmt(_
) => "statements",
794 Annotatable
::Expr(_
) => "expressions",
796 | Annotatable
::Field(..)
797 | Annotatable
::FieldPat(..)
798 | Annotatable
::GenericParam(..)
799 | Annotatable
::Param(..)
800 | Annotatable
::StructField(..)
801 | Annotatable
::Variant(..) => panic
!("unexpected annotatable"),
803 if self.cx
.ecfg
.proc_macro_hygiene() {
807 &self.cx
.sess
.parse_sess
,
808 sym
::proc_macro_hygiene
,
810 &format
!("custom attributes cannot be applied to {}", kind
),
815 fn gate_proc_macro_input(&self, annotatable
: &Annotatable
) {
816 struct GateProcMacroInput
<'a
> {
817 parse_sess
: &'a ParseSess
,
820 impl<'ast
, 'a
> Visitor
<'ast
> for GateProcMacroInput
<'a
> {
821 fn visit_item(&mut self, item
: &'ast ast
::Item
) {
823 ast
::ItemKind
::Mod(module
) if !module
.inline
=> {
826 sym
::proc_macro_hygiene
,
828 "non-inline modules in proc macro input are unstable",
835 visit
::walk_item(self, item
);
838 fn visit_mac(&mut self, _
: &'ast ast
::MacCall
) {}
841 if !self.cx
.ecfg
.proc_macro_hygiene() {
843 .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess }
);
847 fn parse_ast_fragment(
850 kind
: AstFragmentKind
,
854 let mut parser
= self.cx
.new_parser_from_tts(toks
);
855 match parse_ast_fragment(&mut parser
, kind
) {
857 ensure_complete_parse(&mut parser
, path
, kind
.name(), span
);
862 annotate_err_with_kind(&mut err
, kind
, span
);
864 self.cx
.trace_macros_diag();
871 pub fn parse_ast_fragment
<'a
>(
872 this
: &mut Parser
<'a
>,
873 kind
: AstFragmentKind
,
874 ) -> PResult
<'a
, AstFragment
> {
876 AstFragmentKind
::Items
=> {
877 let mut items
= SmallVec
::new();
878 while let Some(item
) = this
.parse_item()?
{
881 AstFragment
::Items(items
)
883 AstFragmentKind
::TraitItems
=> {
884 let mut items
= SmallVec
::new();
885 while let Some(item
) = this
.parse_trait_item()?
{
888 AstFragment
::TraitItems(items
)
890 AstFragmentKind
::ImplItems
=> {
891 let mut items
= SmallVec
::new();
892 while let Some(item
) = this
.parse_impl_item()?
{
895 AstFragment
::ImplItems(items
)
897 AstFragmentKind
::ForeignItems
=> {
898 let mut items
= SmallVec
::new();
899 while let Some(item
) = this
.parse_foreign_item()?
{
902 AstFragment
::ForeignItems(items
)
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()?
{
912 AstFragment
::Stmts(stmts
)
914 AstFragmentKind
::Expr
=> AstFragment
::Expr(this
.parse_expr()?
),
915 AstFragmentKind
::OptExpr
=> {
916 if this
.token
!= token
::Eof
{
917 AstFragment
::OptExpr(Some(this
.parse_expr()?
))
919 AstFragment
::OptExpr(None
)
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"),
934 pub fn ensure_complete_parse
<'a
>(
935 this
: &mut Parser
<'a
>,
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");
948 "the usage of `{}!` is likely invalid in {} context",
949 pprust
::path_to_string(macro_path
),
953 let semi_span
= this
.sess
.source_map().next_point(span
);
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" => {
960 "you might be missing a semicolon here",
962 Applicability
::MaybeIncorrect
,
971 struct InvocationCollector
<'a
, 'b
> {
972 cx
: &'a
mut ExtCtxt
<'b
>,
973 cfg
: StripUnconfigured
<'a
>,
974 invocations
: Vec
<(Invocation
, Option
<InvocationRes
>)>,
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
,
987 ExpnKind
::Macro(MacroKind
::Attr
, sym
::derive
),
989 self.cx
.sess
.parse_sess
.edition
,
995 let expn_id
= ExpnId
::fresh(expn_data
);
996 let vis
= kind
.placeholder_visibility();
997 self.invocations
.push((
1001 expansion_data
: ExpansionData
{
1003 depth
: self.cx
.current_expansion
.depth
+ 1,
1004 ..self.cx
.current_expansion
.clone()
1009 placeholder(fragment_kind
, NodeId
::placeholder_from_expn_id(expn_id
), vis
)
1016 kind
: AstFragmentKind
,
1018 self.collect(kind
, InvocationKind
::Bang { mac, span }
)
1023 attr
: Option
<ast
::Attribute
>,
1026 kind
: AstFragmentKind
,
1032 Some(attr
) => InvocationKind
::Attr { attr, item, derives, after_derive }
,
1033 None
=> InvocationKind
::DeriveContainer { derives, item }
,
1040 attrs
: &mut Vec
<ast
::Attribute
>,
1041 after_derive
: &mut bool
,
1042 ) -> Option
<ast
::Attribute
> {
1046 if a
.has_name(sym
::derive
) {
1047 *after_derive
= true;
1049 !self.cx
.sess
.is_attr_known(a
) && !is_builtin_attr(a
)
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
)
1058 &self.cx
.sess
.parse_sess
,
1059 sym
::custom_inner_attributes
,
1061 "non-builtin inner attributes are unstable",
1069 /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
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);
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
);
1081 (attr
, traits
, after_derive
)
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(
1089 nonitem
: &mut impl HasAttrs
,
1090 ) -> (Option
<ast
::Attribute
>, /* after_derive */ bool
) {
1091 let (mut attr
, mut after_derive
) = (None
, false);
1093 nonitem
.visit_attrs(|mut attrs
| {
1094 attr
= self.find_attr_invoc(&mut attrs
, &mut after_derive
);
1097 (attr
, after_derive
)
1100 fn configure
<T
: HasAttrs
>(&mut self, node
: T
) -> Option
<T
> {
1101 self.cfg
.configure(node
)
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
);
1112 // macros are expanded before any lint passes so this warning has to be hardcoded
1113 if attr
.has_name(sym
::derive
) {
1117 .struct_span_warn(attr
.span
, "`#[derive]` does nothing on macro invocations")
1118 .note("this may become a hard error in a future release")
1122 if attr
.doc_str().is_some() {
1123 self.cx
.sess
.parse_sess
.buffer_lint_with_diagnostic(
1124 &UNUSED_DOC_COMMENTS
,
1127 "unused doc comment",
1128 BuiltinLintDiagnostics
::UnusedDocComment(attr
.span
),
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
);
1141 // ignore derives so they remain unused
1142 let (attr
, after_derive
) = self.classify_nonitem(&mut expr
);
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
);
1149 // AstFragmentKind::Expr requires the macro to emit an expression.
1154 Annotatable
::Expr(P(expr
)),
1155 AstFragmentKind
::Expr
,
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()
1166 ensure_sufficient_stack(|| noop_visit_expr(&mut expr
, self));
1172 fn flat_map_arm(&mut self, arm
: ast
::Arm
) -> SmallVec
<[ast
::Arm
; 1]> {
1173 let mut arm
= configure
!(self, arm
);
1175 let (attr
, traits
, after_derive
) = self.classify_item(&mut arm
);
1176 if attr
.is_some() || !traits
.is_empty() {
1181 Annotatable
::Arm(arm
),
1182 AstFragmentKind
::Arms
,
1188 noop_flat_map_arm(arm
, self)
1191 fn flat_map_field(&mut self, field
: ast
::Field
) -> SmallVec
<[ast
::Field
; 1]> {
1192 let mut field
= configure
!(self, field
);
1194 let (attr
, traits
, after_derive
) = self.classify_item(&mut field
);
1195 if attr
.is_some() || !traits
.is_empty() {
1200 Annotatable
::Field(field
),
1201 AstFragmentKind
::Fields
,
1207 noop_flat_map_field(field
, self)
1210 fn flat_map_field_pattern(&mut self, fp
: ast
::FieldPat
) -> SmallVec
<[ast
::FieldPat
; 1]> {
1211 let mut fp
= configure
!(self, fp
);
1213 let (attr
, traits
, after_derive
) = self.classify_item(&mut fp
);
1214 if attr
.is_some() || !traits
.is_empty() {
1219 Annotatable
::FieldPat(fp
),
1220 AstFragmentKind
::FieldPats
,
1223 .make_field_patterns();
1226 noop_flat_map_field_pattern(fp
, self)
1229 fn flat_map_param(&mut self, p
: ast
::Param
) -> SmallVec
<[ast
::Param
; 1]> {
1230 let mut p
= configure
!(self, p
);
1232 let (attr
, traits
, after_derive
) = self.classify_item(&mut p
);
1233 if attr
.is_some() || !traits
.is_empty() {
1238 Annotatable
::Param(p
),
1239 AstFragmentKind
::Params
,
1245 noop_flat_map_param(p
, self)
1248 fn flat_map_struct_field(&mut self, sf
: ast
::StructField
) -> SmallVec
<[ast
::StructField
; 1]> {
1249 let mut sf
= configure
!(self, sf
);
1251 let (attr
, traits
, after_derive
) = self.classify_item(&mut sf
);
1252 if attr
.is_some() || !traits
.is_empty() {
1257 Annotatable
::StructField(sf
),
1258 AstFragmentKind
::StructFields
,
1261 .make_struct_fields();
1264 noop_flat_map_struct_field(sf
, self)
1267 fn flat_map_variant(&mut self, variant
: ast
::Variant
) -> SmallVec
<[ast
::Variant
; 1]> {
1268 let mut variant
= configure
!(self, variant
);
1270 let (attr
, traits
, after_derive
) = self.classify_item(&mut variant
);
1271 if attr
.is_some() || !traits
.is_empty() {
1276 Annotatable
::Variant(variant
),
1277 AstFragmentKind
::Variants
,
1283 noop_flat_map_variant(variant
, self)
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
);
1291 // Ignore derives so they remain unused.
1292 let (attr
, after_derive
) = self.classify_nonitem(&mut expr
);
1294 if let Some(ref attr_value
) = attr
{
1295 self.cfg
.maybe_emit_expr_attr_err(attr_value
);
1301 Annotatable
::Expr(P(expr
)),
1302 AstFragmentKind
::OptExpr
,
1306 .map(|expr
| expr
.into_inner());
1309 if let ast
::ExprKind
::MacCall(mac
) = expr
.kind
{
1310 self.check_attributes(&expr
.attrs
);
1311 self.collect_bang(mac
, expr
.span
, AstFragmentKind
::OptExpr
)
1313 .map(|expr
| expr
.into_inner())
1316 noop_visit_expr(&mut expr
, self);
1323 fn visit_pat(&mut self, pat
: &mut P
<ast
::Pat
>) {
1324 self.cfg
.configure_pat(pat
);
1326 PatKind
::MacCall(_
) => {}
1327 _
=> return noop_visit_pat(pat
, self),
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()
1334 _
=> unreachable
!(),
1338 fn flat_map_stmt(&mut self, stmt
: ast
::Stmt
) -> SmallVec
<[ast
::Stmt
; 1]> {
1339 let mut stmt
= configure
!(self, stmt
);
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
)
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
)
1352 if attr
.is_some() || !derives
.is_empty() {
1357 Annotatable
::Stmt(P(stmt
)),
1358 AstFragmentKind
::Stmts
,
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();
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());
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)
1386 .map(|kind
| ast
::Stmt { id, kind, span }
)
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
;
1397 fn flat_map_item(&mut self, item
: P
<ast
::Item
>) -> SmallVec
<[P
<ast
::Item
>; 1]> {
1398 let mut item
= configure
!(self, item
);
1400 let (attr
, traits
, after_derive
) = self.classify_item(&mut item
);
1401 if attr
.is_some() || !traits
.is_empty() {
1406 Annotatable
::Item(item
),
1407 AstFragmentKind
::Items
,
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
;
1418 ast
::ItemKind
::MacCall(..) => {
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 }
)
1425 _
=> unreachable
!(),
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();
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.
1438 push_directory(&self.cx
.sess
, ident
, &item
.attrs
, dir
)
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
);
1444 let krate
= ast
::Crate
{
1445 span
: new_mod
.inner
,
1448 proc_macros
: vec
![],
1450 if let Some(extern_mod_loaded
) = self.cx
.extern_mod_loaded
{
1451 extern_mod_loaded(&krate
);
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
) {
1461 sess
.included_mod_stack
.borrow_mut().pop();
1463 return Default
::default();
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
);
1474 mem
::replace(&mut self.cx
.current_expansion
.module
, Rc
::new(module
));
1476 let result
= noop_flat_map_item(item
, self);
1478 // Restore the module info.
1479 self.cx
.current_expansion
.module
= orig_module
;
1480 self.cx
.current_expansion
.directory_ownership
= orig_ownership
;
1482 sess
.included_mod_stack
.borrow_mut().pop();
1488 noop_flat_map_item(item
, self)
1493 fn flat_map_trait_item(&mut self, item
: P
<ast
::AssocItem
>) -> SmallVec
<[P
<ast
::AssocItem
>; 1]> {
1494 let mut item
= configure
!(self, item
);
1496 let (attr
, traits
, after_derive
) = self.classify_item(&mut item
);
1497 if attr
.is_some() || !traits
.is_empty() {
1502 Annotatable
::TraitItem(item
),
1503 AstFragmentKind
::TraitItems
,
1506 .make_trait_items();
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
!(),
1519 _
=> noop_flat_map_assoc_item(item
, self),
1523 fn flat_map_impl_item(&mut self, item
: P
<ast
::AssocItem
>) -> SmallVec
<[P
<ast
::AssocItem
>; 1]> {
1524 let mut item
= configure
!(self, item
);
1526 let (attr
, traits
, after_derive
) = self.classify_item(&mut item
);
1527 if attr
.is_some() || !traits
.is_empty() {
1532 Annotatable
::ImplItem(item
),
1533 AstFragmentKind
::ImplItems
,
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
)
1546 _
=> unreachable
!(),
1549 _
=> noop_flat_map_assoc_item(item
, self),
1553 fn visit_ty(&mut self, ty
: &mut P
<ast
::Ty
>) {
1555 ast
::TyKind
::MacCall(_
) => {}
1556 _
=> return noop_visit_ty(ty
, self),
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()
1563 _
=> unreachable
!(),
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);
1572 fn flat_map_foreign_item(
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
);
1578 if attr
.is_some() || !traits
.is_empty() {
1583 Annotatable
::ForeignItem(foreign_item
),
1584 AstFragmentKind
::ForeignItems
,
1587 .make_foreign_items();
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
!(),
1600 _
=> noop_flat_map_foreign_item(foreign_item
, self),
1604 fn visit_item_kind(&mut self, item
: &mut ast
::ItemKind
) {
1606 ast
::ItemKind
::MacroDef(..) => {}
1608 self.cfg
.configure_item_kind(item
);
1609 noop_visit_item_kind(item
, self);
1614 fn flat_map_generic_param(
1616 param
: ast
::GenericParam
,
1617 ) -> SmallVec
<[ast
::GenericParam
; 1]> {
1618 let mut param
= configure
!(self, param
);
1620 let (attr
, traits
, after_derive
) = self.classify_item(&mut param
);
1621 if attr
.is_some() || !traits
.is_empty() {
1626 Annotatable
::GenericParam(param
),
1627 AstFragmentKind
::GenericParams
,
1630 .make_generic_params();
1633 noop_flat_map_generic_param(param
, self)
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);
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);
1648 let mut items
= vec
![];
1650 for mut it
in list
{
1651 if !it
.has_name(sym
::include
) {
1653 noop_visit_meta_list_item(&mut it
, self);
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);
1667 let filename
= match self.cx
.resolve_path(&*file
.as_str(), it
.span()) {
1668 Ok(filename
) => filename
,
1675 match self.cx
.source_map().load_file(&filename
) {
1676 Ok(source_file
) => {
1677 let src
= source_file
1680 .expect("freshly loaded file should have a source");
1681 let src_interned
= Symbol
::intern(src
.as_str());
1683 let include_info
= vec
![
1684 ast
::NestedMetaItem
::MetaItem(attr
::mk_name_value_item_str(
1685 Ident
::with_dummy_span(sym
::file
),
1689 ast
::NestedMetaItem
::MetaItem(attr
::mk_name_value_item_str(
1690 Ident
::with_dummy_span(sym
::contents
),
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
));
1702 it
.meta_item().and_then(|item
| item
.name_value_literal()).unwrap();
1704 if e
.kind() == ErrorKind
::InvalidData
{
1708 &format
!("{} wasn't a utf-8 file", filename
.display()),
1710 .span_label(lit
.span
, "contains invalid utf-8")
1713 let mut err
= self.cx
.struct_span_err(
1715 &format
!("couldn't read {}: {}", filename
.display(), e
),
1717 err
.span_label(lit
.span
, "couldn't read file");
1726 .struct_span_err(it
.span(), "expected path to external documentation");
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
)
1737 let (path
, applicability
) = match &literal
{
1738 Some(LitKind
::Str(path
, ..)) => {
1739 (path
.to_string(), Applicability
::MachineApplicable
)
1741 _
=> (String
::from("<path>"), Applicability
::HasPlaceholders
),
1744 err
.span_suggestion(
1746 "provide a file path with `=`",
1747 format
!("include = \"{}\"", path
),
1755 let meta
= attr
::mk_list_item(Ident
::with_dummy_span(sym
::doc
), items
);
1756 *at
= ast
::Attribute
{
1757 kind
: ast
::AttrKind
::Normal(AttrItem
{
1759 args
: meta
.kind
.mac_args(meta
.span
),
1766 noop_visit_attribute(at
, self)
1770 fn visit_id(&mut self, id
: &mut ast
::NodeId
) {
1772 debug_assert_eq
!(*id
, ast
::DUMMY_NODE_ID
);
1773 *id
= self.cx
.resolver
.next_node_id()
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);
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`
1793 impl<'feat
> ExpansionConfig
<'feat
> {
1794 pub fn default(crate_name
: String
) -> ExpansionConfig
<'
static> {
1798 recursion_limit
: Limit
::new(1024),
1806 fn proc_macro_hygiene(&self) -> bool
{
1807 self.features
.map_or(false, |features
| features
.proc_macro_hygiene
)
1809 fn custom_inner_attributes(&self) -> bool
{
1810 self.features
.map_or(false, |features
| features
.custom_inner_attributes
)