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, AttrStyle, Block, LitKind, NodeId, PatKind, Path}
;
16 use rustc_ast
::{ItemKind, MacArgs, MacCallStmt, MacStmtStyle, StmtKind, Unsafe}
;
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
::{struct_span_err, Applicability, PResult}
;
22 use rustc_feature
::Features
;
23 use rustc_parse
::parser
::{AttemptLocalParseRecovery, ForceCollect, 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
::symbol
::{sym, Ident, Symbol}
;
30 use rustc_span
::{ExpnId, FileName, Span, DUMMY_SP}
;
32 use smallvec
::{smallvec, SmallVec}
;
33 use std
::io
::ErrorKind
;
34 use std
::ops
::DerefMut
;
35 use std
::path
::PathBuf
;
37 use std
::{iter, mem, slice}
;
39 macro_rules
! ast_fragments
{
41 $
($Kind
:ident($AstTy
:ty
) {
43 $
(one
fn $mut_visit_ast
:ident
; fn $visit_ast
:ident
;)?
44 $
(many
fn $flat_map_ast_elt
:ident
; fn $visit_ast_elt
:ident($
($args
:tt
)*);)?
48 /// A fragment of AST that can be produced by a single macro expansion.
49 /// Can also serve as an input and intermediate result for macro expansion operations.
50 pub enum AstFragment
{
51 OptExpr(Option
<P
<ast
::Expr
>>),
55 /// "Discriminant" of an AST fragment.
56 #[derive(Copy, Clone, PartialEq, Eq)]
57 pub enum AstFragmentKind
{
62 impl AstFragmentKind
{
63 pub fn name(self) -> &'
static str {
65 AstFragmentKind
::OptExpr
=> "expression",
66 $
(AstFragmentKind
::$Kind
=> $kind_name
,)*
70 fn make_from
<'a
>(self, result
: Box
<dyn MacResult
+ 'a
>) -> Option
<AstFragment
> {
72 AstFragmentKind
::OptExpr
=>
73 result
.make_expr().map(Some
).map(AstFragment
::OptExpr
),
74 $
(AstFragmentKind
::$Kind
=> result
.$
make_ast().map(AstFragment
::$Kind
),)*
80 pub fn add_placeholders(&mut self, placeholders
: &[NodeId
]) {
81 if placeholders
.is_empty() {
85 $
($
(AstFragment
::$
Kind(ast
) => ast
.extend(placeholders
.iter().flat_map(|id
| {
86 // We are repeating through arguments with `many`, to do that we have to
87 // mention some macro variable from those arguments even if it's not used.
88 macro _repeating($flat_map_ast_elt
) {}
89 placeholder(AstFragmentKind
::$Kind
, *id
, None
).$
make_ast()
91 _
=> panic
!("unexpected AST fragment kind")
95 pub fn make_opt_expr(self) -> Option
<P
<ast
::Expr
>> {
97 AstFragment
::OptExpr(expr
) => expr
,
98 _
=> panic
!("AstFragment::make_* called on the wrong kind of fragment"),
102 $
(pub fn $
make_ast(self) -> $AstTy
{
104 AstFragment
::$
Kind(ast
) => ast
,
105 _
=> panic
!("AstFragment::make_* called on the wrong kind of fragment"),
109 pub fn mut_visit_with
<F
: MutVisitor
>(&mut self, vis
: &mut F
) {
111 AstFragment
::OptExpr(opt_expr
) => {
112 visit_clobber(opt_expr
, |opt_expr
| {
113 if let Some(expr
) = opt_expr
{
114 vis
.filter_map_expr(expr
)
120 $
($
(AstFragment
::$
Kind(ast
) => vis
.$
mut_visit_ast(ast
),)?
)*
121 $
($
(AstFragment
::$
Kind(ast
) =>
122 ast
.flat_map_in_place(|ast
| vis
.$
flat_map_ast_elt(ast
)),)?
)*
126 pub fn visit_with
<'a
, V
: Visitor
<'a
>>(&'a
self, visitor
: &mut V
) {
128 AstFragment
::OptExpr(Some(ref expr
)) => visitor
.visit_expr(expr
),
129 AstFragment
::OptExpr(None
) => {}
130 $
($
(AstFragment
::$
Kind(ref ast
) => visitor
.$
visit_ast(ast
),)?
)*
131 $
($
(AstFragment
::$
Kind(ref ast
) => for ast_elt
in &ast
[..] {
132 visitor
.$
visit_ast_elt(ast_elt
, $
($args
)*);
138 impl<'a
> MacResult
for crate::mbe
::macro_rules
::ParserAnyMacro
<'a
> {
139 $
(fn $
make_ast(self: Box
<crate::mbe
::macro_rules
::ParserAnyMacro
<'a
>>)
141 Some(self.make(AstFragmentKind
::$Kind
).$
make_ast())
148 Expr(P
<ast
::Expr
>) { "expression"; one fn visit_expr; fn visit_expr; fn make_expr; }
149 Pat(P
<ast
::Pat
>) { "pattern"; one fn visit_pat; fn visit_pat; fn make_pat; }
150 Ty(P
<ast
::Ty
>) { "type"; one fn visit_ty; fn visit_ty; fn make_ty; }
151 Stmts(SmallVec
<[ast
::Stmt
; 1]>) {
152 "statement"; many
fn flat_map_stmt
; fn visit_stmt(); fn make_stmts
;
154 Items(SmallVec
<[P
<ast
::Item
>; 1]>) {
155 "item"; many
fn flat_map_item
; fn visit_item(); fn make_items
;
157 TraitItems(SmallVec
<[P
<ast
::AssocItem
>; 1]>) {
159 many
fn flat_map_trait_item
;
160 fn visit_assoc_item(AssocCtxt
::Trait
);
163 ImplItems(SmallVec
<[P
<ast
::AssocItem
>; 1]>) {
165 many
fn flat_map_impl_item
;
166 fn visit_assoc_item(AssocCtxt
::Impl
);
169 ForeignItems(SmallVec
<[P
<ast
::ForeignItem
>; 1]>) {
171 many
fn flat_map_foreign_item
;
172 fn visit_foreign_item();
173 fn make_foreign_items
;
175 Arms(SmallVec
<[ast
::Arm
; 1]>) {
176 "match arm"; many
fn flat_map_arm
; fn visit_arm(); fn make_arms
;
178 Fields(SmallVec
<[ast
::Field
; 1]>) {
179 "field expression"; many
fn flat_map_field
; fn visit_field(); fn make_fields
;
181 FieldPats(SmallVec
<[ast
::FieldPat
; 1]>) {
183 many
fn flat_map_field_pattern
;
184 fn visit_field_pattern();
185 fn make_field_patterns
;
187 GenericParams(SmallVec
<[ast
::GenericParam
; 1]>) {
189 many
fn flat_map_generic_param
;
190 fn visit_generic_param();
191 fn make_generic_params
;
193 Params(SmallVec
<[ast
::Param
; 1]>) {
194 "function parameter"; many
fn flat_map_param
; fn visit_param(); fn make_params
;
196 StructFields(SmallVec
<[ast
::StructField
; 1]>) {
198 many
fn flat_map_struct_field
;
199 fn visit_struct_field();
200 fn make_struct_fields
;
202 Variants(SmallVec
<[ast
::Variant
; 1]>) {
203 "variant"; many
fn flat_map_variant
; fn visit_variant(); fn make_variants
;
207 impl AstFragmentKind
{
208 crate fn dummy(self, span
: Span
) -> AstFragment
{
209 self.make_from(DummyResult
::any(span
)).expect("couldn't create a dummy AST fragment")
212 /// Fragment supports macro expansion and not just inert attributes, `cfg` and `cfg_attr`.
213 pub fn supports_macro_expansion(self) -> bool
{
215 AstFragmentKind
::OptExpr
216 | AstFragmentKind
::Expr
217 | AstFragmentKind
::Pat
218 | AstFragmentKind
::Ty
219 | AstFragmentKind
::Stmts
220 | AstFragmentKind
::Items
221 | AstFragmentKind
::TraitItems
222 | AstFragmentKind
::ImplItems
223 | AstFragmentKind
::ForeignItems
=> true,
224 AstFragmentKind
::Arms
225 | AstFragmentKind
::Fields
226 | AstFragmentKind
::FieldPats
227 | AstFragmentKind
::GenericParams
228 | AstFragmentKind
::Params
229 | AstFragmentKind
::StructFields
230 | AstFragmentKind
::Variants
=> false,
234 fn expect_from_annotatables
<I
: IntoIterator
<Item
= Annotatable
>>(
238 let mut items
= items
.into_iter();
240 AstFragmentKind
::Arms
=> {
241 AstFragment
::Arms(items
.map(Annotatable
::expect_arm
).collect())
243 AstFragmentKind
::Fields
=> {
244 AstFragment
::Fields(items
.map(Annotatable
::expect_field
).collect())
246 AstFragmentKind
::FieldPats
=> {
247 AstFragment
::FieldPats(items
.map(Annotatable
::expect_field_pattern
).collect())
249 AstFragmentKind
::GenericParams
=> {
250 AstFragment
::GenericParams(items
.map(Annotatable
::expect_generic_param
).collect())
252 AstFragmentKind
::Params
=> {
253 AstFragment
::Params(items
.map(Annotatable
::expect_param
).collect())
255 AstFragmentKind
::StructFields
=> {
256 AstFragment
::StructFields(items
.map(Annotatable
::expect_struct_field
).collect())
258 AstFragmentKind
::Variants
=> {
259 AstFragment
::Variants(items
.map(Annotatable
::expect_variant
).collect())
261 AstFragmentKind
::Items
=> {
262 AstFragment
::Items(items
.map(Annotatable
::expect_item
).collect())
264 AstFragmentKind
::ImplItems
=> {
265 AstFragment
::ImplItems(items
.map(Annotatable
::expect_impl_item
).collect())
267 AstFragmentKind
::TraitItems
=> {
268 AstFragment
::TraitItems(items
.map(Annotatable
::expect_trait_item
).collect())
270 AstFragmentKind
::ForeignItems
=> {
271 AstFragment
::ForeignItems(items
.map(Annotatable
::expect_foreign_item
).collect())
273 AstFragmentKind
::Stmts
=> {
274 AstFragment
::Stmts(items
.map(Annotatable
::expect_stmt
).collect())
276 AstFragmentKind
::Expr
=> AstFragment
::Expr(
277 items
.next().expect("expected exactly one expression").expect_expr(),
279 AstFragmentKind
::OptExpr
=> {
280 AstFragment
::OptExpr(items
.next().map(Annotatable
::expect_expr
))
282 AstFragmentKind
::Pat
| AstFragmentKind
::Ty
=> {
283 panic
!("patterns and types aren't annotatable")
289 pub struct Invocation
{
290 pub kind
: InvocationKind
,
291 pub fragment_kind
: AstFragmentKind
,
292 pub expansion_data
: ExpansionData
,
295 pub enum InvocationKind
{
301 attr
: ast
::Attribute
,
303 // Required for resolving derive helper attributes.
305 // We temporarily report errors for attribute macros placed after derives
312 /// "Invocation" that contains all derives from an item,
313 /// broken into multiple `Derive` invocations when expanded.
314 /// FIXME: Find a way to remove it.
321 impl InvocationKind
{
322 fn placeholder_visibility(&self) -> Option
<ast
::Visibility
> {
323 // HACK: For unnamed fields placeholders should have the same visibility as the actual
324 // fields because for tuple structs/variants resolve determines visibilities of their
325 // constructor using these field visibilities before attributes on them are are expanded.
326 // The assumption is that the attribute expansion cannot change field visibilities,
327 // and it holds because only inert attributes are supported in this position.
329 InvocationKind
::Attr { item: Annotatable::StructField(field), .. }
330 | InvocationKind
::Derive { item: Annotatable::StructField(field), .. }
331 | InvocationKind
::DeriveContainer { item: Annotatable::StructField(field), .. }
332 if field
.ident
.is_none() =>
334 Some(field
.vis
.clone())
342 pub fn span(&self) -> Span
{
344 InvocationKind
::Bang { span, .. }
=> *span
,
345 InvocationKind
::Attr { attr, .. }
=> attr
.span
,
346 InvocationKind
::Derive { path, .. }
=> path
.span
,
347 InvocationKind
::DeriveContainer { item, .. }
=> item
.span(),
352 pub struct MacroExpander
<'a
, 'b
> {
353 pub cx
: &'a
mut ExtCtxt
<'b
>,
354 monotonic
: bool
, // cf. `cx.monotonic_expander()`
357 impl<'a
, 'b
> MacroExpander
<'a
, 'b
> {
358 pub fn new(cx
: &'a
mut ExtCtxt
<'b
>, monotonic
: bool
) -> Self {
359 MacroExpander { cx, monotonic }
362 pub fn expand_crate(&mut self, mut krate
: ast
::Crate
) -> ast
::Crate
{
363 let mut module
= ModuleData
{
364 mod_path
: vec
![Ident
::from_str(&self.cx
.ecfg
.crate_name
)],
365 directory
: match self.cx
.source_map().span_to_unmapped_path(krate
.span
) {
366 FileName
::Real(name
) => name
.into_local_path(),
367 other
=> PathBuf
::from(other
.to_string()),
370 module
.directory
.pop();
371 self.cx
.root_path
= module
.directory
.clone();
372 self.cx
.current_expansion
.module
= Rc
::new(module
);
374 let orig_mod_span
= krate
.module
.inner
;
376 let krate_item
= AstFragment
::Items(smallvec
![P(ast
::Item
{
379 kind
: ast
::ItemKind
::Mod(krate
.module
),
380 ident
: Ident
::invalid(),
381 id
: ast
::DUMMY_NODE_ID
,
382 vis
: ast
::Visibility
{
383 span
: krate
.span
.shrink_to_lo(),
384 kind
: ast
::VisibilityKind
::Public
,
390 match self.fully_expand_fragment(krate_item
).make_items().pop().map(P
::into_inner
) {
391 Some(ast
::Item { attrs, kind: ast::ItemKind::Mod(module), .. }
) => {
393 krate
.module
= module
;
396 // Resolution failed so we return an empty expansion
397 krate
.attrs
= vec
![];
398 krate
.module
= ast
::Mod
{
399 inner
: orig_mod_span
,
400 unsafety
: Unsafe
::No
,
405 Some(ast
::Item { span, kind, .. }
) => {
406 krate
.attrs
= vec
![];
407 krate
.module
= ast
::Mod
{
408 inner
: orig_mod_span
,
409 unsafety
: Unsafe
::No
,
416 "expected crate top-level item to be a module after macro expansion, found {} {}",
417 kind
.article(), kind
.descr()
422 self.cx
.trace_macros_diag();
426 // Recursively expand all macro invocations in this AST fragment.
427 pub fn fully_expand_fragment(&mut self, input_fragment
: AstFragment
) -> AstFragment
{
428 let orig_expansion_data
= self.cx
.current_expansion
.clone();
429 let orig_force_mode
= self.cx
.force_mode
;
430 self.cx
.current_expansion
.depth
= 0;
432 // Collect all macro invocations and replace them with placeholders.
433 let (mut fragment_with_placeholders
, mut invocations
) =
434 self.collect_invocations(input_fragment
, &[]);
436 // Optimization: if we resolve all imports now,
437 // we'll be able to immediately resolve most of imported macros.
438 self.resolve_imports();
440 // Resolve paths in all invocations and produce output expanded fragments for them, but
441 // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
442 // The output fragments also go through expansion recursively until no invocations are left.
443 // Unresolved macros produce dummy outputs as a recovery measure.
444 invocations
.reverse();
445 let mut expanded_fragments
= Vec
::new();
446 let mut undetermined_invocations
= Vec
::new();
447 let (mut progress
, mut force
) = (false, !self.monotonic
);
449 let (invoc
, res
) = if let Some(invoc
) = invocations
.pop() {
452 self.resolve_imports();
453 if undetermined_invocations
.is_empty() {
456 invocations
= mem
::take(&mut undetermined_invocations
);
457 force
= !mem
::replace(&mut progress
, false);
458 if force
&& self.monotonic
{
459 self.cx
.sess
.delay_span_bug(
460 invocations
.last().unwrap().0.span(),
461 "expansion entered force mode without producing any errors",
467 let res
= match res
{
470 let eager_expansion_root
= if self.monotonic
{
471 invoc
.expansion_data
.id
473 orig_expansion_data
.id
475 match self.cx
.resolver
.resolve_macro_invocation(
477 eager_expansion_root
,
481 Err(Indeterminate
) => {
482 // Cannot resolve, will retry this invocation later.
483 undetermined_invocations
.push((invoc
, None
));
490 let ExpansionData { depth, id: expn_id, .. }
= invoc
.expansion_data
;
491 self.cx
.current_expansion
= invoc
.expansion_data
.clone();
492 self.cx
.force_mode
= force
;
494 // FIXME(jseyfried): Refactor out the following logic
495 let fragment_kind
= invoc
.fragment_kind
;
496 let (expanded_fragment
, new_invocations
) = match res
{
497 InvocationRes
::Single(ext
) => match self.expand_invoc(invoc
, &ext
.kind
) {
498 ExpandResult
::Ready(fragment
) => self.collect_invocations(fragment
, &[]),
499 ExpandResult
::Retry(invoc
) => {
503 "expansion entered force mode but is still stuck",
506 // Cannot expand, will retry this invocation later.
507 undetermined_invocations
508 .push((invoc
, Some(InvocationRes
::Single(ext
))));
513 InvocationRes
::DeriveContainer(_exts
) => {
514 // FIXME: Consider using the derive resolutions (`_exts`) immediately,
515 // instead of enqueuing the derives to be resolved again later.
516 let (derives
, mut item
) = match invoc
.kind
{
517 InvocationKind
::DeriveContainer { derives, item }
=> (derives
, item
),
520 let (item
, derive_placeholders
) = if !item
.derive_allowed() {
521 self.error_derive_forbidden_on_non_adt(&derives
, &item
);
522 item
.visit_attrs(|attrs
| attrs
.retain(|a
| !a
.has_name(sym
::derive
)));
525 let mut visitor
= StripUnconfigured
{
527 features
: self.cx
.ecfg
.features
,
530 let mut item
= visitor
.fully_configure(item
);
531 item
.visit_attrs(|attrs
| attrs
.retain(|a
| !a
.has_name(sym
::derive
)));
532 if visitor
.modified
&& !derives
.is_empty() {
533 // Erase the tokens if cfg-stripping modified the item
534 // This will cause us to synthesize fake tokens
535 // when `nt_to_tokenstream` is called on this item.
537 Annotatable
::Item(item
) => item
.tokens
= None
,
538 Annotatable
::Stmt(stmt
) => {
539 if let StmtKind
::Item(item
) = &mut stmt
.kind
{
542 panic
!("Unexpected stmt {:?}", stmt
);
545 _
=> panic
!("Unexpected annotatable {:?}", item
),
549 invocations
.reserve(derives
.len());
550 let derive_placeholders
= derives
553 let expn_id
= ExpnId
::fresh(None
);
556 kind
: InvocationKind
::Derive { path, item: item.clone() }
,
558 expansion_data
: ExpansionData
{
560 ..self.cx
.current_expansion
.clone()
565 NodeId
::placeholder_from_expn_id(expn_id
)
567 .collect
::<Vec
<_
>>();
568 (item
, derive_placeholders
)
571 let fragment
= fragment_kind
.expect_from_annotatables(::std
::iter
::once(item
));
572 self.collect_invocations(fragment
, &derive_placeholders
)
577 if expanded_fragments
.len() < depth
{
578 expanded_fragments
.push(Vec
::new());
580 expanded_fragments
[depth
- 1].push((expn_id
, expanded_fragment
));
581 invocations
.extend(new_invocations
.into_iter().rev());
584 self.cx
.current_expansion
= orig_expansion_data
;
585 self.cx
.force_mode
= orig_force_mode
;
587 // Finally incorporate all the expanded macros into the input AST fragment.
588 let mut placeholder_expander
= PlaceholderExpander
::new(self.cx
, self.monotonic
);
589 while let Some(expanded_fragments
) = expanded_fragments
.pop() {
590 for (expn_id
, expanded_fragment
) in expanded_fragments
.into_iter().rev() {
592 .add(NodeId
::placeholder_from_expn_id(expn_id
), expanded_fragment
);
595 fragment_with_placeholders
.mut_visit_with(&mut placeholder_expander
);
596 fragment_with_placeholders
599 fn error_derive_forbidden_on_non_adt(&self, derives
: &[Path
], item
: &Annotatable
) {
600 let attr
= self.cx
.sess
.find_by_name(item
.attrs(), sym
::derive
);
601 let span
= attr
.map_or(item
.span(), |attr
| attr
.span
);
602 let mut err
= struct_span_err
!(
606 "`derive` may only be applied to structs, enums and unions",
608 if let Some(ast
::Attribute { style: ast::AttrStyle::Inner, .. }
) = attr
{
609 let trait_list
= derives
.iter().map(|t
| pprust
::path_to_string(t
)).collect
::<Vec
<_
>>();
610 let suggestion
= format
!("#[derive({})]", trait_list
.join(", "));
613 "try an outer attribute",
615 // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
616 Applicability
::MaybeIncorrect
,
622 fn resolve_imports(&mut self) {
624 self.cx
.resolver
.resolve_imports();
628 /// Collects all macro invocations reachable at this time in this AST fragment, and replace
629 /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
630 /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
631 /// prepares data for resolving paths of macro invocations.
632 fn collect_invocations(
634 mut fragment
: AstFragment
,
635 extra_placeholders
: &[NodeId
],
636 ) -> (AstFragment
, Vec
<(Invocation
, Option
<InvocationRes
>)>) {
637 // Resolve `$crate`s in the fragment for pretty-printing.
638 self.cx
.resolver
.resolve_dollar_crates();
641 let mut collector
= InvocationCollector
{
642 cfg
: StripUnconfigured
{
644 features
: self.cx
.ecfg
.features
,
648 invocations
: Vec
::new(),
649 monotonic
: self.monotonic
,
651 fragment
.mut_visit_with(&mut collector
);
652 fragment
.add_placeholders(extra_placeholders
);
653 collector
.invocations
659 .visit_ast_fragment_with_placeholders(self.cx
.current_expansion
.id
, &fragment
);
662 (fragment
, invocations
)
665 fn error_recursion_limit_reached(&mut self) {
666 let expn_data
= self.cx
.current_expansion
.id
.expn_data();
667 let suggested_limit
= self.cx
.ecfg
.recursion_limit
* 2;
671 &format
!("recursion limit reached while expanding `{}`", expn_data
.kind
.descr()),
674 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
675 suggested_limit
, self.cx
.ecfg
.crate_name
,
678 self.cx
.trace_macros_diag();
681 /// A macro's expansion does not fit in this fragment kind.
682 /// For example, a non-type macro in a type position.
683 fn error_wrong_fragment_kind(&mut self, kind
: AstFragmentKind
, mac
: &ast
::MacCall
, span
: Span
) {
685 "non-{kind} macro in {kind} position: {path}",
687 path
= pprust
::path_to_string(&mac
.path
),
689 self.cx
.span_err(span
, &msg
);
690 self.cx
.trace_macros_diag();
696 ext
: &SyntaxExtensionKind
,
697 ) -> ExpandResult
<AstFragment
, Invocation
> {
698 let recursion_limit
=
699 self.cx
.reduced_recursion_limit
.unwrap_or(self.cx
.ecfg
.recursion_limit
);
700 if !recursion_limit
.value_within_limit(self.cx
.current_expansion
.depth
) {
701 if self.cx
.reduced_recursion_limit
.is_none() {
702 self.error_recursion_limit_reached();
705 // Reduce the recursion limit by half each time it triggers.
706 self.cx
.reduced_recursion_limit
= Some(recursion_limit
/ 2);
708 return ExpandResult
::Ready(invoc
.fragment_kind
.dummy(invoc
.span()));
711 let (fragment_kind
, span
) = (invoc
.fragment_kind
, invoc
.span());
712 ExpandResult
::Ready(match invoc
.kind
{
713 InvocationKind
::Bang { mac, .. }
=> match ext
{
714 SyntaxExtensionKind
::Bang(expander
) => {
715 let tok_result
= match expander
.expand(self.cx
, span
, mac
.args
.inner_tokens()) {
716 Err(_
) => return ExpandResult
::Ready(fragment_kind
.dummy(span
)),
719 self.parse_ast_fragment(tok_result
, fragment_kind
, &mac
.path
, span
)
721 SyntaxExtensionKind
::LegacyBang(expander
) => {
722 let prev
= self.cx
.current_expansion
.prior_type_ascription
;
723 self.cx
.current_expansion
.prior_type_ascription
= mac
.prior_type_ascription
;
724 let tok_result
= expander
.expand(self.cx
, span
, mac
.args
.inner_tokens());
725 let result
= if let Some(result
) = fragment_kind
.make_from(tok_result
) {
728 self.error_wrong_fragment_kind(fragment_kind
, &mac
, span
);
729 fragment_kind
.dummy(span
)
731 self.cx
.current_expansion
.prior_type_ascription
= prev
;
736 InvocationKind
::Attr { attr, mut item, derives, after_derive }
=> match ext
{
737 SyntaxExtensionKind
::Attr(expander
) => {
738 self.gate_proc_macro_input(&item
);
739 self.gate_proc_macro_attr_item(span
, &item
);
740 let tokens
= match attr
.style
{
741 AttrStyle
::Outer
=> item
.into_tokens(&self.cx
.sess
.parse_sess
),
742 // FIXME: Properly collect tokens for inner attributes
743 AttrStyle
::Inner
=> rustc_parse
::fake_token_stream(
744 &self.cx
.sess
.parse_sess
,
745 &item
.into_nonterminal(),
748 let attr_item
= attr
.unwrap_normal_item();
749 if let MacArgs
::Eq(..) = attr_item
.args
{
750 self.cx
.span_err(span
, "key-value macro attributes are not supported");
752 let inner_tokens
= attr_item
.args
.inner_tokens();
753 let tok_result
= match expander
.expand(self.cx
, span
, inner_tokens
, tokens
) {
754 Err(_
) => return ExpandResult
::Ready(fragment_kind
.dummy(span
)),
757 self.parse_ast_fragment(tok_result
, fragment_kind
, &attr_item
.path
, span
)
759 SyntaxExtensionKind
::LegacyAttr(expander
) => {
760 match validate_attr
::parse_meta(&self.cx
.sess
.parse_sess
, &attr
) {
762 let items
= match expander
.expand(self.cx
, span
, &meta
, item
) {
763 ExpandResult
::Ready(items
) => items
,
764 ExpandResult
::Retry(item
) => {
765 // Reassemble the original invocation for retrying.
766 return ExpandResult
::Retry(Invocation
{
767 kind
: InvocationKind
::Attr
{
777 fragment_kind
.expect_from_annotatables(items
)
781 fragment_kind
.dummy(span
)
785 SyntaxExtensionKind
::NonMacroAttr { mark_used }
=> {
786 self.cx
.sess
.mark_attr_known(&attr
);
788 self.cx
.sess
.mark_attr_used(&attr
);
790 item
.visit_attrs(|attrs
| attrs
.push(attr
));
791 fragment_kind
.expect_from_annotatables(iter
::once(item
))
795 InvocationKind
::Derive { path, item }
=> match ext
{
796 SyntaxExtensionKind
::Derive(expander
)
797 | SyntaxExtensionKind
::LegacyDerive(expander
) => {
798 if let SyntaxExtensionKind
::Derive(..) = ext
{
799 self.gate_proc_macro_input(&item
);
801 let meta
= ast
::MetaItem { kind: ast::MetaItemKind::Word, span, path }
;
802 let items
= match expander
.expand(self.cx
, span
, &meta
, item
) {
803 ExpandResult
::Ready(items
) => items
,
804 ExpandResult
::Retry(item
) => {
805 // Reassemble the original invocation for retrying.
806 return ExpandResult
::Retry(Invocation
{
807 kind
: InvocationKind
::Derive { path: meta.path, item }
,
812 fragment_kind
.expect_from_annotatables(items
)
816 InvocationKind
::DeriveContainer { .. }
=> unreachable
!(),
820 fn gate_proc_macro_attr_item(&self, span
: Span
, item
: &Annotatable
) {
821 let kind
= match item
{
823 | Annotatable
::TraitItem(_
)
824 | Annotatable
::ImplItem(_
)
825 | Annotatable
::ForeignItem(_
) => return,
826 Annotatable
::Stmt(stmt
) => {
827 // Attributes are stable on item statements,
828 // but unstable on all other kinds of statements
834 Annotatable
::Expr(_
) => "expressions",
836 | Annotatable
::Field(..)
837 | Annotatable
::FieldPat(..)
838 | Annotatable
::GenericParam(..)
839 | Annotatable
::Param(..)
840 | Annotatable
::StructField(..)
841 | Annotatable
::Variant(..) => panic
!("unexpected annotatable"),
843 if self.cx
.ecfg
.proc_macro_hygiene() {
847 &self.cx
.sess
.parse_sess
,
848 sym
::proc_macro_hygiene
,
850 &format
!("custom attributes cannot be applied to {}", kind
),
855 fn gate_proc_macro_input(&self, annotatable
: &Annotatable
) {
856 struct GateProcMacroInput
<'a
> {
857 parse_sess
: &'a ParseSess
,
860 impl<'ast
, 'a
> Visitor
<'ast
> for GateProcMacroInput
<'a
> {
861 fn visit_item(&mut self, item
: &'ast ast
::Item
) {
863 ast
::ItemKind
::Mod(module
) if !module
.inline
=> {
866 sym
::proc_macro_hygiene
,
868 "non-inline modules in proc macro input are unstable",
875 visit
::walk_item(self, item
);
879 if !self.cx
.ecfg
.proc_macro_hygiene() {
881 .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess }
);
885 fn parse_ast_fragment(
888 kind
: AstFragmentKind
,
892 let mut parser
= self.cx
.new_parser_from_tts(toks
);
893 match parse_ast_fragment(&mut parser
, kind
) {
895 ensure_complete_parse(&mut parser
, path
, kind
.name(), span
);
899 if err
.span
.is_dummy() {
902 annotate_err_with_kind(&mut err
, kind
, span
);
904 self.cx
.trace_macros_diag();
911 pub fn parse_ast_fragment
<'a
>(
912 this
: &mut Parser
<'a
>,
913 kind
: AstFragmentKind
,
914 ) -> PResult
<'a
, AstFragment
> {
916 AstFragmentKind
::Items
=> {
917 let mut items
= SmallVec
::new();
918 while let Some(item
) = this
.parse_item(ForceCollect
::No
)?
{
921 AstFragment
::Items(items
)
923 AstFragmentKind
::TraitItems
=> {
924 let mut items
= SmallVec
::new();
925 while let Some(item
) = this
.parse_trait_item()?
{
928 AstFragment
::TraitItems(items
)
930 AstFragmentKind
::ImplItems
=> {
931 let mut items
= SmallVec
::new();
932 while let Some(item
) = this
.parse_impl_item()?
{
935 AstFragment
::ImplItems(items
)
937 AstFragmentKind
::ForeignItems
=> {
938 let mut items
= SmallVec
::new();
939 while let Some(item
) = this
.parse_foreign_item()?
{
942 AstFragment
::ForeignItems(items
)
944 AstFragmentKind
::Stmts
=> {
945 let mut stmts
= SmallVec
::new();
946 // Won't make progress on a `}`.
947 while this
.token
!= token
::Eof
&& this
.token
!= token
::CloseDelim(token
::Brace
) {
948 if let Some(stmt
) = this
.parse_full_stmt(AttemptLocalParseRecovery
::Yes
)?
{
952 AstFragment
::Stmts(stmts
)
954 AstFragmentKind
::Expr
=> AstFragment
::Expr(this
.parse_expr()?
),
955 AstFragmentKind
::OptExpr
=> {
956 if this
.token
!= token
::Eof
{
957 AstFragment
::OptExpr(Some(this
.parse_expr()?
))
959 AstFragment
::OptExpr(None
)
962 AstFragmentKind
::Ty
=> AstFragment
::Ty(this
.parse_ty()?
),
963 AstFragmentKind
::Pat
=> AstFragment
::Pat(this
.parse_pat(None
)?
),
964 AstFragmentKind
::Arms
965 | AstFragmentKind
::Fields
966 | AstFragmentKind
::FieldPats
967 | AstFragmentKind
::GenericParams
968 | AstFragmentKind
::Params
969 | AstFragmentKind
::StructFields
970 | AstFragmentKind
::Variants
=> panic
!("unexpected AST fragment kind"),
974 pub fn ensure_complete_parse
<'a
>(
975 this
: &mut Parser
<'a
>,
980 if this
.token
!= token
::Eof
{
981 let token
= pprust
::token_to_string(&this
.token
);
982 let msg
= format
!("macro expansion ignores token `{}` and any following", token
);
983 // Avoid emitting backtrace info twice.
984 let def_site_span
= this
.token
.span
.with_ctxt(SyntaxContext
::root());
985 let mut err
= this
.struct_span_err(def_site_span
, &msg
);
986 err
.span_label(span
, "caused by the macro expansion here");
988 "the usage of `{}!` is likely invalid in {} context",
989 pprust
::path_to_string(macro_path
),
993 let semi_span
= this
.sess
.source_map().next_point(span
);
995 let semi_full_span
= semi_span
.to(this
.sess
.source_map().next_point(semi_span
));
996 match this
.sess
.source_map().span_to_snippet(semi_full_span
) {
997 Ok(ref snippet
) if &snippet
[..] != ";" && kind_name
== "expression" => {
1000 "you might be missing a semicolon here",
1002 Applicability
::MaybeIncorrect
,
1011 struct InvocationCollector
<'a
, 'b
> {
1012 cx
: &'a
mut ExtCtxt
<'b
>,
1013 cfg
: StripUnconfigured
<'a
>,
1014 invocations
: Vec
<(Invocation
, Option
<InvocationRes
>)>,
1018 impl<'a
, 'b
> InvocationCollector
<'a
, 'b
> {
1019 fn collect(&mut self, fragment_kind
: AstFragmentKind
, kind
: InvocationKind
) -> AstFragment
{
1020 // Expansion data for all the collected invocations is set upon their resolution,
1021 // with exception of the derive container case which is not resolved and can get
1022 // its expansion data immediately.
1023 let expn_data
= match &kind
{
1024 InvocationKind
::DeriveContainer { item, .. }
=> {
1025 let mut expn_data
= ExpnData
::default(
1026 ExpnKind
::Macro(MacroKind
::Attr
, sym
::derive
),
1028 self.cx
.sess
.parse_sess
.edition
,
1031 expn_data
.parent
= self.cx
.current_expansion
.id
;
1036 let expn_id
= ExpnId
::fresh(expn_data
);
1037 let vis
= kind
.placeholder_visibility();
1038 self.invocations
.push((
1042 expansion_data
: ExpansionData
{
1044 depth
: self.cx
.current_expansion
.depth
+ 1,
1045 ..self.cx
.current_expansion
.clone()
1050 placeholder(fragment_kind
, NodeId
::placeholder_from_expn_id(expn_id
), vis
)
1057 kind
: AstFragmentKind
,
1059 self.collect(kind
, InvocationKind
::Bang { mac, span }
)
1064 (attr
, derives
, after_derive
): (Option
<ast
::Attribute
>, Vec
<Path
>, bool
),
1066 kind
: AstFragmentKind
,
1071 Some(attr
) => InvocationKind
::Attr { attr, item, derives, after_derive }
,
1072 None
=> InvocationKind
::DeriveContainer { derives, item }
,
1079 attrs
: &mut Vec
<ast
::Attribute
>,
1080 after_derive
: &mut bool
,
1081 ) -> Option
<ast
::Attribute
> {
1085 if a
.has_name(sym
::derive
) {
1086 *after_derive
= true;
1088 !self.cx
.sess
.is_attr_known(a
) && !is_builtin_attr(a
)
1090 .map(|i
| attrs
.remove(i
))
1093 /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
1096 item
: &mut impl HasAttrs
,
1097 ) -> Option
<(Option
<ast
::Attribute
>, Vec
<Path
>, /* after_derive */ bool
)> {
1098 let (mut attr
, mut traits
, mut after_derive
) = (None
, Vec
::new(), false);
1100 item
.visit_attrs(|mut attrs
| {
1101 attr
= self.find_attr_invoc(&mut attrs
, &mut after_derive
);
1102 traits
= collect_derives(&mut self.cx
, &mut attrs
);
1105 if attr
.is_some() || !traits
.is_empty() { Some((attr, traits, after_derive)) }
else { None }
1108 /// Alternative to `take_first_attr()` that ignores `#[derive]` so invocations fallthrough
1109 /// to the unused-attributes lint (making it an error on statements and expressions
1110 /// is a breaking change)
1111 fn take_first_attr_no_derive(
1113 nonitem
: &mut impl HasAttrs
,
1114 ) -> Option
<(Option
<ast
::Attribute
>, Vec
<Path
>, /* after_derive */ bool
)> {
1115 let (mut attr
, mut after_derive
) = (None
, false);
1117 nonitem
.visit_attrs(|mut attrs
| {
1118 attr
= self.find_attr_invoc(&mut attrs
, &mut after_derive
);
1121 attr
.map(|attr
| (Some(attr
), Vec
::new(), after_derive
))
1124 fn configure
<T
: HasAttrs
>(&mut self, node
: T
) -> Option
<T
> {
1125 self.cfg
.configure(node
)
1128 // Detect use of feature-gated or invalid attributes on macro invocations
1129 // since they will not be detected after macro expansion.
1130 fn check_attributes(&mut self, attrs
: &[ast
::Attribute
]) {
1131 let features
= self.cx
.ecfg
.features
.unwrap();
1132 for attr
in attrs
.iter() {
1133 rustc_ast_passes
::feature_gate
::check_attribute(attr
, self.cx
.sess
, features
);
1134 validate_attr
::check_meta(&self.cx
.sess
.parse_sess
, attr
);
1136 // macros are expanded before any lint passes so this warning has to be hardcoded
1137 if attr
.has_name(sym
::derive
) {
1141 .struct_span_warn(attr
.span
, "`#[derive]` does nothing on macro invocations")
1142 .note("this may become a hard error in a future release")
1146 if attr
.doc_str().is_some() {
1147 self.cx
.sess
.parse_sess
.buffer_lint_with_diagnostic(
1148 &UNUSED_DOC_COMMENTS
,
1151 "unused doc comment",
1152 BuiltinLintDiagnostics
::UnusedDocComment(attr
.span
),
1159 impl<'a
, 'b
> MutVisitor
for InvocationCollector
<'a
, 'b
> {
1160 fn visit_expr(&mut self, expr
: &mut P
<ast
::Expr
>) {
1161 self.cfg
.configure_expr(expr
);
1162 visit_clobber(expr
.deref_mut(), |mut expr
| {
1163 self.cfg
.configure_expr_kind(&mut expr
.kind
);
1165 if let Some(attr
) = self.take_first_attr_no_derive(&mut expr
) {
1166 // Collect the invoc regardless of whether or not attributes are permitted here
1167 // expansion will eat the attribute so it won't error later.
1168 if let Some(attr
) = attr
.0.as_ref() {
1169 self.cfg
.maybe_emit_expr_attr_err(attr
)
1172 // AstFragmentKind::Expr requires the macro to emit an expression.
1174 .collect_attr(attr
, Annotatable
::Expr(P(expr
)), AstFragmentKind
::Expr
)
1179 if let ast
::ExprKind
::MacCall(mac
) = expr
.kind
{
1180 self.check_attributes(&expr
.attrs
);
1181 self.collect_bang(mac
, expr
.span
, AstFragmentKind
::Expr
).make_expr().into_inner()
1183 ensure_sufficient_stack(|| noop_visit_expr(&mut expr
, self));
1189 fn flat_map_arm(&mut self, arm
: ast
::Arm
) -> SmallVec
<[ast
::Arm
; 1]> {
1190 let mut arm
= configure
!(self, arm
);
1192 if let Some(attr
) = self.take_first_attr(&mut arm
) {
1194 .collect_attr(attr
, Annotatable
::Arm(arm
), AstFragmentKind
::Arms
)
1198 noop_flat_map_arm(arm
, self)
1201 fn flat_map_field(&mut self, field
: ast
::Field
) -> SmallVec
<[ast
::Field
; 1]> {
1202 let mut field
= configure
!(self, field
);
1204 if let Some(attr
) = self.take_first_attr(&mut field
) {
1206 .collect_attr(attr
, Annotatable
::Field(field
), AstFragmentKind
::Fields
)
1210 noop_flat_map_field(field
, self)
1213 fn flat_map_field_pattern(&mut self, fp
: ast
::FieldPat
) -> SmallVec
<[ast
::FieldPat
; 1]> {
1214 let mut fp
= configure
!(self, fp
);
1216 if let Some(attr
) = self.take_first_attr(&mut fp
) {
1218 .collect_attr(attr
, Annotatable
::FieldPat(fp
), AstFragmentKind
::FieldPats
)
1219 .make_field_patterns();
1222 noop_flat_map_field_pattern(fp
, self)
1225 fn flat_map_param(&mut self, p
: ast
::Param
) -> SmallVec
<[ast
::Param
; 1]> {
1226 let mut p
= configure
!(self, p
);
1228 if let Some(attr
) = self.take_first_attr(&mut p
) {
1230 .collect_attr(attr
, Annotatable
::Param(p
), AstFragmentKind
::Params
)
1234 noop_flat_map_param(p
, self)
1237 fn flat_map_struct_field(&mut self, sf
: ast
::StructField
) -> SmallVec
<[ast
::StructField
; 1]> {
1238 let mut sf
= configure
!(self, sf
);
1240 if let Some(attr
) = self.take_first_attr(&mut sf
) {
1242 .collect_attr(attr
, Annotatable
::StructField(sf
), AstFragmentKind
::StructFields
)
1243 .make_struct_fields();
1246 noop_flat_map_struct_field(sf
, self)
1249 fn flat_map_variant(&mut self, variant
: ast
::Variant
) -> SmallVec
<[ast
::Variant
; 1]> {
1250 let mut variant
= configure
!(self, variant
);
1252 if let Some(attr
) = self.take_first_attr(&mut variant
) {
1254 .collect_attr(attr
, Annotatable
::Variant(variant
), AstFragmentKind
::Variants
)
1258 noop_flat_map_variant(variant
, self)
1261 fn filter_map_expr(&mut self, expr
: P
<ast
::Expr
>) -> Option
<P
<ast
::Expr
>> {
1262 let expr
= configure
!(self, expr
);
1263 expr
.filter_map(|mut expr
| {
1264 self.cfg
.configure_expr_kind(&mut expr
.kind
);
1266 if let Some(attr
) = self.take_first_attr_no_derive(&mut expr
) {
1267 if let Some(attr
) = attr
.0.as_ref() {
1268 self.cfg
.maybe_emit_expr_attr_err(attr
)
1272 .collect_attr(attr
, Annotatable
::Expr(P(expr
)), AstFragmentKind
::OptExpr
)
1274 .map(|expr
| expr
.into_inner());
1277 if let ast
::ExprKind
::MacCall(mac
) = expr
.kind
{
1278 self.check_attributes(&expr
.attrs
);
1279 self.collect_bang(mac
, expr
.span
, AstFragmentKind
::OptExpr
)
1281 .map(|expr
| expr
.into_inner())
1284 noop_visit_expr(&mut expr
, self);
1291 fn visit_pat(&mut self, pat
: &mut P
<ast
::Pat
>) {
1292 self.cfg
.configure_pat(pat
);
1294 PatKind
::MacCall(_
) => {}
1295 _
=> return noop_visit_pat(pat
, self),
1298 visit_clobber(pat
, |mut pat
| match mem
::replace(&mut pat
.kind
, PatKind
::Wild
) {
1299 PatKind
::MacCall(mac
) => {
1300 self.collect_bang(mac
, pat
.span
, AstFragmentKind
::Pat
).make_pat()
1302 _
=> unreachable
!(),
1306 fn flat_map_stmt(&mut self, stmt
: ast
::Stmt
) -> SmallVec
<[ast
::Stmt
; 1]> {
1307 let mut stmt
= configure
!(self, stmt
);
1309 // we'll expand attributes on expressions separately
1310 if !stmt
.is_expr() {
1311 let attr
= if stmt
.is_item() {
1312 self.take_first_attr(&mut stmt
)
1314 // Ignore derives on non-item statements for backwards compatibility.
1315 // This will result in a unused attribute warning
1316 self.take_first_attr_no_derive(&mut stmt
)
1319 if let Some(attr
) = attr
{
1321 .collect_attr(attr
, Annotatable
::Stmt(P(stmt
)), AstFragmentKind
::Stmts
)
1326 if let StmtKind
::MacCall(mac
) = stmt
.kind
{
1327 let MacCallStmt { mac, style, attrs, tokens: _ }
= mac
.into_inner();
1328 self.check_attributes(&attrs
);
1329 let mut placeholder
=
1330 self.collect_bang(mac
, stmt
.span
, AstFragmentKind
::Stmts
).make_stmts();
1332 // If this is a macro invocation with a semicolon, then apply that
1333 // semicolon to the final statement produced by expansion.
1334 if style
== MacStmtStyle
::Semicolon
{
1335 if let Some(stmt
) = placeholder
.pop() {
1336 placeholder
.push(stmt
.add_trailing_semicolon());
1343 // The placeholder expander gives ids to statements, so we avoid folding the id here.
1344 let ast
::Stmt { id, kind, span }
= stmt
;
1345 noop_flat_map_stmt_kind(kind
, self)
1347 .map(|kind
| ast
::Stmt { id, kind, span }
)
1351 fn visit_block(&mut self, block
: &mut P
<Block
>) {
1352 let old_directory_ownership
= self.cx
.current_expansion
.directory_ownership
;
1353 self.cx
.current_expansion
.directory_ownership
= DirectoryOwnership
::UnownedViaBlock
;
1354 noop_visit_block(block
, self);
1355 self.cx
.current_expansion
.directory_ownership
= old_directory_ownership
;
1358 fn flat_map_item(&mut self, item
: P
<ast
::Item
>) -> SmallVec
<[P
<ast
::Item
>; 1]> {
1359 let mut item
= configure
!(self, item
);
1361 if let Some(attr
) = self.take_first_attr(&mut item
) {
1363 .collect_attr(attr
, Annotatable
::Item(item
), AstFragmentKind
::Items
)
1367 let mut attrs
= mem
::take(&mut item
.attrs
); // We do this to please borrowck.
1368 let ident
= item
.ident
;
1369 let span
= item
.span
;
1372 ast
::ItemKind
::MacCall(..) => {
1374 self.check_attributes(&item
.attrs
);
1375 item
.and_then(|item
| match item
.kind
{
1376 ItemKind
::MacCall(mac
) => {
1377 self.collect_bang(mac
, span
, AstFragmentKind
::Items
).make_items()
1379 _
=> unreachable
!(),
1382 ast
::ItemKind
::Mod(ref mut old_mod @ ast
::Mod { .. }
) if ident
!= Ident
::invalid() => {
1383 let sess
= &self.cx
.sess
.parse_sess
;
1384 let orig_ownership
= self.cx
.current_expansion
.directory_ownership
;
1385 let mut module
= (*self.cx
.current_expansion
.module
).clone();
1387 let pushed
= &mut false; // Record `parse_external_mod` pushing so we can pop.
1388 let dir
= Directory { ownership: orig_ownership, path: module.directory }
;
1389 let Directory { ownership, path }
= if old_mod
.inline
{
1390 // Inline `mod foo { ... }`, but we still need to push directories.
1392 push_directory(&self.cx
.sess
, ident
, &item
.attrs
, dir
)
1394 // We have an outline `mod foo;` so we need to parse the file.
1395 let (new_mod
, dir
) = parse_external_mod(
1405 let krate
= ast
::Crate
{
1406 span
: new_mod
.inner
,
1409 proc_macros
: vec
![],
1411 if let Some(extern_mod_loaded
) = self.cx
.extern_mod_loaded
{
1412 extern_mod_loaded(&krate
, ident
);
1415 *old_mod
= krate
.module
;
1416 item
.attrs
= krate
.attrs
;
1417 // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1418 item
= match self.configure(item
) {
1422 sess
.included_mod_stack
.borrow_mut().pop();
1424 return Default
::default();
1430 // Set the module info before we flat map.
1431 self.cx
.current_expansion
.directory_ownership
= ownership
;
1432 module
.directory
= path
;
1433 module
.mod_path
.push(ident
);
1435 mem
::replace(&mut self.cx
.current_expansion
.module
, Rc
::new(module
));
1437 let result
= noop_flat_map_item(item
, self);
1439 // Restore the module info.
1440 self.cx
.current_expansion
.module
= orig_module
;
1441 self.cx
.current_expansion
.directory_ownership
= orig_ownership
;
1443 sess
.included_mod_stack
.borrow_mut().pop();
1449 noop_flat_map_item(item
, self)
1454 fn flat_map_trait_item(&mut self, item
: P
<ast
::AssocItem
>) -> SmallVec
<[P
<ast
::AssocItem
>; 1]> {
1455 let mut item
= configure
!(self, item
);
1457 if let Some(attr
) = self.take_first_attr(&mut item
) {
1459 .collect_attr(attr
, Annotatable
::TraitItem(item
), AstFragmentKind
::TraitItems
)
1460 .make_trait_items();
1464 ast
::AssocItemKind
::MacCall(..) => {
1465 self.check_attributes(&item
.attrs
);
1466 item
.and_then(|item
| match item
.kind
{
1467 ast
::AssocItemKind
::MacCall(mac
) => self
1468 .collect_bang(mac
, item
.span
, AstFragmentKind
::TraitItems
)
1469 .make_trait_items(),
1470 _
=> unreachable
!(),
1473 _
=> noop_flat_map_assoc_item(item
, self),
1477 fn flat_map_impl_item(&mut self, item
: P
<ast
::AssocItem
>) -> SmallVec
<[P
<ast
::AssocItem
>; 1]> {
1478 let mut item
= configure
!(self, item
);
1480 if let Some(attr
) = self.take_first_attr(&mut item
) {
1482 .collect_attr(attr
, Annotatable
::ImplItem(item
), AstFragmentKind
::ImplItems
)
1487 ast
::AssocItemKind
::MacCall(..) => {
1488 self.check_attributes(&item
.attrs
);
1489 item
.and_then(|item
| match item
.kind
{
1490 ast
::AssocItemKind
::MacCall(mac
) => self
1491 .collect_bang(mac
, item
.span
, AstFragmentKind
::ImplItems
)
1493 _
=> unreachable
!(),
1496 _
=> noop_flat_map_assoc_item(item
, self),
1500 fn visit_ty(&mut self, ty
: &mut P
<ast
::Ty
>) {
1502 ast
::TyKind
::MacCall(_
) => {}
1503 _
=> return noop_visit_ty(ty
, self),
1506 visit_clobber(ty
, |mut ty
| match mem
::replace(&mut ty
.kind
, ast
::TyKind
::Err
) {
1507 ast
::TyKind
::MacCall(mac
) => {
1508 self.collect_bang(mac
, ty
.span
, AstFragmentKind
::Ty
).make_ty()
1510 _
=> unreachable
!(),
1514 fn visit_foreign_mod(&mut self, foreign_mod
: &mut ast
::ForeignMod
) {
1515 self.cfg
.configure_foreign_mod(foreign_mod
);
1516 noop_visit_foreign_mod(foreign_mod
, self);
1519 fn flat_map_foreign_item(
1521 mut foreign_item
: P
<ast
::ForeignItem
>,
1522 ) -> SmallVec
<[P
<ast
::ForeignItem
>; 1]> {
1523 if let Some(attr
) = self.take_first_attr(&mut foreign_item
) {
1527 Annotatable
::ForeignItem(foreign_item
),
1528 AstFragmentKind
::ForeignItems
,
1530 .make_foreign_items();
1533 match foreign_item
.kind
{
1534 ast
::ForeignItemKind
::MacCall(..) => {
1535 self.check_attributes(&foreign_item
.attrs
);
1536 foreign_item
.and_then(|item
| match item
.kind
{
1537 ast
::ForeignItemKind
::MacCall(mac
) => self
1538 .collect_bang(mac
, item
.span
, AstFragmentKind
::ForeignItems
)
1539 .make_foreign_items(),
1540 _
=> unreachable
!(),
1543 _
=> noop_flat_map_foreign_item(foreign_item
, self),
1547 fn visit_item_kind(&mut self, item
: &mut ast
::ItemKind
) {
1548 self.cfg
.configure_item_kind(item
);
1549 noop_visit_item_kind(item
, self);
1552 fn flat_map_generic_param(
1554 param
: ast
::GenericParam
,
1555 ) -> SmallVec
<[ast
::GenericParam
; 1]> {
1556 let mut param
= configure
!(self, param
);
1558 if let Some(attr
) = self.take_first_attr(&mut param
) {
1562 Annotatable
::GenericParam(param
),
1563 AstFragmentKind
::GenericParams
,
1565 .make_generic_params();
1568 noop_flat_map_generic_param(param
, self)
1571 fn visit_attribute(&mut self, at
: &mut ast
::Attribute
) {
1572 // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
1573 // contents="file contents")]` attributes
1574 if !self.cx
.sess
.check_name(at
, sym
::doc
) {
1575 return noop_visit_attribute(at
, self);
1578 if let Some(list
) = at
.meta_item_list() {
1579 if !list
.iter().any(|it
| it
.has_name(sym
::include
)) {
1580 return noop_visit_attribute(at
, self);
1583 let mut items
= vec
![];
1585 for mut it
in list
{
1586 if !it
.has_name(sym
::include
) {
1588 noop_visit_meta_list_item(&mut it
, self);
1594 if let Some(file
) = it
.value_str() {
1595 let err_count
= self.cx
.sess
.parse_sess
.span_diagnostic
.err_count();
1596 self.check_attributes(slice
::from_ref(at
));
1597 if self.cx
.sess
.parse_sess
.span_diagnostic
.err_count() > err_count
{
1598 // avoid loading the file if they haven't enabled the feature
1599 return noop_visit_attribute(at
, self);
1602 let filename
= match self.cx
.resolve_path(&*file
.as_str(), it
.span()) {
1603 Ok(filename
) => filename
,
1610 match self.cx
.source_map().load_file(&filename
) {
1611 Ok(source_file
) => {
1612 let src
= source_file
1615 .expect("freshly loaded file should have a source");
1616 let src_interned
= Symbol
::intern(src
.as_str());
1618 let include_info
= vec
![
1619 ast
::NestedMetaItem
::MetaItem(attr
::mk_name_value_item_str(
1620 Ident
::with_dummy_span(sym
::file
),
1624 ast
::NestedMetaItem
::MetaItem(attr
::mk_name_value_item_str(
1625 Ident
::with_dummy_span(sym
::contents
),
1631 let include_ident
= Ident
::with_dummy_span(sym
::include
);
1632 let item
= attr
::mk_list_item(include_ident
, include_info
);
1633 items
.push(ast
::NestedMetaItem
::MetaItem(item
));
1636 let lit_span
= it
.name_value_literal_span().unwrap();
1638 if e
.kind() == ErrorKind
::InvalidData
{
1642 &format
!("{} wasn't a utf-8 file", filename
.display()),
1644 .span_label(lit_span
, "contains invalid utf-8")
1647 let mut err
= self.cx
.struct_span_err(
1649 &format
!("couldn't read {}: {}", filename
.display(), e
),
1651 err
.span_label(lit_span
, "couldn't read file");
1660 .struct_span_err(it
.span(), "expected path to external documentation");
1662 // Check if the user erroneously used `doc(include(...))` syntax.
1663 let literal
= it
.meta_item_list().and_then(|list
| {
1664 if list
.len() == 1 {
1665 list
[0].literal().map(|literal
| &literal
.kind
)
1671 let (path
, applicability
) = match &literal
{
1672 Some(LitKind
::Str(path
, ..)) => {
1673 (path
.to_string(), Applicability
::MachineApplicable
)
1675 _
=> (String
::from("<path>"), Applicability
::HasPlaceholders
),
1678 err
.span_suggestion(
1680 "provide a file path with `=`",
1681 format
!("include = \"{}\"", path
),
1689 let meta
= attr
::mk_list_item(Ident
::with_dummy_span(sym
::doc
), items
);
1690 *at
= ast
::Attribute
{
1691 kind
: ast
::AttrKind
::Normal(
1692 AttrItem { path: meta.path, args: meta.kind.mac_args(meta.span), tokens: None }
,
1700 noop_visit_attribute(at
, self)
1704 fn visit_id(&mut self, id
: &mut ast
::NodeId
) {
1706 debug_assert_eq
!(*id
, ast
::DUMMY_NODE_ID
);
1707 *id
= self.cx
.resolver
.next_node_id()
1711 fn visit_fn_decl(&mut self, mut fn_decl
: &mut P
<ast
::FnDecl
>) {
1712 self.cfg
.configure_fn_decl(&mut fn_decl
);
1713 noop_visit_fn_decl(fn_decl
, self);
1717 pub struct ExpansionConfig
<'feat
> {
1718 pub crate_name
: String
,
1719 pub features
: Option
<&'feat Features
>,
1720 pub recursion_limit
: Limit
,
1721 pub trace_mac
: bool
,
1722 pub should_test
: bool
, // If false, strip `#[test]` nodes
1723 pub keep_macs
: bool
,
1724 pub span_debug
: bool
, // If true, use verbose debugging for `proc_macro::Span`
1725 pub proc_macro_backtrace
: bool
, // If true, show backtraces for proc-macro panics
1728 impl<'feat
> ExpansionConfig
<'feat
> {
1729 pub fn default(crate_name
: String
) -> ExpansionConfig
<'
static> {
1733 recursion_limit
: Limit
::new(1024),
1738 proc_macro_backtrace
: false,
1742 fn proc_macro_hygiene(&self) -> bool
{
1743 self.features
.map_or(false, |features
| features
.proc_macro_hygiene
)