1 use crate::expand
::{self, AstFragment, Invocation}
;
2 use crate::module
::DirectoryOwnership
;
4 use rustc_ast
::ast
::{self, Attribute, Name, NodeId, PatKind}
;
5 use rustc_ast
::mut_visit
::{self, MutVisitor}
;
8 use rustc_ast
::tokenstream
::{self, TokenStream, TokenTree}
;
9 use rustc_ast
::visit
::{AssocCtxt, Visitor}
;
10 use rustc_attr
::{self as attr, Deprecation, HasAttrs, Stability}
;
11 use rustc_data_structures
::fx
::FxHashMap
;
12 use rustc_data_structures
::sync
::{self, Lrc}
;
13 use rustc_errors
::{DiagnosticBuilder, ErrorReported}
;
14 use rustc_parse
::{self, parser, MACRO_ARGUMENTS}
;
15 use rustc_session
::parse
::ParseSess
;
16 use rustc_span
::edition
::Edition
;
17 use rustc_span
::hygiene
::{AstPass, ExpnData, ExpnId, ExpnKind}
;
18 use rustc_span
::source_map
::SourceMap
;
19 use rustc_span
::symbol
::{kw, sym, Ident, Symbol}
;
20 use rustc_span
::{FileName, MultiSpan, Span, DUMMY_SP}
;
21 use smallvec
::{smallvec, SmallVec}
;
23 use std
::default::Default
;
25 use std
::path
::PathBuf
;
28 crate use rustc_span
::hygiene
::MacroKind
;
30 #[derive(Debug, Clone)]
31 pub enum Annotatable
{
33 TraitItem(P
<ast
::AssocItem
>),
34 ImplItem(P
<ast
::AssocItem
>),
35 ForeignItem(P
<ast
::ForeignItem
>),
40 FieldPat(ast
::FieldPat
),
41 GenericParam(ast
::GenericParam
),
43 StructField(ast
::StructField
),
44 Variant(ast
::Variant
),
47 impl HasAttrs
for Annotatable
{
48 fn attrs(&self) -> &[Attribute
] {
50 Annotatable
::Item(ref item
) => &item
.attrs
,
51 Annotatable
::TraitItem(ref trait_item
) => &trait_item
.attrs
,
52 Annotatable
::ImplItem(ref impl_item
) => &impl_item
.attrs
,
53 Annotatable
::ForeignItem(ref foreign_item
) => &foreign_item
.attrs
,
54 Annotatable
::Stmt(ref stmt
) => stmt
.attrs(),
55 Annotatable
::Expr(ref expr
) => &expr
.attrs
,
56 Annotatable
::Arm(ref arm
) => &arm
.attrs
,
57 Annotatable
::Field(ref field
) => &field
.attrs
,
58 Annotatable
::FieldPat(ref fp
) => &fp
.attrs
,
59 Annotatable
::GenericParam(ref gp
) => &gp
.attrs
,
60 Annotatable
::Param(ref p
) => &p
.attrs
,
61 Annotatable
::StructField(ref sf
) => &sf
.attrs
,
62 Annotatable
::Variant(ref v
) => &v
.attrs(),
66 fn visit_attrs(&mut self, f
: impl FnOnce(&mut Vec
<Attribute
>)) {
68 Annotatable
::Item(item
) => item
.visit_attrs(f
),
69 Annotatable
::TraitItem(trait_item
) => trait_item
.visit_attrs(f
),
70 Annotatable
::ImplItem(impl_item
) => impl_item
.visit_attrs(f
),
71 Annotatable
::ForeignItem(foreign_item
) => foreign_item
.visit_attrs(f
),
72 Annotatable
::Stmt(stmt
) => stmt
.visit_attrs(f
),
73 Annotatable
::Expr(expr
) => expr
.visit_attrs(f
),
74 Annotatable
::Arm(arm
) => arm
.visit_attrs(f
),
75 Annotatable
::Field(field
) => field
.visit_attrs(f
),
76 Annotatable
::FieldPat(fp
) => fp
.visit_attrs(f
),
77 Annotatable
::GenericParam(gp
) => gp
.visit_attrs(f
),
78 Annotatable
::Param(p
) => p
.visit_attrs(f
),
79 Annotatable
::StructField(sf
) => sf
.visit_attrs(f
),
80 Annotatable
::Variant(v
) => v
.visit_attrs(f
),
86 pub fn span(&self) -> Span
{
88 Annotatable
::Item(ref item
) => item
.span
,
89 Annotatable
::TraitItem(ref trait_item
) => trait_item
.span
,
90 Annotatable
::ImplItem(ref impl_item
) => impl_item
.span
,
91 Annotatable
::ForeignItem(ref foreign_item
) => foreign_item
.span
,
92 Annotatable
::Stmt(ref stmt
) => stmt
.span
,
93 Annotatable
::Expr(ref expr
) => expr
.span
,
94 Annotatable
::Arm(ref arm
) => arm
.span
,
95 Annotatable
::Field(ref field
) => field
.span
,
96 Annotatable
::FieldPat(ref fp
) => fp
.pat
.span
,
97 Annotatable
::GenericParam(ref gp
) => gp
.ident
.span
,
98 Annotatable
::Param(ref p
) => p
.span
,
99 Annotatable
::StructField(ref sf
) => sf
.span
,
100 Annotatable
::Variant(ref v
) => v
.span
,
104 pub fn visit_with
<'a
, V
: Visitor
<'a
>>(&'a
self, visitor
: &mut V
) {
106 Annotatable
::Item(item
) => visitor
.visit_item(item
),
107 Annotatable
::TraitItem(item
) => visitor
.visit_assoc_item(item
, AssocCtxt
::Trait
),
108 Annotatable
::ImplItem(item
) => visitor
.visit_assoc_item(item
, AssocCtxt
::Impl
),
109 Annotatable
::ForeignItem(foreign_item
) => visitor
.visit_foreign_item(foreign_item
),
110 Annotatable
::Stmt(stmt
) => visitor
.visit_stmt(stmt
),
111 Annotatable
::Expr(expr
) => visitor
.visit_expr(expr
),
112 Annotatable
::Arm(arm
) => visitor
.visit_arm(arm
),
113 Annotatable
::Field(field
) => visitor
.visit_field(field
),
114 Annotatable
::FieldPat(fp
) => visitor
.visit_field_pattern(fp
),
115 Annotatable
::GenericParam(gp
) => visitor
.visit_generic_param(gp
),
116 Annotatable
::Param(p
) => visitor
.visit_param(p
),
117 Annotatable
::StructField(sf
) => visitor
.visit_struct_field(sf
),
118 Annotatable
::Variant(v
) => visitor
.visit_variant(v
),
122 crate fn into_tokens(self) -> TokenStream
{
123 // `Annotatable` can be converted into tokens directly, but we
124 // are packing it into a nonterminal as a piece of AST to make
125 // the produced token stream look nicer in pretty-printed form.
126 let nt
= match self {
127 Annotatable
::Item(item
) => token
::NtItem(item
),
128 Annotatable
::TraitItem(item
) | Annotatable
::ImplItem(item
) => {
129 token
::NtItem(P(item
.and_then(ast
::AssocItem
::into_item
)))
131 Annotatable
::ForeignItem(item
) => {
132 token
::NtItem(P(item
.and_then(ast
::ForeignItem
::into_item
)))
134 Annotatable
::Stmt(stmt
) => token
::NtStmt(stmt
.into_inner()),
135 Annotatable
::Expr(expr
) => token
::NtExpr(expr
),
137 | Annotatable
::Field(..)
138 | Annotatable
::FieldPat(..)
139 | Annotatable
::GenericParam(..)
140 | Annotatable
::Param(..)
141 | Annotatable
::StructField(..)
142 | Annotatable
::Variant(..) => panic
!("unexpected annotatable"),
144 TokenTree
::token(token
::Interpolated(Lrc
::new(nt
)), DUMMY_SP
).into()
147 pub fn expect_item(self) -> P
<ast
::Item
> {
149 Annotatable
::Item(i
) => i
,
150 _
=> panic
!("expected Item"),
154 pub fn map_item_or
<F
, G
>(self, mut f
: F
, mut or
: G
) -> Annotatable
156 F
: FnMut(P
<ast
::Item
>) -> P
<ast
::Item
>,
157 G
: FnMut(Annotatable
) -> Annotatable
,
160 Annotatable
::Item(i
) => Annotatable
::Item(f(i
)),
165 pub fn expect_trait_item(self) -> P
<ast
::AssocItem
> {
167 Annotatable
::TraitItem(i
) => i
,
168 _
=> panic
!("expected Item"),
172 pub fn expect_impl_item(self) -> P
<ast
::AssocItem
> {
174 Annotatable
::ImplItem(i
) => i
,
175 _
=> panic
!("expected Item"),
179 pub fn expect_foreign_item(self) -> P
<ast
::ForeignItem
> {
181 Annotatable
::ForeignItem(i
) => i
,
182 _
=> panic
!("expected foreign item"),
186 pub fn expect_stmt(self) -> ast
::Stmt
{
188 Annotatable
::Stmt(stmt
) => stmt
.into_inner(),
189 _
=> panic
!("expected statement"),
193 pub fn expect_expr(self) -> P
<ast
::Expr
> {
195 Annotatable
::Expr(expr
) => expr
,
196 _
=> panic
!("expected expression"),
200 pub fn expect_arm(self) -> ast
::Arm
{
202 Annotatable
::Arm(arm
) => arm
,
203 _
=> panic
!("expected match arm"),
207 pub fn expect_field(self) -> ast
::Field
{
209 Annotatable
::Field(field
) => field
,
210 _
=> panic
!("expected field"),
214 pub fn expect_field_pattern(self) -> ast
::FieldPat
{
216 Annotatable
::FieldPat(fp
) => fp
,
217 _
=> panic
!("expected field pattern"),
221 pub fn expect_generic_param(self) -> ast
::GenericParam
{
223 Annotatable
::GenericParam(gp
) => gp
,
224 _
=> panic
!("expected generic parameter"),
228 pub fn expect_param(self) -> ast
::Param
{
230 Annotatable
::Param(param
) => param
,
231 _
=> panic
!("expected parameter"),
235 pub fn expect_struct_field(self) -> ast
::StructField
{
237 Annotatable
::StructField(sf
) => sf
,
238 _
=> panic
!("expected struct field"),
242 pub fn expect_variant(self) -> ast
::Variant
{
244 Annotatable
::Variant(v
) => v
,
245 _
=> panic
!("expected variant"),
249 pub fn derive_allowed(&self) -> bool
{
251 Annotatable
::Item(ref item
) => match item
.kind
{
252 ast
::ItemKind
::Struct(..) | ast
::ItemKind
::Enum(..) | ast
::ItemKind
::Union(..) => {
262 /// Result of an expansion that may need to be retried.
263 /// Consider using this for non-`MultiItemModifier` expanders as well.
264 pub enum ExpandResult
<T
, U
> {
265 /// Expansion produced a result (possibly dummy).
267 /// Expansion could not produce a result and needs to be retried.
268 /// The string is an explanation that will be printed if we are stuck in an infinite retry loop.
272 // `meta_item` is the attribute, and `item` is the item being modified.
273 pub trait MultiItemModifier
{
276 ecx
: &mut ExtCtxt
<'_
>,
278 meta_item
: &ast
::MetaItem
,
280 ) -> ExpandResult
<Vec
<Annotatable
>, Annotatable
>;
283 impl<F
> MultiItemModifier
for F
285 F
: Fn(&mut ExtCtxt
<'_
>, Span
, &ast
::MetaItem
, Annotatable
) -> Vec
<Annotatable
>,
289 ecx
: &mut ExtCtxt
<'_
>,
291 meta_item
: &ast
::MetaItem
,
293 ) -> ExpandResult
<Vec
<Annotatable
>, Annotatable
> {
294 ExpandResult
::Ready(self(ecx
, span
, meta_item
, item
))
298 pub trait ProcMacro
{
301 ecx
: &'cx
mut ExtCtxt
<'_
>,
304 ) -> Result
<TokenStream
, ErrorReported
>;
307 impl<F
> ProcMacro
for F
309 F
: Fn(TokenStream
) -> TokenStream
,
313 _ecx
: &'cx
mut ExtCtxt
<'_
>,
316 ) -> Result
<TokenStream
, ErrorReported
> {
317 // FIXME setup implicit context in TLS before calling self.
322 pub trait AttrProcMacro
{
325 ecx
: &'cx
mut ExtCtxt
<'_
>,
327 annotation
: TokenStream
,
328 annotated
: TokenStream
,
329 ) -> Result
<TokenStream
, ErrorReported
>;
332 impl<F
> AttrProcMacro
for F
334 F
: Fn(TokenStream
, TokenStream
) -> TokenStream
,
338 _ecx
: &'cx
mut ExtCtxt
<'_
>,
340 annotation
: TokenStream
,
341 annotated
: TokenStream
,
342 ) -> Result
<TokenStream
, ErrorReported
> {
343 // FIXME setup implicit context in TLS before calling self.
344 Ok((*self)(annotation
, annotated
))
348 /// Represents a thing that maps token trees to Macro Results
349 pub trait TTMacroExpander
{
352 ecx
: &'cx
mut ExtCtxt
<'_
>,
355 ) -> Box
<dyn MacResult
+ 'cx
>;
358 pub type MacroExpanderFn
=
359 for<'cx
> fn(&'cx
mut ExtCtxt
<'_
>, Span
, TokenStream
) -> Box
<dyn MacResult
+ 'cx
>;
361 impl<F
> TTMacroExpander
for F
363 F
: for<'cx
> Fn(&'cx
mut ExtCtxt
<'_
>, Span
, TokenStream
) -> Box
<dyn MacResult
+ 'cx
>,
367 ecx
: &'cx
mut ExtCtxt
<'_
>,
369 mut input
: TokenStream
,
370 ) -> Box
<dyn MacResult
+ 'cx
> {
371 struct AvoidInterpolatedIdents
;
373 impl MutVisitor
for AvoidInterpolatedIdents
{
374 fn visit_tt(&mut self, tt
: &mut tokenstream
::TokenTree
) {
375 if let tokenstream
::TokenTree
::Token(token
) = tt
{
376 if let token
::Interpolated(nt
) = &token
.kind
{
377 if let token
::NtIdent(ident
, is_raw
) = **nt
{
378 *tt
= tokenstream
::TokenTree
::token(
379 token
::Ident(ident
.name
, is_raw
),
385 mut_visit
::noop_visit_tt(tt
, self)
388 fn visit_mac(&mut self, mac
: &mut ast
::MacCall
) {
389 mut_visit
::noop_visit_mac(mac
, self)
392 AvoidInterpolatedIdents
.visit_tts(&mut input
);
393 (*self)(ecx
, span
, input
)
397 // Use a macro because forwarding to a simple function has type system issues
398 macro_rules
! make_stmts_default
{
400 $me
.make_expr().map(|e
| {
401 smallvec
![ast
::Stmt
{
402 id
: ast
::DUMMY_NODE_ID
,
404 kind
: ast
::StmtKind
::Expr(e
),
410 /// The result of a macro expansion. The return values of the various
411 /// methods are spliced into the AST at the callsite of the macro.
412 pub trait MacResult
{
413 /// Creates an expression.
414 fn make_expr(self: Box
<Self>) -> Option
<P
<ast
::Expr
>> {
417 /// Creates zero or more items.
418 fn make_items(self: Box
<Self>) -> Option
<SmallVec
<[P
<ast
::Item
>; 1]>> {
422 /// Creates zero or more impl items.
423 fn make_impl_items(self: Box
<Self>) -> Option
<SmallVec
<[P
<ast
::AssocItem
>; 1]>> {
427 /// Creates zero or more trait items.
428 fn make_trait_items(self: Box
<Self>) -> Option
<SmallVec
<[P
<ast
::AssocItem
>; 1]>> {
432 /// Creates zero or more items in an `extern {}` block
433 fn make_foreign_items(self: Box
<Self>) -> Option
<SmallVec
<[P
<ast
::ForeignItem
>; 1]>> {
437 /// Creates a pattern.
438 fn make_pat(self: Box
<Self>) -> Option
<P
<ast
::Pat
>> {
442 /// Creates zero or more statements.
444 /// By default this attempts to create an expression statement,
445 /// returning None if that fails.
446 fn make_stmts(self: Box
<Self>) -> Option
<SmallVec
<[ast
::Stmt
; 1]>> {
447 make_stmts_default
!(self)
450 fn make_ty(self: Box
<Self>) -> Option
<P
<ast
::Ty
>> {
454 fn make_arms(self: Box
<Self>) -> Option
<SmallVec
<[ast
::Arm
; 1]>> {
458 fn make_fields(self: Box
<Self>) -> Option
<SmallVec
<[ast
::Field
; 1]>> {
462 fn make_field_patterns(self: Box
<Self>) -> Option
<SmallVec
<[ast
::FieldPat
; 1]>> {
466 fn make_generic_params(self: Box
<Self>) -> Option
<SmallVec
<[ast
::GenericParam
; 1]>> {
470 fn make_params(self: Box
<Self>) -> Option
<SmallVec
<[ast
::Param
; 1]>> {
474 fn make_struct_fields(self: Box
<Self>) -> Option
<SmallVec
<[ast
::StructField
; 1]>> {
478 fn make_variants(self: Box
<Self>) -> Option
<SmallVec
<[ast
::Variant
; 1]>> {
483 macro_rules
! make_MacEager
{
484 ( $
( $fld
:ident
: $t
:ty
, )* ) => {
485 /// `MacResult` implementation for the common case where you've already
486 /// built each form of AST that you might return.
488 pub struct MacEager
{
490 pub $fld
: Option
<$t
>,
496 pub fn $
fld(v
: $t
) -> Box
<dyn MacResult
> {
510 items
: SmallVec
<[P
<ast
::Item
>; 1]>,
511 impl_items
: SmallVec
<[P
<ast
::AssocItem
>; 1]>,
512 trait_items
: SmallVec
<[P
<ast
::AssocItem
>; 1]>,
513 foreign_items
: SmallVec
<[P
<ast
::ForeignItem
>; 1]>,
514 stmts
: SmallVec
<[ast
::Stmt
; 1]>,
518 impl MacResult
for MacEager
{
519 fn make_expr(self: Box
<Self>) -> Option
<P
<ast
::Expr
>> {
523 fn make_items(self: Box
<Self>) -> Option
<SmallVec
<[P
<ast
::Item
>; 1]>> {
527 fn make_impl_items(self: Box
<Self>) -> Option
<SmallVec
<[P
<ast
::AssocItem
>; 1]>> {
531 fn make_trait_items(self: Box
<Self>) -> Option
<SmallVec
<[P
<ast
::AssocItem
>; 1]>> {
535 fn make_foreign_items(self: Box
<Self>) -> Option
<SmallVec
<[P
<ast
::ForeignItem
>; 1]>> {
539 fn make_stmts(self: Box
<Self>) -> Option
<SmallVec
<[ast
::Stmt
; 1]>> {
540 match self.stmts
.as_ref().map_or(0, |s
| s
.len()) {
541 0 => make_stmts_default
!(self),
546 fn make_pat(self: Box
<Self>) -> Option
<P
<ast
::Pat
>> {
547 if let Some(p
) = self.pat
{
550 if let Some(e
) = self.expr
{
551 if let ast
::ExprKind
::Lit(_
) = e
.kind
{
552 return Some(P(ast
::Pat
{
553 id
: ast
::DUMMY_NODE_ID
,
555 kind
: PatKind
::Lit(e
),
562 fn make_ty(self: Box
<Self>) -> Option
<P
<ast
::Ty
>> {
567 /// Fill-in macro expansion result, to allow compilation to continue
568 /// after hitting errors.
569 #[derive(Copy, Clone)]
570 pub struct DummyResult
{
576 /// Creates a default MacResult that can be anything.
578 /// Use this as a return value after hitting any errors and
579 /// calling `span_err`.
580 pub fn any(span
: Span
) -> Box
<dyn MacResult
+ '
static> {
581 Box
::new(DummyResult { is_error: true, span }
)
584 /// Same as `any`, but must be a valid fragment, not error.
585 pub fn any_valid(span
: Span
) -> Box
<dyn MacResult
+ '
static> {
586 Box
::new(DummyResult { is_error: false, span }
)
589 /// A plain dummy expression.
590 pub fn raw_expr(sp
: Span
, is_error
: bool
) -> P
<ast
::Expr
> {
592 id
: ast
::DUMMY_NODE_ID
,
593 kind
: if is_error { ast::ExprKind::Err }
else { ast::ExprKind::Tup(Vec::new()) }
,
595 attrs
: ast
::AttrVec
::new(),
599 /// A plain dummy pattern.
600 pub fn raw_pat(sp
: Span
) -> ast
::Pat
{
601 ast
::Pat { id: ast::DUMMY_NODE_ID, kind: PatKind::Wild, span: sp }
604 /// A plain dummy type.
605 pub fn raw_ty(sp
: Span
, is_error
: bool
) -> P
<ast
::Ty
> {
607 id
: ast
::DUMMY_NODE_ID
,
608 kind
: if is_error { ast::TyKind::Err }
else { ast::TyKind::Tup(Vec::new()) }
,
614 impl MacResult
for DummyResult
{
615 fn make_expr(self: Box
<DummyResult
>) -> Option
<P
<ast
::Expr
>> {
616 Some(DummyResult
::raw_expr(self.span
, self.is_error
))
619 fn make_pat(self: Box
<DummyResult
>) -> Option
<P
<ast
::Pat
>> {
620 Some(P(DummyResult
::raw_pat(self.span
)))
623 fn make_items(self: Box
<DummyResult
>) -> Option
<SmallVec
<[P
<ast
::Item
>; 1]>> {
624 Some(SmallVec
::new())
627 fn make_impl_items(self: Box
<DummyResult
>) -> Option
<SmallVec
<[P
<ast
::AssocItem
>; 1]>> {
628 Some(SmallVec
::new())
631 fn make_trait_items(self: Box
<DummyResult
>) -> Option
<SmallVec
<[P
<ast
::AssocItem
>; 1]>> {
632 Some(SmallVec
::new())
635 fn make_foreign_items(self: Box
<Self>) -> Option
<SmallVec
<[P
<ast
::ForeignItem
>; 1]>> {
636 Some(SmallVec
::new())
639 fn make_stmts(self: Box
<DummyResult
>) -> Option
<SmallVec
<[ast
::Stmt
; 1]>> {
640 Some(smallvec
![ast
::Stmt
{
641 id
: ast
::DUMMY_NODE_ID
,
642 kind
: ast
::StmtKind
::Expr(DummyResult
::raw_expr(self.span
, self.is_error
)),
647 fn make_ty(self: Box
<DummyResult
>) -> Option
<P
<ast
::Ty
>> {
648 Some(DummyResult
::raw_ty(self.span
, self.is_error
))
651 fn make_arms(self: Box
<DummyResult
>) -> Option
<SmallVec
<[ast
::Arm
; 1]>> {
652 Some(SmallVec
::new())
655 fn make_fields(self: Box
<DummyResult
>) -> Option
<SmallVec
<[ast
::Field
; 1]>> {
656 Some(SmallVec
::new())
659 fn make_field_patterns(self: Box
<DummyResult
>) -> Option
<SmallVec
<[ast
::FieldPat
; 1]>> {
660 Some(SmallVec
::new())
663 fn make_generic_params(self: Box
<DummyResult
>) -> Option
<SmallVec
<[ast
::GenericParam
; 1]>> {
664 Some(SmallVec
::new())
667 fn make_params(self: Box
<DummyResult
>) -> Option
<SmallVec
<[ast
::Param
; 1]>> {
668 Some(SmallVec
::new())
671 fn make_struct_fields(self: Box
<DummyResult
>) -> Option
<SmallVec
<[ast
::StructField
; 1]>> {
672 Some(SmallVec
::new())
675 fn make_variants(self: Box
<DummyResult
>) -> Option
<SmallVec
<[ast
::Variant
; 1]>> {
676 Some(SmallVec
::new())
680 /// A syntax extension kind.
681 pub enum SyntaxExtensionKind
{
682 /// A token-based function-like macro.
684 /// An expander with signature TokenStream -> TokenStream.
685 Box
<dyn ProcMacro
+ sync
::Sync
+ sync
::Send
>,
688 /// An AST-based function-like macro.
690 /// An expander with signature TokenStream -> AST.
691 Box
<dyn TTMacroExpander
+ sync
::Sync
+ sync
::Send
>,
694 /// A token-based attribute macro.
696 /// An expander with signature (TokenStream, TokenStream) -> TokenStream.
697 /// The first TokenSteam is the attribute itself, the second is the annotated item.
698 /// The produced TokenSteam replaces the input TokenSteam.
699 Box
<dyn AttrProcMacro
+ sync
::Sync
+ sync
::Send
>,
702 /// An AST-based attribute macro.
704 /// An expander with signature (AST, AST) -> AST.
705 /// The first AST fragment is the attribute itself, the second is the annotated item.
706 /// The produced AST fragment replaces the input AST fragment.
707 Box
<dyn MultiItemModifier
+ sync
::Sync
+ sync
::Send
>,
710 /// A trivial attribute "macro" that does nothing,
711 /// only keeps the attribute and marks it as inert,
712 /// thus making it ineligible for further expansion.
714 /// Suppresses the `unused_attributes` lint for this attribute.
718 /// A token-based derive macro.
720 /// An expander with signature TokenStream -> TokenStream (not yet).
721 /// The produced TokenSteam is appended to the input TokenSteam.
722 Box
<dyn MultiItemModifier
+ sync
::Sync
+ sync
::Send
>,
725 /// An AST-based derive macro.
727 /// An expander with signature AST -> AST.
728 /// The produced AST fragment is appended to the input AST fragment.
729 Box
<dyn MultiItemModifier
+ sync
::Sync
+ sync
::Send
>,
733 /// A struct representing a macro definition in "lowered" form ready for expansion.
734 pub struct SyntaxExtension
{
735 /// A syntax extension kind.
736 pub kind
: SyntaxExtensionKind
,
737 /// Span of the macro definition.
739 /// Whitelist of unstable features that are treated as stable inside this macro.
740 pub allow_internal_unstable
: Option
<Lrc
<[Symbol
]>>,
741 /// Suppresses the `unsafe_code` lint for code produced by this macro.
742 pub allow_internal_unsafe
: bool
,
743 /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
744 pub local_inner_macros
: bool
,
745 /// The macro's stability info.
746 pub stability
: Option
<Stability
>,
747 /// The macro's deprecation info.
748 pub deprecation
: Option
<Deprecation
>,
749 /// Names of helper attributes registered by this macro.
750 pub helper_attrs
: Vec
<Symbol
>,
751 /// Edition of the crate in which this macro is defined.
752 pub edition
: Edition
,
753 /// Built-in macros have a couple of special properties like availability
754 /// in `#[no_implicit_prelude]` modules, so we have to keep this flag.
755 pub is_builtin
: bool
,
756 /// We have to identify macros providing a `Copy` impl early for compatibility reasons.
757 pub is_derive_copy
: bool
,
760 impl SyntaxExtension
{
761 /// Returns which kind of macro calls this syntax extension.
762 pub fn macro_kind(&self) -> MacroKind
{
764 SyntaxExtensionKind
::Bang(..) | SyntaxExtensionKind
::LegacyBang(..) => MacroKind
::Bang
,
765 SyntaxExtensionKind
::Attr(..)
766 | SyntaxExtensionKind
::LegacyAttr(..)
767 | SyntaxExtensionKind
::NonMacroAttr { .. }
=> MacroKind
::Attr
,
768 SyntaxExtensionKind
::Derive(..) | SyntaxExtensionKind
::LegacyDerive(..) => {
774 /// Constructs a syntax extension with default properties.
775 pub fn default(kind
: SyntaxExtensionKind
, edition
: Edition
) -> SyntaxExtension
{
778 allow_internal_unstable
: None
,
779 allow_internal_unsafe
: false,
780 local_inner_macros
: false,
783 helper_attrs
: Vec
::new(),
786 is_derive_copy
: false,
791 /// Constructs a syntax extension with the given properties
792 /// and other properties converted from attributes.
795 kind
: SyntaxExtensionKind
,
797 helper_attrs
: Vec
<Symbol
>,
800 attrs
: &[ast
::Attribute
],
801 ) -> SyntaxExtension
{
802 let allow_internal_unstable
= attr
::allow_internal_unstable(&attrs
, &sess
.span_diagnostic
)
803 .map(|features
| features
.collect
::<Vec
<Symbol
>>().into());
805 let mut local_inner_macros
= false;
806 if let Some(macro_export
) = attr
::find_by_name(attrs
, sym
::macro_export
) {
807 if let Some(l
) = macro_export
.meta_item_list() {
808 local_inner_macros
= attr
::list_contains_name(&l
, sym
::local_inner_macros
);
812 let is_builtin
= attr
::contains_name(attrs
, sym
::rustc_builtin_macro
);
813 let (stability
, const_stability
) = attr
::find_stability(&sess
, attrs
, span
);
814 if const_stability
.is_some() {
815 sess
.span_diagnostic
.span_err(span
, "macros cannot have const stability attributes");
821 allow_internal_unstable
,
822 allow_internal_unsafe
: attr
::contains_name(attrs
, sym
::allow_internal_unsafe
),
825 deprecation
: attr
::find_deprecation(&sess
, attrs
, span
),
829 is_derive_copy
: is_builtin
&& name
== sym
::Copy
,
833 pub fn dummy_bang(edition
: Edition
) -> SyntaxExtension
{
835 _
: &'cx
mut ExtCtxt
<'_
>,
838 ) -> Box
<dyn MacResult
+ 'cx
> {
839 DummyResult
::any(span
)
841 SyntaxExtension
::default(SyntaxExtensionKind
::LegacyBang(Box
::new(expander
)), edition
)
844 pub fn dummy_derive(edition
: Edition
) -> SyntaxExtension
{
850 ) -> Vec
<Annotatable
> {
853 SyntaxExtension
::default(SyntaxExtensionKind
::Derive(Box
::new(expander
)), edition
)
856 pub fn non_macro_attr(mark_used
: bool
, edition
: Edition
) -> SyntaxExtension
{
857 SyntaxExtension
::default(SyntaxExtensionKind
::NonMacroAttr { mark_used }
, edition
)
860 pub fn expn_data(&self, parent
: ExpnId
, call_site
: Span
, descr
: Symbol
) -> ExpnData
{
862 kind
: ExpnKind
::Macro(self.macro_kind(), descr
),
866 allow_internal_unstable
: self.allow_internal_unstable
.clone(),
867 allow_internal_unsafe
: self.allow_internal_unsafe
,
868 local_inner_macros
: self.local_inner_macros
,
869 edition
: self.edition
,
874 /// Result of resolving a macro invocation.
875 pub enum InvocationRes
{
876 Single(Lrc
<SyntaxExtension
>),
877 DeriveContainer(Vec
<Lrc
<SyntaxExtension
>>),
880 /// Error type that denotes indeterminacy.
881 pub struct Indeterminate
;
884 fn next_node_id(&mut self) -> NodeId
;
886 fn resolve_dollar_crates(&mut self);
887 fn visit_ast_fragment_with_placeholders(&mut self, expn_id
: ExpnId
, fragment
: &AstFragment
);
888 fn register_builtin_macro(&mut self, ident
: ast
::Ident
, ext
: SyntaxExtension
);
890 fn expansion_for_ast_pass(
895 parent_module_id
: Option
<NodeId
>,
898 fn resolve_imports(&mut self);
900 fn resolve_macro_invocation(
903 eager_expansion_root
: ExpnId
,
905 ) -> Result
<InvocationRes
, Indeterminate
>;
907 fn check_unused_macros(&mut self);
909 fn has_derive_copy(&self, expn_id
: ExpnId
) -> bool
;
910 fn add_derive_copy(&mut self, expn_id
: ExpnId
);
911 fn cfg_accessible(&mut self, expn_id
: ExpnId
, path
: &ast
::Path
) -> Result
<bool
, Indeterminate
>;
915 pub struct ModuleData
{
916 pub mod_path
: Vec
<ast
::Ident
>,
917 pub directory
: PathBuf
,
921 pub struct ExpansionData
{
924 pub module
: Rc
<ModuleData
>,
925 pub directory_ownership
: DirectoryOwnership
,
926 pub prior_type_ascription
: Option
<(Span
, bool
)>,
929 /// One of these is made during expansion and incrementally updated as we go;
930 /// when a macro expansion occurs, the resulting nodes have the `backtrace()
931 /// -> expn_data` of their expansion context stored into their span.
932 pub struct ExtCtxt
<'a
> {
933 pub parse_sess
: &'a ParseSess
,
934 pub ecfg
: expand
::ExpansionConfig
<'a
>,
935 pub reduced_recursion_limit
: Option
<usize>,
936 pub root_path
: PathBuf
,
937 pub resolver
: &'a
mut dyn Resolver
,
938 pub current_expansion
: ExpansionData
,
939 pub expansions
: FxHashMap
<Span
, Vec
<String
>>,
940 /// Called directly after having parsed an external `mod foo;` in expansion.
941 pub(super) extern_mod_loaded
: Option
<&'a
dyn Fn(&ast
::Crate
)>,
944 impl<'a
> ExtCtxt
<'a
> {
946 parse_sess
: &'a ParseSess
,
947 ecfg
: expand
::ExpansionConfig
<'a
>,
948 resolver
: &'a
mut dyn Resolver
,
949 extern_mod_loaded
: Option
<&'a
dyn Fn(&ast
::Crate
)>,
954 reduced_recursion_limit
: None
,
957 root_path
: PathBuf
::new(),
958 current_expansion
: ExpansionData
{
961 module
: Rc
::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }
),
962 directory_ownership
: DirectoryOwnership
::Owned { relative: None }
,
963 prior_type_ascription
: None
,
965 expansions
: FxHashMap
::default(),
969 /// Returns a `Folder` for deeply expanding all macros in an AST node.
970 pub fn expander
<'b
>(&'b
mut self) -> expand
::MacroExpander
<'b
, 'a
> {
971 expand
::MacroExpander
::new(self, false)
974 /// Returns a `Folder` that deeply expands all macros and assigns all `NodeId`s in an AST node.
975 /// Once `NodeId`s are assigned, the node may not be expanded, removed, or otherwise modified.
976 pub fn monotonic_expander
<'b
>(&'b
mut self) -> expand
::MacroExpander
<'b
, 'a
> {
977 expand
::MacroExpander
::new(self, true)
979 pub fn new_parser_from_tts(&self, stream
: TokenStream
) -> parser
::Parser
<'a
> {
980 rustc_parse
::stream_to_parser(self.parse_sess
, stream
, MACRO_ARGUMENTS
)
982 pub fn source_map(&self) -> &'a SourceMap
{
983 self.parse_sess
.source_map()
985 pub fn parse_sess(&self) -> &'a ParseSess
{
988 pub fn call_site(&self) -> Span
{
989 self.current_expansion
.id
.expn_data().call_site
992 /// Equivalent of `Span::def_site` from the proc macro API,
993 /// except that the location is taken from the span passed as an argument.
994 pub fn with_def_site_ctxt(&self, span
: Span
) -> Span
{
995 span
.with_def_site_ctxt(self.current_expansion
.id
)
998 /// Equivalent of `Span::call_site` from the proc macro API,
999 /// except that the location is taken from the span passed as an argument.
1000 pub fn with_call_site_ctxt(&self, span
: Span
) -> Span
{
1001 span
.with_call_site_ctxt(self.current_expansion
.id
)
1004 /// Equivalent of `Span::mixed_site` from the proc macro API,
1005 /// except that the location is taken from the span passed as an argument.
1006 pub fn with_mixed_site_ctxt(&self, span
: Span
) -> Span
{
1007 span
.with_mixed_site_ctxt(self.current_expansion
.id
)
1010 /// Returns span for the macro which originally caused the current expansion to happen.
1012 /// Stops backtracing at include! boundary.
1013 pub fn expansion_cause(&self) -> Option
<Span
> {
1014 self.current_expansion
.id
.expansion_cause()
1017 pub fn struct_span_err
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) -> DiagnosticBuilder
<'a
> {
1018 self.parse_sess
.span_diagnostic
.struct_span_err(sp
, msg
)
1021 /// Emit `msg` attached to `sp`, without immediately stopping
1024 /// Compilation will be stopped in the near future (at the end of
1025 /// the macro expansion phase).
1026 pub fn span_err
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) {
1027 self.parse_sess
.span_diagnostic
.span_err(sp
, msg
);
1029 pub fn span_warn
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) {
1030 self.parse_sess
.span_diagnostic
.span_warn(sp
, msg
);
1032 pub fn span_bug
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) -> ! {
1033 self.parse_sess
.span_diagnostic
.span_bug(sp
, msg
);
1035 pub fn trace_macros_diag(&mut self) {
1036 for (sp
, notes
) in self.expansions
.iter() {
1037 let mut db
= self.parse_sess
.span_diagnostic
.span_note_diag(*sp
, "trace_macro");
1043 // Fixme: does this result in errors?
1044 self.expansions
.clear();
1046 pub fn bug(&self, msg
: &str) -> ! {
1047 self.parse_sess
.span_diagnostic
.bug(msg
);
1049 pub fn trace_macros(&self) -> bool
{
1052 pub fn set_trace_macros(&mut self, x
: bool
) {
1053 self.ecfg
.trace_mac
= x
1055 pub fn ident_of(&self, st
: &str, sp
: Span
) -> ast
::Ident
{
1056 ast
::Ident
::from_str_and_span(st
, sp
)
1058 pub fn std_path(&self, components
: &[Symbol
]) -> Vec
<ast
::Ident
> {
1059 let def_site
= self.with_def_site_ctxt(DUMMY_SP
);
1060 iter
::once(Ident
::new(kw
::DollarCrate
, def_site
))
1061 .chain(components
.iter().map(|&s
| Ident
::with_dummy_span(s
)))
1064 pub fn name_of(&self, st
: &str) -> ast
::Name
{
1068 pub fn check_unused_macros(&mut self) {
1069 self.resolver
.check_unused_macros();
1072 /// Resolves a path mentioned inside Rust code.
1074 /// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
1076 /// Returns an absolute path to the file that `path` refers to.
1077 pub fn resolve_path(
1079 path
: impl Into
<PathBuf
>,
1081 ) -> Result
<PathBuf
, DiagnosticBuilder
<'a
>> {
1082 let path
= path
.into();
1084 // Relative paths are resolved relative to the file in which they are found
1085 // after macro expansion (that is, they are unhygienic).
1086 if !path
.is_absolute() {
1087 let callsite
= span
.source_callsite();
1088 let mut result
= match self.source_map().span_to_unmapped_path(callsite
) {
1089 FileName
::Real(name
) => name
.into_local_path(),
1090 FileName
::DocTest(path
, _
) => path
,
1092 return Err(self.struct_span_err(
1094 &format
!("cannot resolve relative path in non-file source `{}`", other
),
1107 /// Extracts a string literal from the macro expanded version of `expr`,
1108 /// emitting `err_msg` if `expr` is not a string literal. This does not stop
1109 /// compilation on error, merely emits a non-fatal error and returns `None`.
1110 pub fn expr_to_spanned_string
<'a
>(
1111 cx
: &'a
mut ExtCtxt
<'_
>,
1114 ) -> Result
<(Symbol
, ast
::StrStyle
, Span
), Option
<DiagnosticBuilder
<'a
>>> {
1115 // Perform eager expansion on the expression.
1116 // We want to be able to handle e.g., `concat!("foo", "bar")`.
1117 let expr
= cx
.expander().fully_expand_fragment(AstFragment
::Expr(expr
)).make_expr();
1119 Err(match expr
.kind
{
1120 ast
::ExprKind
::Lit(ref l
) => match l
.kind
{
1121 ast
::LitKind
::Str(s
, style
) => return Ok((s
, style
, expr
.span
)),
1122 ast
::LitKind
::Err(_
) => None
,
1123 _
=> Some(cx
.struct_span_err(l
.span
, err_msg
)),
1125 ast
::ExprKind
::Err
=> None
,
1126 _
=> Some(cx
.struct_span_err(expr
.span
, err_msg
)),
1130 pub fn expr_to_string(
1131 cx
: &mut ExtCtxt
<'_
>,
1134 ) -> Option
<(Symbol
, ast
::StrStyle
)> {
1135 expr_to_spanned_string(cx
, expr
, err_msg
)
1142 .map(|(symbol
, style
, _
)| (symbol
, style
))
1145 /// Non-fatally assert that `tts` is empty. Note that this function
1146 /// returns even when `tts` is non-empty, macros that *need* to stop
1147 /// compilation should call
1148 /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
1149 /// done as rarely as possible).
1150 pub fn check_zero_tts(cx
: &ExtCtxt
<'_
>, sp
: Span
, tts
: TokenStream
, name
: &str) {
1151 if !tts
.is_empty() {
1152 cx
.span_err(sp
, &format
!("{} takes no arguments", name
));
1156 /// Parse an expression. On error, emit it, advancing to `Eof`, and return `None`.
1157 pub fn parse_expr(p
: &mut parser
::Parser
<'_
>) -> Option
<P
<ast
::Expr
>> {
1158 match p
.parse_expr() {
1159 Ok(e
) => return Some(e
),
1160 Err(mut err
) => err
.emit(),
1162 while p
.token
!= token
::Eof
{
1168 /// Interpreting `tts` as a comma-separated sequence of expressions,
1169 /// expect exactly one string literal, or emit an error and return `None`.
1170 pub fn get_single_str_from_tts(
1171 cx
: &mut ExtCtxt
<'_
>,
1175 ) -> Option
<String
> {
1176 let mut p
= cx
.new_parser_from_tts(tts
);
1177 if p
.token
== token
::Eof
{
1178 cx
.span_err(sp
, &format
!("{} takes 1 argument", name
));
1181 let ret
= parse_expr(&mut p
)?
;
1182 let _
= p
.eat(&token
::Comma
);
1184 if p
.token
!= token
::Eof
{
1185 cx
.span_err(sp
, &format
!("{} takes 1 argument", name
));
1187 expr_to_string(cx
, ret
, "argument must be a string literal").map(|(s
, _
)| s
.to_string())
1190 /// Extracts comma-separated expressions from `tts`.
1191 /// On error, emit it, and return `None`.
1192 pub fn get_exprs_from_tts(
1193 cx
: &mut ExtCtxt
<'_
>,
1196 ) -> Option
<Vec
<P
<ast
::Expr
>>> {
1197 let mut p
= cx
.new_parser_from_tts(tts
);
1198 let mut es
= Vec
::new();
1199 while p
.token
!= token
::Eof
{
1200 let expr
= parse_expr(&mut p
)?
;
1202 // Perform eager expansion on the expression.
1203 // We want to be able to handle e.g., `concat!("foo", "bar")`.
1204 let expr
= cx
.expander().fully_expand_fragment(AstFragment
::Expr(expr
)).make_expr();
1207 if p
.eat(&token
::Comma
) {
1210 if p
.token
!= token
::Eof
{
1211 cx
.span_err(sp
, "expected token: `,`");