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, 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
::{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
::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 fn expect_from_annotatables
<I
: IntoIterator
<Item
= Annotatable
>>(
216 let mut items
= items
.into_iter();
218 AstFragmentKind
::Arms
=> {
219 AstFragment
::Arms(items
.map(Annotatable
::expect_arm
).collect())
221 AstFragmentKind
::Fields
=> {
222 AstFragment
::Fields(items
.map(Annotatable
::expect_field
).collect())
224 AstFragmentKind
::FieldPats
=> {
225 AstFragment
::FieldPats(items
.map(Annotatable
::expect_field_pattern
).collect())
227 AstFragmentKind
::GenericParams
=> {
228 AstFragment
::GenericParams(items
.map(Annotatable
::expect_generic_param
).collect())
230 AstFragmentKind
::Params
=> {
231 AstFragment
::Params(items
.map(Annotatable
::expect_param
).collect())
233 AstFragmentKind
::StructFields
=> {
234 AstFragment
::StructFields(items
.map(Annotatable
::expect_struct_field
).collect())
236 AstFragmentKind
::Variants
=> {
237 AstFragment
::Variants(items
.map(Annotatable
::expect_variant
).collect())
239 AstFragmentKind
::Items
=> {
240 AstFragment
::Items(items
.map(Annotatable
::expect_item
).collect())
242 AstFragmentKind
::ImplItems
=> {
243 AstFragment
::ImplItems(items
.map(Annotatable
::expect_impl_item
).collect())
245 AstFragmentKind
::TraitItems
=> {
246 AstFragment
::TraitItems(items
.map(Annotatable
::expect_trait_item
).collect())
248 AstFragmentKind
::ForeignItems
=> {
249 AstFragment
::ForeignItems(items
.map(Annotatable
::expect_foreign_item
).collect())
251 AstFragmentKind
::Stmts
=> {
252 AstFragment
::Stmts(items
.map(Annotatable
::expect_stmt
).collect())
254 AstFragmentKind
::Expr
=> AstFragment
::Expr(
255 items
.next().expect("expected exactly one expression").expect_expr(),
257 AstFragmentKind
::OptExpr
=> {
258 AstFragment
::OptExpr(items
.next().map(Annotatable
::expect_expr
))
260 AstFragmentKind
::Pat
| AstFragmentKind
::Ty
=> {
261 panic
!("patterns and types aren't annotatable")
267 pub struct Invocation
{
268 pub kind
: InvocationKind
,
269 pub fragment_kind
: AstFragmentKind
,
270 pub expansion_data
: ExpansionData
,
273 pub enum InvocationKind
{
279 attr
: ast
::Attribute
,
281 // Required for resolving derive helper attributes.
283 // We temporarily report errors for attribute macros placed after derives
290 /// "Invocation" that contains all derives from an item,
291 /// broken into multiple `Derive` invocations when expanded.
292 /// FIXME: Find a way to remove it.
299 impl InvocationKind
{
300 fn placeholder_visibility(&self) -> Option
<ast
::Visibility
> {
301 // HACK: For unnamed fields placeholders should have the same visibility as the actual
302 // fields because for tuple structs/variants resolve determines visibilities of their
303 // constructor using these field visibilities before attributes on them are are expanded.
304 // The assumption is that the attribute expansion cannot change field visibilities,
305 // and it holds because only inert attributes are supported in this position.
307 InvocationKind
::Attr { item: Annotatable::StructField(field), .. }
308 | InvocationKind
::Derive { item: Annotatable::StructField(field), .. }
309 | InvocationKind
::DeriveContainer { item: Annotatable::StructField(field), .. }
310 if field
.ident
.is_none() =>
312 Some(field
.vis
.clone())
320 pub fn span(&self) -> Span
{
322 InvocationKind
::Bang { span, .. }
=> *span
,
323 InvocationKind
::Attr { attr, .. }
=> attr
.span
,
324 InvocationKind
::Derive { path, .. }
=> path
.span
,
325 InvocationKind
::DeriveContainer { item, .. }
=> item
.span(),
330 pub struct MacroExpander
<'a
, 'b
> {
331 pub cx
: &'a
mut ExtCtxt
<'b
>,
332 monotonic
: bool
, // cf. `cx.monotonic_expander()`
335 impl<'a
, 'b
> MacroExpander
<'a
, 'b
> {
336 pub fn new(cx
: &'a
mut ExtCtxt
<'b
>, monotonic
: bool
) -> Self {
337 MacroExpander { cx, monotonic }
340 pub fn expand_crate(&mut self, mut krate
: ast
::Crate
) -> ast
::Crate
{
341 let mut module
= ModuleData
{
342 mod_path
: vec
![Ident
::from_str(&self.cx
.ecfg
.crate_name
)],
343 directory
: match self.cx
.source_map().span_to_unmapped_path(krate
.span
) {
344 FileName
::Real(name
) => name
.into_local_path(),
345 other
=> PathBuf
::from(other
.to_string()),
348 module
.directory
.pop();
349 self.cx
.root_path
= module
.directory
.clone();
350 self.cx
.current_expansion
.module
= Rc
::new(module
);
352 let orig_mod_span
= krate
.module
.inner
;
354 let krate_item
= AstFragment
::Items(smallvec
![P(ast
::Item
{
357 kind
: ast
::ItemKind
::Mod(krate
.module
),
358 ident
: Ident
::invalid(),
359 id
: ast
::DUMMY_NODE_ID
,
360 vis
: ast
::Visibility
{
361 span
: krate
.span
.shrink_to_lo(),
362 kind
: ast
::VisibilityKind
::Public
,
368 match self.fully_expand_fragment(krate_item
).make_items().pop().map(P
::into_inner
) {
369 Some(ast
::Item { attrs, kind: ast::ItemKind::Mod(module), .. }
) => {
371 krate
.module
= module
;
374 // Resolution failed so we return an empty expansion
375 krate
.attrs
= vec
![];
376 krate
.module
= ast
::Mod
{
377 inner
: orig_mod_span
,
378 unsafety
: Unsafe
::No
,
383 Some(ast
::Item { span, kind, .. }
) => {
384 krate
.attrs
= vec
![];
385 krate
.module
= ast
::Mod
{
386 inner
: orig_mod_span
,
387 unsafety
: Unsafe
::No
,
394 "expected crate top-level item to be a module after macro expansion, found {} {}",
395 kind
.article(), kind
.descr()
400 self.cx
.trace_macros_diag();
404 // Recursively expand all macro invocations in this AST fragment.
405 pub fn fully_expand_fragment(&mut self, input_fragment
: AstFragment
) -> AstFragment
{
406 let orig_expansion_data
= self.cx
.current_expansion
.clone();
407 self.cx
.current_expansion
.depth
= 0;
409 // Collect all macro invocations and replace them with placeholders.
410 let (mut fragment_with_placeholders
, mut invocations
) =
411 self.collect_invocations(input_fragment
, &[]);
413 // Optimization: if we resolve all imports now,
414 // we'll be able to immediately resolve most of imported macros.
415 self.resolve_imports();
417 // Resolve paths in all invocations and produce output expanded fragments for them, but
418 // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
419 // The output fragments also go through expansion recursively until no invocations are left.
420 // Unresolved macros produce dummy outputs as a recovery measure.
421 invocations
.reverse();
422 let mut expanded_fragments
= Vec
::new();
423 let mut undetermined_invocations
= Vec
::new();
424 let (mut progress
, mut force
) = (false, !self.monotonic
);
426 let (invoc
, res
) = if let Some(invoc
) = invocations
.pop() {
429 self.resolve_imports();
430 if undetermined_invocations
.is_empty() {
433 invocations
= mem
::take(&mut undetermined_invocations
);
434 force
= !mem
::replace(&mut progress
, false);
438 let res
= match res
{
441 let eager_expansion_root
= if self.monotonic
{
442 invoc
.expansion_data
.id
444 orig_expansion_data
.id
446 match self.cx
.resolver
.resolve_macro_invocation(
448 eager_expansion_root
,
452 Err(Indeterminate
) => {
453 // Cannot resolve, will retry this invocation later.
454 undetermined_invocations
.push((invoc
, None
));
461 let ExpansionData { depth, id: expn_id, .. }
= invoc
.expansion_data
;
462 self.cx
.current_expansion
= invoc
.expansion_data
.clone();
464 // FIXME(jseyfried): Refactor out the following logic
465 let (expanded_fragment
, new_invocations
) = match res
{
466 InvocationRes
::Single(ext
) => match self.expand_invoc(invoc
, &ext
.kind
) {
467 ExpandResult
::Ready(fragment
) => self.collect_invocations(fragment
, &[]),
468 ExpandResult
::Retry(invoc
, explanation
) => {
470 // We are stuck, stop retrying and produce a dummy fragment.
471 let span
= invoc
.span();
472 self.cx
.span_err(span
, &explanation
);
473 let fragment
= invoc
.fragment_kind
.dummy(span
);
474 self.collect_invocations(fragment
, &[])
476 // Cannot expand, will retry this invocation later.
477 undetermined_invocations
478 .push((invoc
, Some(InvocationRes
::Single(ext
))));
483 InvocationRes
::DeriveContainer(_exts
) => {
484 // FIXME: Consider using the derive resolutions (`_exts`) immediately,
485 // instead of enqueuing the derives to be resolved again later.
486 let (derives
, item
) = match invoc
.kind
{
487 InvocationKind
::DeriveContainer { derives, item }
=> (derives
, item
),
490 if !item
.derive_allowed() {
491 self.error_derive_forbidden_on_non_adt(&derives
, &item
);
494 let mut item
= self.fully_configure(item
);
495 item
.visit_attrs(|attrs
| attrs
.retain(|a
| !a
.has_name(sym
::derive
)));
497 let mut derive_placeholders
= Vec
::with_capacity(derives
.len());
498 invocations
.reserve(derives
.len());
499 for path
in derives
{
500 let expn_id
= ExpnId
::fresh(None
);
501 derive_placeholders
.push(NodeId
::placeholder_from_expn_id(expn_id
));
504 kind
: InvocationKind
::Derive { path, item: item.clone() }
,
505 fragment_kind
: invoc
.fragment_kind
,
506 expansion_data
: ExpansionData
{
508 ..invoc
.expansion_data
.clone()
515 invoc
.fragment_kind
.expect_from_annotatables(::std
::iter
::once(item
));
516 self.collect_invocations(fragment
, &derive_placeholders
)
521 if expanded_fragments
.len() < depth
{
522 expanded_fragments
.push(Vec
::new());
524 expanded_fragments
[depth
- 1].push((expn_id
, expanded_fragment
));
525 invocations
.extend(new_invocations
.into_iter().rev());
528 self.cx
.current_expansion
= orig_expansion_data
;
530 // Finally incorporate all the expanded macros into the input AST fragment.
531 let mut placeholder_expander
= PlaceholderExpander
::new(self.cx
, self.monotonic
);
532 while let Some(expanded_fragments
) = expanded_fragments
.pop() {
533 for (expn_id
, expanded_fragment
) in expanded_fragments
.into_iter().rev() {
535 .add(NodeId
::placeholder_from_expn_id(expn_id
), expanded_fragment
);
538 fragment_with_placeholders
.mut_visit_with(&mut placeholder_expander
);
539 fragment_with_placeholders
542 fn error_derive_forbidden_on_non_adt(&self, derives
: &[Path
], item
: &Annotatable
) {
543 let attr
= self.cx
.sess
.find_by_name(item
.attrs(), sym
::derive
);
544 let span
= attr
.map_or(item
.span(), |attr
| attr
.span
);
545 let mut err
= rustc_errors
::struct_span_err
!(
549 "`derive` may only be applied to structs, enums and unions",
551 if let Some(ast
::Attribute { style: ast::AttrStyle::Inner, .. }
) = attr
{
552 let trait_list
= derives
.iter().map(|t
| pprust
::path_to_string(t
)).collect
::<Vec
<_
>>();
553 let suggestion
= format
!("#[derive({})]", trait_list
.join(", "));
556 "try an outer attribute",
558 // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
559 Applicability
::MaybeIncorrect
,
565 fn resolve_imports(&mut self) {
567 self.cx
.resolver
.resolve_imports();
571 /// Collects all macro invocations reachable at this time in this AST fragment, and replace
572 /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
573 /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
574 /// prepares data for resolving paths of macro invocations.
575 fn collect_invocations(
577 mut fragment
: AstFragment
,
578 extra_placeholders
: &[NodeId
],
579 ) -> (AstFragment
, Vec
<(Invocation
, Option
<InvocationRes
>)>) {
580 // Resolve `$crate`s in the fragment for pretty-printing.
581 self.cx
.resolver
.resolve_dollar_crates();
584 let mut collector
= InvocationCollector
{
585 cfg
: StripUnconfigured { sess: &self.cx.sess, features: self.cx.ecfg.features }
,
587 invocations
: Vec
::new(),
588 monotonic
: self.monotonic
,
590 fragment
.mut_visit_with(&mut collector
);
591 fragment
.add_placeholders(extra_placeholders
);
592 collector
.invocations
598 .visit_ast_fragment_with_placeholders(self.cx
.current_expansion
.id
, &fragment
);
601 (fragment
, invocations
)
604 fn fully_configure(&mut self, item
: Annotatable
) -> Annotatable
{
605 let mut cfg
= StripUnconfigured { sess: &self.cx.sess, features: self.cx.ecfg.features }
;
606 // Since the item itself has already been configured by the InvocationCollector,
607 // we know that fold result vector will contain exactly one element
609 Annotatable
::Item(item
) => Annotatable
::Item(cfg
.flat_map_item(item
).pop().unwrap()),
610 Annotatable
::TraitItem(item
) => {
611 Annotatable
::TraitItem(cfg
.flat_map_trait_item(item
).pop().unwrap())
613 Annotatable
::ImplItem(item
) => {
614 Annotatable
::ImplItem(cfg
.flat_map_impl_item(item
).pop().unwrap())
616 Annotatable
::ForeignItem(item
) => {
617 Annotatable
::ForeignItem(cfg
.flat_map_foreign_item(item
).pop().unwrap())
619 Annotatable
::Stmt(stmt
) => {
620 Annotatable
::Stmt(stmt
.map(|stmt
| cfg
.flat_map_stmt(stmt
).pop().unwrap()))
622 Annotatable
::Expr(mut expr
) => Annotatable
::Expr({
623 cfg
.visit_expr(&mut expr
);
626 Annotatable
::Arm(arm
) => Annotatable
::Arm(cfg
.flat_map_arm(arm
).pop().unwrap()),
627 Annotatable
::Field(field
) => {
628 Annotatable
::Field(cfg
.flat_map_field(field
).pop().unwrap())
630 Annotatable
::FieldPat(fp
) => {
631 Annotatable
::FieldPat(cfg
.flat_map_field_pattern(fp
).pop().unwrap())
633 Annotatable
::GenericParam(param
) => {
634 Annotatable
::GenericParam(cfg
.flat_map_generic_param(param
).pop().unwrap())
636 Annotatable
::Param(param
) => {
637 Annotatable
::Param(cfg
.flat_map_param(param
).pop().unwrap())
639 Annotatable
::StructField(sf
) => {
640 Annotatable
::StructField(cfg
.flat_map_struct_field(sf
).pop().unwrap())
642 Annotatable
::Variant(v
) => Annotatable
::Variant(cfg
.flat_map_variant(v
).pop().unwrap()),
646 fn error_recursion_limit_reached(&mut self) {
647 let expn_data
= self.cx
.current_expansion
.id
.expn_data();
648 let suggested_limit
= self.cx
.ecfg
.recursion_limit
* 2;
652 &format
!("recursion limit reached while expanding `{}`", expn_data
.kind
.descr()),
655 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
656 suggested_limit
, self.cx
.ecfg
.crate_name
,
659 self.cx
.trace_macros_diag();
662 /// A macro's expansion does not fit in this fragment kind.
663 /// For example, a non-type macro in a type position.
664 fn error_wrong_fragment_kind(&mut self, kind
: AstFragmentKind
, mac
: &ast
::MacCall
, span
: Span
) {
666 "non-{kind} macro in {kind} position: {path}",
668 path
= pprust
::path_to_string(&mac
.path
),
670 self.cx
.span_err(span
, &msg
);
671 self.cx
.trace_macros_diag();
677 ext
: &SyntaxExtensionKind
,
678 ) -> ExpandResult
<AstFragment
, Invocation
> {
679 let recursion_limit
=
680 self.cx
.reduced_recursion_limit
.unwrap_or(self.cx
.ecfg
.recursion_limit
);
681 if !recursion_limit
.value_within_limit(self.cx
.current_expansion
.depth
) {
682 if self.cx
.reduced_recursion_limit
.is_none() {
683 self.error_recursion_limit_reached();
686 // Reduce the recursion limit by half each time it triggers.
687 self.cx
.reduced_recursion_limit
= Some(recursion_limit
/ 2);
689 return ExpandResult
::Ready(invoc
.fragment_kind
.dummy(invoc
.span()));
692 let (fragment_kind
, span
) = (invoc
.fragment_kind
, invoc
.span());
693 ExpandResult
::Ready(match invoc
.kind
{
694 InvocationKind
::Bang { mac, .. }
=> match ext
{
695 SyntaxExtensionKind
::Bang(expander
) => {
696 let tok_result
= match expander
.expand(self.cx
, span
, mac
.args
.inner_tokens()) {
697 Err(_
) => return ExpandResult
::Ready(fragment_kind
.dummy(span
)),
700 self.parse_ast_fragment(tok_result
, fragment_kind
, &mac
.path
, span
)
702 SyntaxExtensionKind
::LegacyBang(expander
) => {
703 let prev
= self.cx
.current_expansion
.prior_type_ascription
;
704 self.cx
.current_expansion
.prior_type_ascription
= mac
.prior_type_ascription
;
705 let tok_result
= expander
.expand(self.cx
, span
, mac
.args
.inner_tokens());
706 let result
= if let Some(result
) = fragment_kind
.make_from(tok_result
) {
709 self.error_wrong_fragment_kind(fragment_kind
, &mac
, span
);
710 fragment_kind
.dummy(span
)
712 self.cx
.current_expansion
.prior_type_ascription
= prev
;
717 InvocationKind
::Attr { attr, mut item, derives, after_derive }
=> match ext
{
718 SyntaxExtensionKind
::Attr(expander
) => {
719 self.gate_proc_macro_input(&item
);
720 self.gate_proc_macro_attr_item(span
, &item
);
721 let tokens
= item
.into_tokens(&self.cx
.sess
.parse_sess
);
722 let attr_item
= attr
.unwrap_normal_item();
723 if let MacArgs
::Eq(..) = attr_item
.args
{
724 self.cx
.span_err(span
, "key-value macro attributes are not supported");
726 let inner_tokens
= attr_item
.args
.inner_tokens();
727 let tok_result
= match expander
.expand(self.cx
, span
, inner_tokens
, tokens
) {
728 Err(_
) => return ExpandResult
::Ready(fragment_kind
.dummy(span
)),
731 self.parse_ast_fragment(tok_result
, fragment_kind
, &attr_item
.path
, span
)
733 SyntaxExtensionKind
::LegacyAttr(expander
) => {
734 match validate_attr
::parse_meta(&self.cx
.sess
.parse_sess
, &attr
) {
736 let items
= match expander
.expand(self.cx
, span
, &meta
, item
) {
737 ExpandResult
::Ready(items
) => items
,
738 ExpandResult
::Retry(item
, explanation
) => {
739 // Reassemble the original invocation for retrying.
740 return ExpandResult
::Retry(
742 kind
: InvocationKind
::Attr
{
754 fragment_kind
.expect_from_annotatables(items
)
758 fragment_kind
.dummy(span
)
762 SyntaxExtensionKind
::NonMacroAttr { mark_used }
=> {
763 self.cx
.sess
.mark_attr_known(&attr
);
765 self.cx
.sess
.mark_attr_used(&attr
);
767 item
.visit_attrs(|attrs
| attrs
.push(attr
));
768 fragment_kind
.expect_from_annotatables(iter
::once(item
))
772 InvocationKind
::Derive { path, item }
=> match ext
{
773 SyntaxExtensionKind
::Derive(expander
)
774 | SyntaxExtensionKind
::LegacyDerive(expander
) => {
775 if !item
.derive_allowed() {
776 return ExpandResult
::Ready(fragment_kind
.dummy(span
));
778 if let SyntaxExtensionKind
::Derive(..) = ext
{
779 self.gate_proc_macro_input(&item
);
781 let meta
= ast
::MetaItem { kind: ast::MetaItemKind::Word, span, path }
;
782 let items
= match expander
.expand(self.cx
, span
, &meta
, item
) {
783 ExpandResult
::Ready(items
) => items
,
784 ExpandResult
::Retry(item
, explanation
) => {
785 // Reassemble the original invocation for retrying.
786 return ExpandResult
::Retry(
788 kind
: InvocationKind
::Derive { path: meta.path, item }
,
795 fragment_kind
.expect_from_annotatables(items
)
799 InvocationKind
::DeriveContainer { .. }
=> unreachable
!(),
803 fn gate_proc_macro_attr_item(&self, span
: Span
, item
: &Annotatable
) {
804 let kind
= match item
{
806 | Annotatable
::TraitItem(_
)
807 | Annotatable
::ImplItem(_
)
808 | Annotatable
::ForeignItem(_
) => return,
809 Annotatable
::Stmt(_
) => "statements",
810 Annotatable
::Expr(_
) => "expressions",
812 | Annotatable
::Field(..)
813 | Annotatable
::FieldPat(..)
814 | Annotatable
::GenericParam(..)
815 | Annotatable
::Param(..)
816 | Annotatable
::StructField(..)
817 | Annotatable
::Variant(..) => panic
!("unexpected annotatable"),
819 if self.cx
.ecfg
.proc_macro_hygiene() {
823 &self.cx
.sess
.parse_sess
,
824 sym
::proc_macro_hygiene
,
826 &format
!("custom attributes cannot be applied to {}", kind
),
831 fn gate_proc_macro_input(&self, annotatable
: &Annotatable
) {
832 struct GateProcMacroInput
<'a
> {
833 parse_sess
: &'a ParseSess
,
836 impl<'ast
, 'a
> Visitor
<'ast
> for GateProcMacroInput
<'a
> {
837 fn visit_item(&mut self, item
: &'ast ast
::Item
) {
839 ast
::ItemKind
::Mod(module
) if !module
.inline
=> {
842 sym
::proc_macro_hygiene
,
844 "non-inline modules in proc macro input are unstable",
851 visit
::walk_item(self, item
);
854 fn visit_mac(&mut self, _
: &'ast ast
::MacCall
) {}
857 if !self.cx
.ecfg
.proc_macro_hygiene() {
859 .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess }
);
863 fn parse_ast_fragment(
866 kind
: AstFragmentKind
,
870 let mut parser
= self.cx
.new_parser_from_tts(toks
);
871 match parse_ast_fragment(&mut parser
, kind
) {
873 ensure_complete_parse(&mut parser
, path
, kind
.name(), span
);
878 annotate_err_with_kind(&mut err
, kind
, span
);
880 self.cx
.trace_macros_diag();
887 pub fn parse_ast_fragment
<'a
>(
888 this
: &mut Parser
<'a
>,
889 kind
: AstFragmentKind
,
890 ) -> PResult
<'a
, AstFragment
> {
892 AstFragmentKind
::Items
=> {
893 let mut items
= SmallVec
::new();
894 while let Some(item
) = this
.parse_item()?
{
897 AstFragment
::Items(items
)
899 AstFragmentKind
::TraitItems
=> {
900 let mut items
= SmallVec
::new();
901 while let Some(item
) = this
.parse_trait_item()?
{
904 AstFragment
::TraitItems(items
)
906 AstFragmentKind
::ImplItems
=> {
907 let mut items
= SmallVec
::new();
908 while let Some(item
) = this
.parse_impl_item()?
{
911 AstFragment
::ImplItems(items
)
913 AstFragmentKind
::ForeignItems
=> {
914 let mut items
= SmallVec
::new();
915 while let Some(item
) = this
.parse_foreign_item()?
{
918 AstFragment
::ForeignItems(items
)
920 AstFragmentKind
::Stmts
=> {
921 let mut stmts
= SmallVec
::new();
922 // Won't make progress on a `}`.
923 while this
.token
!= token
::Eof
&& this
.token
!= token
::CloseDelim(token
::Brace
) {
924 if let Some(stmt
) = this
.parse_full_stmt()?
{
928 AstFragment
::Stmts(stmts
)
930 AstFragmentKind
::Expr
=> AstFragment
::Expr(this
.parse_expr()?
),
931 AstFragmentKind
::OptExpr
=> {
932 if this
.token
!= token
::Eof
{
933 AstFragment
::OptExpr(Some(this
.parse_expr()?
))
935 AstFragment
::OptExpr(None
)
938 AstFragmentKind
::Ty
=> AstFragment
::Ty(this
.parse_ty()?
),
939 AstFragmentKind
::Pat
=> AstFragment
::Pat(this
.parse_pat(None
)?
),
940 AstFragmentKind
::Arms
941 | AstFragmentKind
::Fields
942 | AstFragmentKind
::FieldPats
943 | AstFragmentKind
::GenericParams
944 | AstFragmentKind
::Params
945 | AstFragmentKind
::StructFields
946 | AstFragmentKind
::Variants
=> panic
!("unexpected AST fragment kind"),
950 pub fn ensure_complete_parse
<'a
>(
951 this
: &mut Parser
<'a
>,
956 if this
.token
!= token
::Eof
{
957 let token
= pprust
::token_to_string(&this
.token
);
958 let msg
= format
!("macro expansion ignores token `{}` and any following", token
);
959 // Avoid emitting backtrace info twice.
960 let def_site_span
= this
.token
.span
.with_ctxt(SyntaxContext
::root());
961 let mut err
= this
.struct_span_err(def_site_span
, &msg
);
962 err
.span_label(span
, "caused by the macro expansion here");
964 "the usage of `{}!` is likely invalid in {} context",
965 pprust
::path_to_string(macro_path
),
969 let semi_span
= this
.sess
.source_map().next_point(span
);
971 let semi_full_span
= semi_span
.to(this
.sess
.source_map().next_point(semi_span
));
972 match this
.sess
.source_map().span_to_snippet(semi_full_span
) {
973 Ok(ref snippet
) if &snippet
[..] != ";" && kind_name
== "expression" => {
976 "you might be missing a semicolon here",
978 Applicability
::MaybeIncorrect
,
987 struct InvocationCollector
<'a
, 'b
> {
988 cx
: &'a
mut ExtCtxt
<'b
>,
989 cfg
: StripUnconfigured
<'a
>,
990 invocations
: Vec
<(Invocation
, Option
<InvocationRes
>)>,
994 impl<'a
, 'b
> InvocationCollector
<'a
, 'b
> {
995 fn collect(&mut self, fragment_kind
: AstFragmentKind
, kind
: InvocationKind
) -> AstFragment
{
996 // Expansion data for all the collected invocations is set upon their resolution,
997 // with exception of the derive container case which is not resolved and can get
998 // its expansion data immediately.
999 let expn_data
= match &kind
{
1000 InvocationKind
::DeriveContainer { item, .. }
=> Some(ExpnData
{
1001 parent
: self.cx
.current_expansion
.id
,
1002 ..ExpnData
::default(
1003 ExpnKind
::Macro(MacroKind
::Attr
, sym
::derive
),
1005 self.cx
.sess
.parse_sess
.edition
,
1011 let expn_id
= ExpnId
::fresh(expn_data
);
1012 let vis
= kind
.placeholder_visibility();
1013 self.invocations
.push((
1017 expansion_data
: ExpansionData
{
1019 depth
: self.cx
.current_expansion
.depth
+ 1,
1020 ..self.cx
.current_expansion
.clone()
1025 placeholder(fragment_kind
, NodeId
::placeholder_from_expn_id(expn_id
), vis
)
1032 kind
: AstFragmentKind
,
1034 self.collect(kind
, InvocationKind
::Bang { mac, span }
)
1039 attr
: Option
<ast
::Attribute
>,
1042 kind
: AstFragmentKind
,
1048 Some(attr
) => InvocationKind
::Attr { attr, item, derives, after_derive }
,
1049 None
=> InvocationKind
::DeriveContainer { derives, item }
,
1056 attrs
: &mut Vec
<ast
::Attribute
>,
1057 after_derive
: &mut bool
,
1058 ) -> Option
<ast
::Attribute
> {
1062 if a
.has_name(sym
::derive
) {
1063 *after_derive
= true;
1065 !self.cx
.sess
.is_attr_known(a
) && !is_builtin_attr(a
)
1067 .map(|i
| attrs
.remove(i
));
1068 if let Some(attr
) = &attr
{
1069 if !self.cx
.ecfg
.custom_inner_attributes()
1070 && attr
.style
== ast
::AttrStyle
::Inner
1071 && !attr
.has_name(sym
::test
)
1074 &self.cx
.sess
.parse_sess
,
1075 sym
::custom_inner_attributes
,
1077 "non-builtin inner attributes are unstable",
1085 /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
1088 item
: &mut impl HasAttrs
,
1089 ) -> (Option
<ast
::Attribute
>, Vec
<Path
>, /* after_derive */ bool
) {
1090 let (mut attr
, mut traits
, mut after_derive
) = (None
, Vec
::new(), false);
1092 item
.visit_attrs(|mut attrs
| {
1093 attr
= self.find_attr_invoc(&mut attrs
, &mut after_derive
);
1094 traits
= collect_derives(&mut self.cx
, &mut attrs
);
1097 (attr
, traits
, after_derive
)
1100 /// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough
1101 /// to the unused-attributes lint (making it an error on statements and expressions
1102 /// is a breaking change)
1103 fn classify_nonitem(
1105 nonitem
: &mut impl HasAttrs
,
1106 ) -> (Option
<ast
::Attribute
>, /* after_derive */ bool
) {
1107 let (mut attr
, mut after_derive
) = (None
, false);
1109 nonitem
.visit_attrs(|mut attrs
| {
1110 attr
= self.find_attr_invoc(&mut attrs
, &mut after_derive
);
1113 (attr
, after_derive
)
1116 fn configure
<T
: HasAttrs
>(&mut self, node
: T
) -> Option
<T
> {
1117 self.cfg
.configure(node
)
1120 // Detect use of feature-gated or invalid attributes on macro invocations
1121 // since they will not be detected after macro expansion.
1122 fn check_attributes(&mut self, attrs
: &[ast
::Attribute
]) {
1123 let features
= self.cx
.ecfg
.features
.unwrap();
1124 for attr
in attrs
.iter() {
1125 rustc_ast_passes
::feature_gate
::check_attribute(attr
, self.cx
.sess
, features
);
1126 validate_attr
::check_meta(&self.cx
.sess
.parse_sess
, attr
);
1128 // macros are expanded before any lint passes so this warning has to be hardcoded
1129 if attr
.has_name(sym
::derive
) {
1133 .struct_span_warn(attr
.span
, "`#[derive]` does nothing on macro invocations")
1134 .note("this may become a hard error in a future release")
1138 if attr
.doc_str().is_some() {
1139 self.cx
.sess
.parse_sess
.buffer_lint_with_diagnostic(
1140 &UNUSED_DOC_COMMENTS
,
1143 "unused doc comment",
1144 BuiltinLintDiagnostics
::UnusedDocComment(attr
.span
),
1151 impl<'a
, 'b
> MutVisitor
for InvocationCollector
<'a
, 'b
> {
1152 fn visit_expr(&mut self, expr
: &mut P
<ast
::Expr
>) {
1153 self.cfg
.configure_expr(expr
);
1154 visit_clobber(expr
.deref_mut(), |mut expr
| {
1155 self.cfg
.configure_expr_kind(&mut expr
.kind
);
1157 // ignore derives so they remain unused
1158 let (attr
, after_derive
) = self.classify_nonitem(&mut expr
);
1160 if let Some(ref attr_value
) = attr
{
1161 // Collect the invoc regardless of whether or not attributes are permitted here
1162 // expansion will eat the attribute so it won't error later.
1163 self.cfg
.maybe_emit_expr_attr_err(attr_value
);
1165 // AstFragmentKind::Expr requires the macro to emit an expression.
1170 Annotatable
::Expr(P(expr
)),
1171 AstFragmentKind
::Expr
,
1178 if let ast
::ExprKind
::MacCall(mac
) = expr
.kind
{
1179 self.check_attributes(&expr
.attrs
);
1180 self.collect_bang(mac
, expr
.span
, AstFragmentKind
::Expr
).make_expr().into_inner()
1182 ensure_sufficient_stack(|| noop_visit_expr(&mut expr
, self));
1188 fn flat_map_arm(&mut self, arm
: ast
::Arm
) -> SmallVec
<[ast
::Arm
; 1]> {
1189 let mut arm
= configure
!(self, arm
);
1191 let (attr
, traits
, after_derive
) = self.classify_item(&mut arm
);
1192 if attr
.is_some() || !traits
.is_empty() {
1197 Annotatable
::Arm(arm
),
1198 AstFragmentKind
::Arms
,
1204 noop_flat_map_arm(arm
, self)
1207 fn flat_map_field(&mut self, field
: ast
::Field
) -> SmallVec
<[ast
::Field
; 1]> {
1208 let mut field
= configure
!(self, field
);
1210 let (attr
, traits
, after_derive
) = self.classify_item(&mut field
);
1211 if attr
.is_some() || !traits
.is_empty() {
1216 Annotatable
::Field(field
),
1217 AstFragmentKind
::Fields
,
1223 noop_flat_map_field(field
, self)
1226 fn flat_map_field_pattern(&mut self, fp
: ast
::FieldPat
) -> SmallVec
<[ast
::FieldPat
; 1]> {
1227 let mut fp
= configure
!(self, fp
);
1229 let (attr
, traits
, after_derive
) = self.classify_item(&mut fp
);
1230 if attr
.is_some() || !traits
.is_empty() {
1235 Annotatable
::FieldPat(fp
),
1236 AstFragmentKind
::FieldPats
,
1239 .make_field_patterns();
1242 noop_flat_map_field_pattern(fp
, self)
1245 fn flat_map_param(&mut self, p
: ast
::Param
) -> SmallVec
<[ast
::Param
; 1]> {
1246 let mut p
= configure
!(self, p
);
1248 let (attr
, traits
, after_derive
) = self.classify_item(&mut p
);
1249 if attr
.is_some() || !traits
.is_empty() {
1254 Annotatable
::Param(p
),
1255 AstFragmentKind
::Params
,
1261 noop_flat_map_param(p
, self)
1264 fn flat_map_struct_field(&mut self, sf
: ast
::StructField
) -> SmallVec
<[ast
::StructField
; 1]> {
1265 let mut sf
= configure
!(self, sf
);
1267 let (attr
, traits
, after_derive
) = self.classify_item(&mut sf
);
1268 if attr
.is_some() || !traits
.is_empty() {
1273 Annotatable
::StructField(sf
),
1274 AstFragmentKind
::StructFields
,
1277 .make_struct_fields();
1280 noop_flat_map_struct_field(sf
, self)
1283 fn flat_map_variant(&mut self, variant
: ast
::Variant
) -> SmallVec
<[ast
::Variant
; 1]> {
1284 let mut variant
= configure
!(self, variant
);
1286 let (attr
, traits
, after_derive
) = self.classify_item(&mut variant
);
1287 if attr
.is_some() || !traits
.is_empty() {
1292 Annotatable
::Variant(variant
),
1293 AstFragmentKind
::Variants
,
1299 noop_flat_map_variant(variant
, self)
1302 fn filter_map_expr(&mut self, expr
: P
<ast
::Expr
>) -> Option
<P
<ast
::Expr
>> {
1303 let expr
= configure
!(self, expr
);
1304 expr
.filter_map(|mut expr
| {
1305 self.cfg
.configure_expr_kind(&mut expr
.kind
);
1307 // Ignore derives so they remain unused.
1308 let (attr
, after_derive
) = self.classify_nonitem(&mut expr
);
1310 if let Some(ref attr_value
) = attr
{
1311 self.cfg
.maybe_emit_expr_attr_err(attr_value
);
1317 Annotatable
::Expr(P(expr
)),
1318 AstFragmentKind
::OptExpr
,
1322 .map(|expr
| expr
.into_inner());
1325 if let ast
::ExprKind
::MacCall(mac
) = expr
.kind
{
1326 self.check_attributes(&expr
.attrs
);
1327 self.collect_bang(mac
, expr
.span
, AstFragmentKind
::OptExpr
)
1329 .map(|expr
| expr
.into_inner())
1332 noop_visit_expr(&mut expr
, self);
1339 fn visit_pat(&mut self, pat
: &mut P
<ast
::Pat
>) {
1340 self.cfg
.configure_pat(pat
);
1342 PatKind
::MacCall(_
) => {}
1343 _
=> return noop_visit_pat(pat
, self),
1346 visit_clobber(pat
, |mut pat
| match mem
::replace(&mut pat
.kind
, PatKind
::Wild
) {
1347 PatKind
::MacCall(mac
) => {
1348 self.collect_bang(mac
, pat
.span
, AstFragmentKind
::Pat
).make_pat()
1350 _
=> unreachable
!(),
1354 fn flat_map_stmt(&mut self, stmt
: ast
::Stmt
) -> SmallVec
<[ast
::Stmt
; 1]> {
1355 let mut stmt
= configure
!(self, stmt
);
1357 // we'll expand attributes on expressions separately
1358 if !stmt
.is_expr() {
1359 let (attr
, derives
, after_derive
) = if stmt
.is_item() {
1360 self.classify_item(&mut stmt
)
1362 // ignore derives on non-item statements so it falls through
1363 // to the unused-attributes lint
1364 let (attr
, after_derive
) = self.classify_nonitem(&mut stmt
);
1365 (attr
, vec
![], after_derive
)
1368 if attr
.is_some() || !derives
.is_empty() {
1373 Annotatable
::Stmt(P(stmt
)),
1374 AstFragmentKind
::Stmts
,
1381 if let StmtKind
::MacCall(mac
) = stmt
.kind
{
1382 let MacCallStmt { mac, style, attrs }
= mac
.into_inner();
1383 self.check_attributes(&attrs
);
1384 let mut placeholder
=
1385 self.collect_bang(mac
, stmt
.span
, AstFragmentKind
::Stmts
).make_stmts();
1387 // If this is a macro invocation with a semicolon, then apply that
1388 // semicolon to the final statement produced by expansion.
1389 if style
== MacStmtStyle
::Semicolon
{
1390 if let Some(stmt
) = placeholder
.pop() {
1391 placeholder
.push(stmt
.add_trailing_semicolon());
1398 // The placeholder expander gives ids to statements, so we avoid folding the id here.
1399 let ast
::Stmt { id, kind, span, tokens }
= stmt
;
1400 noop_flat_map_stmt_kind(kind
, self)
1402 .map(|kind
| ast
::Stmt { id, kind, span, tokens: tokens.clone() }
)
1406 fn visit_block(&mut self, block
: &mut P
<Block
>) {
1407 let old_directory_ownership
= self.cx
.current_expansion
.directory_ownership
;
1408 self.cx
.current_expansion
.directory_ownership
= DirectoryOwnership
::UnownedViaBlock
;
1409 noop_visit_block(block
, self);
1410 self.cx
.current_expansion
.directory_ownership
= old_directory_ownership
;
1413 fn flat_map_item(&mut self, item
: P
<ast
::Item
>) -> SmallVec
<[P
<ast
::Item
>; 1]> {
1414 let mut item
= configure
!(self, item
);
1416 let (attr
, traits
, after_derive
) = self.classify_item(&mut item
);
1417 if attr
.is_some() || !traits
.is_empty() {
1422 Annotatable
::Item(item
),
1423 AstFragmentKind
::Items
,
1429 let mut attrs
= mem
::take(&mut item
.attrs
); // We do this to please borrowck.
1430 let ident
= item
.ident
;
1431 let span
= item
.span
;
1434 ast
::ItemKind
::MacCall(..) => {
1436 self.check_attributes(&item
.attrs
);
1437 item
.and_then(|item
| match item
.kind
{
1438 ItemKind
::MacCall(mac
) => self
1439 .collect(AstFragmentKind
::Items
, InvocationKind
::Bang { mac, span }
)
1441 _
=> unreachable
!(),
1444 ast
::ItemKind
::Mod(ref mut old_mod @ ast
::Mod { .. }
) if ident
!= Ident
::invalid() => {
1445 let sess
= &self.cx
.sess
.parse_sess
;
1446 let orig_ownership
= self.cx
.current_expansion
.directory_ownership
;
1447 let mut module
= (*self.cx
.current_expansion
.module
).clone();
1449 let pushed
= &mut false; // Record `parse_external_mod` pushing so we can pop.
1450 let dir
= Directory { ownership: orig_ownership, path: module.directory }
;
1451 let Directory { ownership, path }
= if old_mod
.inline
{
1452 // Inline `mod foo { ... }`, but we still need to push directories.
1454 push_directory(&self.cx
.sess
, ident
, &item
.attrs
, dir
)
1456 // We have an outline `mod foo;` so we need to parse the file.
1457 let (new_mod
, dir
) = parse_external_mod(
1467 let krate
= ast
::Crate
{
1468 span
: new_mod
.inner
,
1471 proc_macros
: vec
![],
1473 if let Some(extern_mod_loaded
) = self.cx
.extern_mod_loaded
{
1474 extern_mod_loaded(&krate
);
1477 *old_mod
= krate
.module
;
1478 item
.attrs
= krate
.attrs
;
1479 // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1480 item
= match self.configure(item
) {
1484 sess
.included_mod_stack
.borrow_mut().pop();
1486 return Default
::default();
1492 // Set the module info before we flat map.
1493 self.cx
.current_expansion
.directory_ownership
= ownership
;
1494 module
.directory
= path
;
1495 module
.mod_path
.push(ident
);
1497 mem
::replace(&mut self.cx
.current_expansion
.module
, Rc
::new(module
));
1499 let result
= noop_flat_map_item(item
, self);
1501 // Restore the module info.
1502 self.cx
.current_expansion
.module
= orig_module
;
1503 self.cx
.current_expansion
.directory_ownership
= orig_ownership
;
1505 sess
.included_mod_stack
.borrow_mut().pop();
1511 noop_flat_map_item(item
, self)
1516 fn flat_map_trait_item(&mut self, item
: P
<ast
::AssocItem
>) -> SmallVec
<[P
<ast
::AssocItem
>; 1]> {
1517 let mut item
= configure
!(self, item
);
1519 let (attr
, traits
, after_derive
) = self.classify_item(&mut item
);
1520 if attr
.is_some() || !traits
.is_empty() {
1525 Annotatable
::TraitItem(item
),
1526 AstFragmentKind
::TraitItems
,
1529 .make_trait_items();
1533 ast
::AssocItemKind
::MacCall(..) => {
1534 self.check_attributes(&item
.attrs
);
1535 item
.and_then(|item
| match item
.kind
{
1536 ast
::AssocItemKind
::MacCall(mac
) => self
1537 .collect_bang(mac
, item
.span
, AstFragmentKind
::TraitItems
)
1538 .make_trait_items(),
1539 _
=> unreachable
!(),
1542 _
=> noop_flat_map_assoc_item(item
, self),
1546 fn flat_map_impl_item(&mut self, item
: P
<ast
::AssocItem
>) -> SmallVec
<[P
<ast
::AssocItem
>; 1]> {
1547 let mut item
= configure
!(self, item
);
1549 let (attr
, traits
, after_derive
) = self.classify_item(&mut item
);
1550 if attr
.is_some() || !traits
.is_empty() {
1555 Annotatable
::ImplItem(item
),
1556 AstFragmentKind
::ImplItems
,
1563 ast
::AssocItemKind
::MacCall(..) => {
1564 self.check_attributes(&item
.attrs
);
1565 item
.and_then(|item
| match item
.kind
{
1566 ast
::AssocItemKind
::MacCall(mac
) => self
1567 .collect_bang(mac
, item
.span
, AstFragmentKind
::ImplItems
)
1569 _
=> unreachable
!(),
1572 _
=> noop_flat_map_assoc_item(item
, self),
1576 fn visit_ty(&mut self, ty
: &mut P
<ast
::Ty
>) {
1578 ast
::TyKind
::MacCall(_
) => {}
1579 _
=> return noop_visit_ty(ty
, self),
1582 visit_clobber(ty
, |mut ty
| match mem
::replace(&mut ty
.kind
, ast
::TyKind
::Err
) {
1583 ast
::TyKind
::MacCall(mac
) => {
1584 self.collect_bang(mac
, ty
.span
, AstFragmentKind
::Ty
).make_ty()
1586 _
=> unreachable
!(),
1590 fn visit_foreign_mod(&mut self, foreign_mod
: &mut ast
::ForeignMod
) {
1591 self.cfg
.configure_foreign_mod(foreign_mod
);
1592 noop_visit_foreign_mod(foreign_mod
, self);
1595 fn flat_map_foreign_item(
1597 mut foreign_item
: P
<ast
::ForeignItem
>,
1598 ) -> SmallVec
<[P
<ast
::ForeignItem
>; 1]> {
1599 let (attr
, traits
, after_derive
) = self.classify_item(&mut foreign_item
);
1601 if attr
.is_some() || !traits
.is_empty() {
1606 Annotatable
::ForeignItem(foreign_item
),
1607 AstFragmentKind
::ForeignItems
,
1610 .make_foreign_items();
1613 match foreign_item
.kind
{
1614 ast
::ForeignItemKind
::MacCall(..) => {
1615 self.check_attributes(&foreign_item
.attrs
);
1616 foreign_item
.and_then(|item
| match item
.kind
{
1617 ast
::ForeignItemKind
::MacCall(mac
) => self
1618 .collect_bang(mac
, item
.span
, AstFragmentKind
::ForeignItems
)
1619 .make_foreign_items(),
1620 _
=> unreachable
!(),
1623 _
=> noop_flat_map_foreign_item(foreign_item
, self),
1627 fn visit_item_kind(&mut self, item
: &mut ast
::ItemKind
) {
1629 ast
::ItemKind
::MacroDef(..) => {}
1631 self.cfg
.configure_item_kind(item
);
1632 noop_visit_item_kind(item
, self);
1637 fn flat_map_generic_param(
1639 param
: ast
::GenericParam
,
1640 ) -> SmallVec
<[ast
::GenericParam
; 1]> {
1641 let mut param
= configure
!(self, param
);
1643 let (attr
, traits
, after_derive
) = self.classify_item(&mut param
);
1644 if attr
.is_some() || !traits
.is_empty() {
1649 Annotatable
::GenericParam(param
),
1650 AstFragmentKind
::GenericParams
,
1653 .make_generic_params();
1656 noop_flat_map_generic_param(param
, self)
1659 fn visit_attribute(&mut self, at
: &mut ast
::Attribute
) {
1660 // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
1661 // contents="file contents")]` attributes
1662 if !self.cx
.sess
.check_name(at
, sym
::doc
) {
1663 return noop_visit_attribute(at
, self);
1666 if let Some(list
) = at
.meta_item_list() {
1667 if !list
.iter().any(|it
| it
.has_name(sym
::include
)) {
1668 return noop_visit_attribute(at
, self);
1671 let mut items
= vec
![];
1673 for mut it
in list
{
1674 if !it
.has_name(sym
::include
) {
1676 noop_visit_meta_list_item(&mut it
, self);
1682 if let Some(file
) = it
.value_str() {
1683 let err_count
= self.cx
.sess
.parse_sess
.span_diagnostic
.err_count();
1684 self.check_attributes(slice
::from_ref(at
));
1685 if self.cx
.sess
.parse_sess
.span_diagnostic
.err_count() > err_count
{
1686 // avoid loading the file if they haven't enabled the feature
1687 return noop_visit_attribute(at
, self);
1690 let filename
= match self.cx
.resolve_path(&*file
.as_str(), it
.span()) {
1691 Ok(filename
) => filename
,
1698 match self.cx
.source_map().load_file(&filename
) {
1699 Ok(source_file
) => {
1700 let src
= source_file
1703 .expect("freshly loaded file should have a source");
1704 let src_interned
= Symbol
::intern(src
.as_str());
1706 let include_info
= vec
![
1707 ast
::NestedMetaItem
::MetaItem(attr
::mk_name_value_item_str(
1708 Ident
::with_dummy_span(sym
::file
),
1712 ast
::NestedMetaItem
::MetaItem(attr
::mk_name_value_item_str(
1713 Ident
::with_dummy_span(sym
::contents
),
1719 let include_ident
= Ident
::with_dummy_span(sym
::include
);
1720 let item
= attr
::mk_list_item(include_ident
, include_info
);
1721 items
.push(ast
::NestedMetaItem
::MetaItem(item
));
1725 it
.meta_item().and_then(|item
| item
.name_value_literal()).unwrap();
1727 if e
.kind() == ErrorKind
::InvalidData
{
1731 &format
!("{} wasn't a utf-8 file", filename
.display()),
1733 .span_label(lit
.span
, "contains invalid utf-8")
1736 let mut err
= self.cx
.struct_span_err(
1738 &format
!("couldn't read {}: {}", filename
.display(), e
),
1740 err
.span_label(lit
.span
, "couldn't read file");
1749 .struct_span_err(it
.span(), "expected path to external documentation");
1751 // Check if the user erroneously used `doc(include(...))` syntax.
1752 let literal
= it
.meta_item_list().and_then(|list
| {
1753 if list
.len() == 1 {
1754 list
[0].literal().map(|literal
| &literal
.kind
)
1760 let (path
, applicability
) = match &literal
{
1761 Some(LitKind
::Str(path
, ..)) => {
1762 (path
.to_string(), Applicability
::MachineApplicable
)
1764 _
=> (String
::from("<path>"), Applicability
::HasPlaceholders
),
1767 err
.span_suggestion(
1769 "provide a file path with `=`",
1770 format
!("include = \"{}\"", path
),
1778 let meta
= attr
::mk_list_item(Ident
::with_dummy_span(sym
::doc
), items
);
1779 *at
= ast
::Attribute
{
1780 kind
: ast
::AttrKind
::Normal(AttrItem
{
1782 args
: meta
.kind
.mac_args(meta
.span
),
1790 noop_visit_attribute(at
, self)
1794 fn visit_id(&mut self, id
: &mut ast
::NodeId
) {
1796 debug_assert_eq
!(*id
, ast
::DUMMY_NODE_ID
);
1797 *id
= self.cx
.resolver
.next_node_id()
1801 fn visit_fn_decl(&mut self, mut fn_decl
: &mut P
<ast
::FnDecl
>) {
1802 self.cfg
.configure_fn_decl(&mut fn_decl
);
1803 noop_visit_fn_decl(fn_decl
, self);
1807 pub struct ExpansionConfig
<'feat
> {
1808 pub crate_name
: String
,
1809 pub features
: Option
<&'feat Features
>,
1810 pub recursion_limit
: Limit
,
1811 pub trace_mac
: bool
,
1812 pub should_test
: bool
, // If false, strip `#[test]` nodes
1813 pub keep_macs
: bool
,
1814 pub span_debug
: bool
, // If true, use verbose debugging for `proc_macro::Span`
1815 pub proc_macro_backtrace
: bool
, // If true, show backtraces for proc-macro panics
1818 impl<'feat
> ExpansionConfig
<'feat
> {
1819 pub fn default(crate_name
: String
) -> ExpansionConfig
<'
static> {
1823 recursion_limit
: Limit
::new(1024),
1828 proc_macro_backtrace
: false,
1832 fn proc_macro_hygiene(&self) -> bool
{
1833 self.features
.map_or(false, |features
| features
.proc_macro_hygiene
)
1835 fn custom_inner_attributes(&self) -> bool
{
1836 self.features
.map_or(false, |features
| features
.custom_inner_attributes
)