1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 pub use self::SyntaxExtension
::*;
13 use ast
::{self, Attribute, Name, PatKind, MetaItem}
;
15 use codemap
::{self, CodeMap, Spanned, respan}
;
16 use syntax_pos
::{Span, MultiSpan, DUMMY_SP}
;
18 use errors
::{DiagnosticBuilder, DiagnosticId}
;
19 use ext
::expand
::{self, Expansion, Invocation}
;
20 use ext
::hygiene
::{self, Mark, SyntaxContext}
;
21 use fold
::{self, Folder}
;
22 use parse
::{self, parser, DirectoryOwnership}
;
25 use symbol
::{keywords, Ident, Symbol}
;
26 use util
::small_vector
::SmallVector
;
28 use std
::collections
::HashMap
;
30 use std
::path
::PathBuf
;
32 use rustc_data_structures
::sync
::{self, Lrc}
;
33 use std
::default::Default
;
34 use tokenstream
::{self, TokenStream}
;
37 #[derive(Debug,Clone)]
38 pub enum Annotatable
{
40 TraitItem(P
<ast
::TraitItem
>),
41 ImplItem(P
<ast
::ImplItem
>),
42 ForeignItem(P
<ast
::ForeignItem
>),
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
,
59 fn map_attrs
<F
: FnOnce(Vec
<Attribute
>) -> Vec
<Attribute
>>(self, f
: F
) -> Self {
61 Annotatable
::Item(item
) => Annotatable
::Item(item
.map_attrs(f
)),
62 Annotatable
::TraitItem(trait_item
) => Annotatable
::TraitItem(trait_item
.map_attrs(f
)),
63 Annotatable
::ImplItem(impl_item
) => Annotatable
::ImplItem(impl_item
.map_attrs(f
)),
64 Annotatable
::ForeignItem(foreign_item
) =>
65 Annotatable
::ForeignItem(foreign_item
.map_attrs(f
)),
66 Annotatable
::Stmt(stmt
) => Annotatable
::Stmt(stmt
.map_attrs(f
)),
67 Annotatable
::Expr(expr
) => Annotatable
::Expr(expr
.map_attrs(f
)),
73 pub fn span(&self) -> Span
{
75 Annotatable
::Item(ref item
) => item
.span
,
76 Annotatable
::TraitItem(ref trait_item
) => trait_item
.span
,
77 Annotatable
::ImplItem(ref impl_item
) => impl_item
.span
,
78 Annotatable
::ForeignItem(ref foreign_item
) => foreign_item
.span
,
79 Annotatable
::Stmt(ref stmt
) => stmt
.span
,
80 Annotatable
::Expr(ref expr
) => expr
.span
,
84 pub fn expect_item(self) -> P
<ast
::Item
> {
86 Annotatable
::Item(i
) => i
,
87 _
=> panic
!("expected Item")
91 pub fn map_item_or
<F
, G
>(self, mut f
: F
, mut or
: G
) -> Annotatable
92 where F
: FnMut(P
<ast
::Item
>) -> P
<ast
::Item
>,
93 G
: FnMut(Annotatable
) -> Annotatable
96 Annotatable
::Item(i
) => Annotatable
::Item(f(i
)),
101 pub fn expect_trait_item(self) -> ast
::TraitItem
{
103 Annotatable
::TraitItem(i
) => i
.into_inner(),
104 _
=> panic
!("expected Item")
108 pub fn expect_impl_item(self) -> ast
::ImplItem
{
110 Annotatable
::ImplItem(i
) => i
.into_inner(),
111 _
=> panic
!("expected Item")
115 pub fn expect_foreign_item(self) -> ast
::ForeignItem
{
117 Annotatable
::ForeignItem(i
) => i
.into_inner(),
118 _
=> panic
!("expected foreign item")
122 pub fn expect_stmt(self) -> ast
::Stmt
{
124 Annotatable
::Stmt(stmt
) => stmt
.into_inner(),
125 _
=> panic
!("expected statement"),
129 pub fn expect_expr(self) -> P
<ast
::Expr
> {
131 Annotatable
::Expr(expr
) => expr
,
132 _
=> panic
!("expected expression"),
136 pub fn derive_allowed(&self) -> bool
{
138 Annotatable
::Item(ref item
) => match item
.node
{
139 ast
::ItemKind
::Struct(..) |
140 ast
::ItemKind
::Enum(..) |
141 ast
::ItemKind
::Union(..) => true,
149 // A more flexible ItemDecorator.
150 pub trait MultiItemDecorator
{
154 meta_item
: &ast
::MetaItem
,
156 push
: &mut FnMut(Annotatable
));
159 impl<F
> MultiItemDecorator
for F
160 where F
: Fn(&mut ExtCtxt
, Span
, &ast
::MetaItem
, &Annotatable
, &mut FnMut(Annotatable
))
165 meta_item
: &ast
::MetaItem
,
167 push
: &mut FnMut(Annotatable
)) {
168 (*self)(ecx
, sp
, meta_item
, item
, push
)
172 // `meta_item` is the annotation, and `item` is the item being modified.
173 // FIXME Decorators should follow the same pattern too.
174 pub trait MultiItemModifier
{
178 meta_item
: &ast
::MetaItem
,
183 impl<F
, T
> MultiItemModifier
for F
184 where F
: Fn(&mut ExtCtxt
, Span
, &ast
::MetaItem
, Annotatable
) -> T
,
185 T
: Into
<Vec
<Annotatable
>>,
190 meta_item
: &ast
::MetaItem
,
192 -> Vec
<Annotatable
> {
193 (*self)(ecx
, span
, meta_item
, item
).into()
197 impl Into
<Vec
<Annotatable
>> for Annotatable
{
198 fn into(self) -> Vec
<Annotatable
> {
203 pub trait ProcMacro
{
204 fn expand
<'cx
>(&self,
205 ecx
: &'cx
mut ExtCtxt
,
211 impl<F
> ProcMacro
for F
212 where F
: Fn(TokenStream
) -> TokenStream
214 fn expand
<'cx
>(&self,
215 _ecx
: &'cx
mut ExtCtxt
,
219 // FIXME setup implicit context in TLS before calling self.
224 pub trait AttrProcMacro
{
225 fn expand
<'cx
>(&self,
226 ecx
: &'cx
mut ExtCtxt
,
228 annotation
: TokenStream
,
229 annotated
: TokenStream
)
233 impl<F
> AttrProcMacro
for F
234 where F
: Fn(TokenStream
, TokenStream
) -> TokenStream
236 fn expand
<'cx
>(&self,
237 _ecx
: &'cx
mut ExtCtxt
,
239 annotation
: TokenStream
,
240 annotated
: TokenStream
)
242 // FIXME setup implicit context in TLS before calling self.
243 (*self)(annotation
, annotated
)
247 /// Represents a thing that maps token trees to Macro Results
248 pub trait TTMacroExpander
{
249 fn expand
<'cx
>(&self, ecx
: &'cx
mut ExtCtxt
, span
: Span
, input
: TokenStream
)
250 -> Box
<MacResult
+'cx
>;
253 pub type MacroExpanderFn
=
254 for<'cx
> fn(&'cx
mut ExtCtxt
, Span
, &[tokenstream
::TokenTree
])
255 -> Box
<MacResult
+'cx
>;
257 impl<F
> TTMacroExpander
for F
258 where F
: for<'cx
> Fn(&'cx
mut ExtCtxt
, Span
, &[tokenstream
::TokenTree
]) -> Box
<MacResult
+'cx
>
260 fn expand
<'cx
>(&self, ecx
: &'cx
mut ExtCtxt
, span
: Span
, input
: TokenStream
)
261 -> Box
<MacResult
+'cx
> {
262 struct AvoidInterpolatedIdents
;
264 impl Folder
for AvoidInterpolatedIdents
{
265 fn fold_tt(&mut self, tt
: tokenstream
::TokenTree
) -> tokenstream
::TokenTree
{
266 if let tokenstream
::TokenTree
::Token(_
, token
::Interpolated(ref nt
)) = tt
{
267 if let token
::NtIdent(ident
, is_raw
) = nt
.0 {
268 return tokenstream
::TokenTree
::Token(ident
.span
,
269 token
::Ident(ident
, is_raw
));
272 fold
::noop_fold_tt(tt
, self)
275 fn fold_mac(&mut self, mac
: ast
::Mac
) -> ast
::Mac
{
276 fold
::noop_fold_mac(mac
, self)
281 input
.trees().map(|tt
| AvoidInterpolatedIdents
.fold_tt(tt
)).collect();
282 (*self)(ecx
, span
, &input
)
286 pub trait IdentMacroExpander
{
287 fn expand
<'cx
>(&self,
288 cx
: &'cx
mut ExtCtxt
,
291 token_tree
: Vec
<tokenstream
::TokenTree
>)
292 -> Box
<MacResult
+'cx
>;
295 pub type IdentMacroExpanderFn
=
296 for<'cx
> fn(&'cx
mut ExtCtxt
, Span
, ast
::Ident
, Vec
<tokenstream
::TokenTree
>)
297 -> Box
<MacResult
+'cx
>;
299 impl<F
> IdentMacroExpander
for F
300 where F
: for<'cx
> Fn(&'cx
mut ExtCtxt
, Span
, ast
::Ident
,
301 Vec
<tokenstream
::TokenTree
>) -> Box
<MacResult
+'cx
>
303 fn expand
<'cx
>(&self,
304 cx
: &'cx
mut ExtCtxt
,
307 token_tree
: Vec
<tokenstream
::TokenTree
>)
308 -> Box
<MacResult
+'cx
>
310 (*self)(cx
, sp
, ident
, token_tree
)
314 // Use a macro because forwarding to a simple function has type system issues
315 macro_rules
! make_stmts_default
{
317 $me
.make_expr().map(|e
| SmallVector
::one(ast
::Stmt
{
318 id
: ast
::DUMMY_NODE_ID
,
320 node
: ast
::StmtKind
::Expr(e
),
325 /// The result of a macro expansion. The return values of the various
326 /// methods are spliced into the AST at the callsite of the macro.
327 pub trait MacResult
{
328 /// Create an expression.
329 fn make_expr(self: Box
<Self>) -> Option
<P
<ast
::Expr
>> {
332 /// Create zero or more items.
333 fn make_items(self: Box
<Self>) -> Option
<SmallVector
<P
<ast
::Item
>>> {
337 /// Create zero or more impl items.
338 fn make_impl_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::ImplItem
>> {
342 /// Create zero or more trait items.
343 fn make_trait_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::TraitItem
>> {
347 /// Create zero or more items in an `extern {}` block
348 fn make_foreign_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::ForeignItem
>> { None }
350 /// Create a pattern.
351 fn make_pat(self: Box
<Self>) -> Option
<P
<ast
::Pat
>> {
355 /// Create zero or more statements.
357 /// By default this attempts to create an expression statement,
358 /// returning None if that fails.
359 fn make_stmts(self: Box
<Self>) -> Option
<SmallVector
<ast
::Stmt
>> {
360 make_stmts_default
!(self)
363 fn make_ty(self: Box
<Self>) -> Option
<P
<ast
::Ty
>> {
368 macro_rules
! make_MacEager
{
369 ( $
( $fld
:ident
: $t
:ty
, )* ) => {
370 /// `MacResult` implementation for the common case where you've already
371 /// built each form of AST that you might return.
373 pub struct MacEager
{
375 pub $fld
: Option
<$t
>,
381 pub fn $
fld(v
: $t
) -> Box
<MacResult
> {
395 items
: SmallVector
<P
<ast
::Item
>>,
396 impl_items
: SmallVector
<ast
::ImplItem
>,
397 trait_items
: SmallVector
<ast
::TraitItem
>,
398 foreign_items
: SmallVector
<ast
::ForeignItem
>,
399 stmts
: SmallVector
<ast
::Stmt
>,
403 impl MacResult
for MacEager
{
404 fn make_expr(self: Box
<Self>) -> Option
<P
<ast
::Expr
>> {
408 fn make_items(self: Box
<Self>) -> Option
<SmallVector
<P
<ast
::Item
>>> {
412 fn make_impl_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::ImplItem
>> {
416 fn make_trait_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::TraitItem
>> {
420 fn make_foreign_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::ForeignItem
>> {
424 fn make_stmts(self: Box
<Self>) -> Option
<SmallVector
<ast
::Stmt
>> {
425 match self.stmts
.as_ref().map_or(0, |s
| s
.len()) {
426 0 => make_stmts_default
!(self),
431 fn make_pat(self: Box
<Self>) -> Option
<P
<ast
::Pat
>> {
432 if let Some(p
) = self.pat
{
435 if let Some(e
) = self.expr
{
436 if let ast
::ExprKind
::Lit(_
) = e
.node
{
437 return Some(P(ast
::Pat
{
438 id
: ast
::DUMMY_NODE_ID
,
440 node
: PatKind
::Lit(e
),
447 fn make_ty(self: Box
<Self>) -> Option
<P
<ast
::Ty
>> {
452 /// Fill-in macro expansion result, to allow compilation to continue
453 /// after hitting errors.
454 #[derive(Copy, Clone)]
455 pub struct DummyResult
{
461 /// Create a default MacResult that can be anything.
463 /// Use this as a return value after hitting any errors and
464 /// calling `span_err`.
465 pub fn any(sp
: Span
) -> Box
<MacResult
+'
static> {
466 Box
::new(DummyResult { expr_only: false, span: sp }
)
469 /// Create a default MacResult that can only be an expression.
471 /// Use this for macros that must expand to an expression, so even
472 /// if an error is encountered internally, the user will receive
473 /// an error that they also used it in the wrong place.
474 pub fn expr(sp
: Span
) -> Box
<MacResult
+'
static> {
475 Box
::new(DummyResult { expr_only: true, span: sp }
)
478 /// A plain dummy expression.
479 pub fn raw_expr(sp
: Span
) -> P
<ast
::Expr
> {
481 id
: ast
::DUMMY_NODE_ID
,
482 node
: ast
::ExprKind
::Lit(P(codemap
::respan(sp
, ast
::LitKind
::Bool(false)))),
484 attrs
: ast
::ThinVec
::new(),
488 /// A plain dummy pattern.
489 pub fn raw_pat(sp
: Span
) -> ast
::Pat
{
491 id
: ast
::DUMMY_NODE_ID
,
497 pub fn raw_ty(sp
: Span
) -> P
<ast
::Ty
> {
499 id
: ast
::DUMMY_NODE_ID
,
500 node
: ast
::TyKind
::Infer
,
506 impl MacResult
for DummyResult
{
507 fn make_expr(self: Box
<DummyResult
>) -> Option
<P
<ast
::Expr
>> {
508 Some(DummyResult
::raw_expr(self.span
))
511 fn make_pat(self: Box
<DummyResult
>) -> Option
<P
<ast
::Pat
>> {
512 Some(P(DummyResult
::raw_pat(self.span
)))
515 fn make_items(self: Box
<DummyResult
>) -> Option
<SmallVector
<P
<ast
::Item
>>> {
516 // this code needs a comment... why not always just return the Some() ?
520 Some(SmallVector
::new())
524 fn make_impl_items(self: Box
<DummyResult
>) -> Option
<SmallVector
<ast
::ImplItem
>> {
528 Some(SmallVector
::new())
532 fn make_trait_items(self: Box
<DummyResult
>) -> Option
<SmallVector
<ast
::TraitItem
>> {
536 Some(SmallVector
::new())
540 fn make_foreign_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::ForeignItem
>> {
544 Some(SmallVector
::new())
548 fn make_stmts(self: Box
<DummyResult
>) -> Option
<SmallVector
<ast
::Stmt
>> {
549 Some(SmallVector
::one(ast
::Stmt
{
550 id
: ast
::DUMMY_NODE_ID
,
551 node
: ast
::StmtKind
::Expr(DummyResult
::raw_expr(self.span
)),
556 fn make_ty(self: Box
<DummyResult
>) -> Option
<P
<ast
::Ty
>> {
557 Some(DummyResult
::raw_ty(self.span
))
561 pub type BuiltinDeriveFn
=
562 for<'cx
> fn(&'cx
mut ExtCtxt
, Span
, &MetaItem
, &Annotatable
, &mut FnMut(Annotatable
));
564 /// Represents different kinds of macro invocations that can be resolved.
565 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
567 /// A bang macro - foo!()
569 /// An attribute macro - #[foo]
571 /// A derive attribute macro - #[derive(Foo)]
576 pub fn descr(self) -> &'
static str {
578 MacroKind
::Bang
=> "macro",
579 MacroKind
::Attr
=> "attribute macro",
580 MacroKind
::Derive
=> "derive macro",
585 /// An enum representing the different kinds of syntax extensions.
586 pub enum SyntaxExtension
{
587 /// A syntax extension that is attached to an item and creates new items
590 /// `#[derive(...)]` is a `MultiItemDecorator`.
592 /// Prefer ProcMacro or MultiModifier since they are more flexible.
593 MultiDecorator(Box
<MultiItemDecorator
+ sync
::Sync
+ sync
::Send
>),
595 /// A syntax extension that is attached to an item and modifies it
596 /// in-place. Also allows decoration, i.e., creating new items.
597 MultiModifier(Box
<MultiItemModifier
+ sync
::Sync
+ sync
::Send
>),
599 /// A function-like procedural macro. TokenStream -> TokenStream.
600 ProcMacro(Box
<ProcMacro
+ sync
::Sync
+ sync
::Send
>, Edition
),
602 /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
603 /// The first TokenSteam is the attribute, the second is the annotated item.
604 /// Allows modification of the input items and adding new items, similar to
605 /// MultiModifier, but uses TokenStreams, rather than AST nodes.
606 AttrProcMacro(Box
<AttrProcMacro
+ sync
::Sync
+ sync
::Send
>, Edition
),
608 /// A normal, function-like syntax extension.
610 /// `bytes!` is a `NormalTT`.
612 expander
: Box
<TTMacroExpander
+ sync
::Sync
+ sync
::Send
>,
613 def_info
: Option
<(ast
::NodeId
, Span
)>,
614 /// Whether the contents of the macro can
615 /// directly use `#[unstable]` things (true == yes).
616 allow_internal_unstable
: bool
,
617 /// Whether the contents of the macro can use `unsafe`
618 /// without triggering the `unsafe_code` lint.
619 allow_internal_unsafe
: bool
,
620 /// The macro's feature name if it is unstable, and the stability feature
621 unstable_feature
: Option
<(Symbol
, u32)>,
622 /// Edition of the crate in which the macro is defined
626 /// A function-like syntax extension that has an extra ident before
629 IdentTT(Box
<IdentMacroExpander
+ sync
::Sync
+ sync
::Send
>, Option
<Span
>, bool
),
631 /// An attribute-like procedural macro. TokenStream -> TokenStream.
632 /// The input is the annotated item.
633 /// Allows generating code to implement a Trait for a given struct
635 ProcMacroDerive(Box
<MultiItemModifier
+ sync
::Sync
+ sync
::Send
>,
636 Vec
<Symbol
> /* inert attribute names */, Edition
),
638 /// An attribute-like procedural macro that derives a builtin trait.
639 BuiltinDerive(BuiltinDeriveFn
),
641 /// A declarative macro, e.g. `macro m() {}`.
643 /// The second element is the definition site span.
644 DeclMacro(Box
<TTMacroExpander
+ sync
::Sync
+ sync
::Send
>, Option
<(ast
::NodeId
, Span
)>, Edition
),
647 impl SyntaxExtension
{
648 /// Return which kind of macro calls this syntax extension.
649 pub fn kind(&self) -> MacroKind
{
651 SyntaxExtension
::DeclMacro(..) |
652 SyntaxExtension
::NormalTT { .. }
|
653 SyntaxExtension
::IdentTT(..) |
654 SyntaxExtension
::ProcMacro(..) =>
656 SyntaxExtension
::MultiDecorator(..) |
657 SyntaxExtension
::MultiModifier(..) |
658 SyntaxExtension
::AttrProcMacro(..) =>
660 SyntaxExtension
::ProcMacroDerive(..) |
661 SyntaxExtension
::BuiltinDerive(..) =>
666 pub fn is_modern(&self) -> bool
{
668 SyntaxExtension
::DeclMacro(..) |
669 SyntaxExtension
::ProcMacro(..) |
670 SyntaxExtension
::AttrProcMacro(..) |
671 SyntaxExtension
::ProcMacroDerive(..) => true,
676 pub fn edition(&self) -> Edition
{
678 SyntaxExtension
::NormalTT { edition, .. }
|
679 SyntaxExtension
::DeclMacro(.., edition
) |
680 SyntaxExtension
::ProcMacro(.., edition
) |
681 SyntaxExtension
::AttrProcMacro(.., edition
) |
682 SyntaxExtension
::ProcMacroDerive(.., edition
) => edition
,
683 // Unstable legacy stuff
684 SyntaxExtension
::IdentTT(..) |
685 SyntaxExtension
::MultiDecorator(..) |
686 SyntaxExtension
::MultiModifier(..) |
687 SyntaxExtension
::BuiltinDerive(..) => hygiene
::default_edition(),
692 pub type NamedSyntaxExtension
= (Name
, SyntaxExtension
);
695 fn next_node_id(&mut self) -> ast
::NodeId
;
696 fn get_module_scope(&mut self, id
: ast
::NodeId
) -> Mark
;
697 fn eliminate_crate_var(&mut self, item
: P
<ast
::Item
>) -> P
<ast
::Item
>;
698 fn is_whitelisted_legacy_custom_derive(&self, name
: Name
) -> bool
;
700 fn visit_expansion(&mut self, mark
: Mark
, expansion
: &Expansion
, derives
: &[Mark
]);
701 fn add_builtin(&mut self, ident
: ast
::Ident
, ext
: Lrc
<SyntaxExtension
>);
703 fn resolve_imports(&mut self);
704 // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
705 fn find_legacy_attr_invoc(&mut self, attrs
: &mut Vec
<Attribute
>, allow_derive
: bool
)
706 -> Option
<Attribute
>;
708 fn resolve_invoc(&mut self, invoc
: &mut Invocation
, scope
: Mark
, force
: bool
)
709 -> Result
<Option
<Lrc
<SyntaxExtension
>>, Determinacy
>;
710 fn resolve_macro(&mut self, scope
: Mark
, path
: &ast
::Path
, kind
: MacroKind
, force
: bool
)
711 -> Result
<Lrc
<SyntaxExtension
>, Determinacy
>;
712 fn check_unused_macros(&self);
715 #[derive(Copy, Clone, Debug, PartialEq)]
716 pub enum Determinacy
{
721 pub struct DummyResolver
;
723 impl Resolver
for DummyResolver
{
724 fn next_node_id(&mut self) -> ast
::NodeId { ast::DUMMY_NODE_ID }
725 fn get_module_scope(&mut self, _id
: ast
::NodeId
) -> Mark { Mark::root() }
726 fn eliminate_crate_var(&mut self, item
: P
<ast
::Item
>) -> P
<ast
::Item
> { item }
727 fn is_whitelisted_legacy_custom_derive(&self, _name
: Name
) -> bool { false }
729 fn visit_expansion(&mut self, _invoc
: Mark
, _expansion
: &Expansion
, _derives
: &[Mark
]) {}
730 fn add_builtin(&mut self, _ident
: ast
::Ident
, _ext
: Lrc
<SyntaxExtension
>) {}
732 fn resolve_imports(&mut self) {}
733 fn find_legacy_attr_invoc(&mut self, _attrs
: &mut Vec
<Attribute
>, _allow_derive
: bool
)
734 -> Option
<Attribute
> { None }
735 fn resolve_invoc(&mut self, _invoc
: &mut Invocation
, _scope
: Mark
, _force
: bool
)
736 -> Result
<Option
<Lrc
<SyntaxExtension
>>, Determinacy
> {
737 Err(Determinacy
::Determined
)
739 fn resolve_macro(&mut self, _scope
: Mark
, _path
: &ast
::Path
, _kind
: MacroKind
,
740 _force
: bool
) -> Result
<Lrc
<SyntaxExtension
>, Determinacy
> {
741 Err(Determinacy
::Determined
)
743 fn check_unused_macros(&self) {}
747 pub struct ModuleData
{
748 pub mod_path
: Vec
<ast
::Ident
>,
749 pub directory
: PathBuf
,
753 pub struct ExpansionData
{
756 pub module
: Rc
<ModuleData
>,
757 pub directory_ownership
: DirectoryOwnership
,
758 pub crate_span
: Option
<Span
>,
761 /// One of these is made during expansion and incrementally updated as we go;
762 /// when a macro expansion occurs, the resulting nodes have the `backtrace()
763 /// -> expn_info` of their expansion context stored into their span.
764 pub struct ExtCtxt
<'a
> {
765 pub parse_sess
: &'a parse
::ParseSess
,
766 pub ecfg
: expand
::ExpansionConfig
<'a
>,
767 pub root_path
: PathBuf
,
768 pub resolver
: &'a
mut Resolver
,
769 pub resolve_err_count
: usize,
770 pub current_expansion
: ExpansionData
,
771 pub expansions
: HashMap
<Span
, Vec
<String
>>,
774 impl<'a
> ExtCtxt
<'a
> {
775 pub fn new(parse_sess
: &'a parse
::ParseSess
,
776 ecfg
: expand
::ExpansionConfig
<'a
>,
777 resolver
: &'a
mut Resolver
)
782 root_path
: PathBuf
::new(),
784 resolve_err_count
: 0,
785 current_expansion
: ExpansionData
{
788 module
: Rc
::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }
),
789 directory_ownership
: DirectoryOwnership
::Owned { relative: None }
,
792 expansions
: HashMap
::new(),
796 /// Returns a `Folder` for deeply expanding all macros in an AST node.
797 pub fn expander
<'b
>(&'b
mut self) -> expand
::MacroExpander
<'b
, 'a
> {
798 expand
::MacroExpander
::new(self, false)
801 /// Returns a `Folder` that deeply expands all macros and assigns all node ids in an AST node.
802 /// Once node ids are assigned, the node may not be expanded, removed, or otherwise modified.
803 pub fn monotonic_expander
<'b
>(&'b
mut self) -> expand
::MacroExpander
<'b
, 'a
> {
804 expand
::MacroExpander
::new(self, true)
807 pub fn new_parser_from_tts(&self, tts
: &[tokenstream
::TokenTree
]) -> parser
::Parser
<'a
> {
808 parse
::stream_to_parser(self.parse_sess
, tts
.iter().cloned().collect())
810 pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() }
811 pub fn parse_sess(&self) -> &'a parse
::ParseSess { self.parse_sess }
812 pub fn cfg(&self) -> &ast
::CrateConfig { &self.parse_sess.config }
813 pub fn call_site(&self) -> Span
{
814 match self.current_expansion
.mark
.expn_info() {
815 Some(expn_info
) => expn_info
.call_site
,
819 pub fn backtrace(&self) -> SyntaxContext
{
820 SyntaxContext
::empty().apply_mark(self.current_expansion
.mark
)
823 /// Returns span for the macro which originally caused the current expansion to happen.
825 /// Stops backtracing at include! boundary.
826 pub fn expansion_cause(&self) -> Option
<Span
> {
827 let mut ctxt
= self.backtrace();
828 let mut last_macro
= None
;
830 if ctxt
.outer().expn_info().map_or(None
, |info
| {
831 if info
.callee
.name() == "include" {
832 // Stop going up the backtrace once include! is encountered
835 ctxt
= info
.call_site
.ctxt();
836 last_macro
= Some(info
.call_site
);
845 pub fn struct_span_warn
<S
: Into
<MultiSpan
>>(&self,
848 -> DiagnosticBuilder
<'a
> {
849 self.parse_sess
.span_diagnostic
.struct_span_warn(sp
, msg
)
851 pub fn struct_span_err
<S
: Into
<MultiSpan
>>(&self,
854 -> DiagnosticBuilder
<'a
> {
855 self.parse_sess
.span_diagnostic
.struct_span_err(sp
, msg
)
857 pub fn struct_span_fatal
<S
: Into
<MultiSpan
>>(&self,
860 -> DiagnosticBuilder
<'a
> {
861 self.parse_sess
.span_diagnostic
.struct_span_fatal(sp
, msg
)
864 /// Emit `msg` attached to `sp`, and stop compilation immediately.
866 /// `span_err` should be strongly preferred where-ever possible:
867 /// this should *only* be used when:
869 /// - continuing has a high risk of flow-on errors (e.g. errors in
870 /// declaring a macro would cause all uses of that macro to
871 /// complain about "undefined macro"), or
872 /// - there is literally nothing else that can be done (however,
873 /// in most cases one can construct a dummy expression/item to
874 /// substitute; we never hit resolve/type-checking so the dummy
875 /// value doesn't have to match anything)
876 pub fn span_fatal
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) -> ! {
877 self.parse_sess
.span_diagnostic
.span_fatal(sp
, msg
).raise();
880 /// Emit `msg` attached to `sp`, without immediately stopping
883 /// Compilation will be stopped in the near future (at the end of
884 /// the macro expansion phase).
885 pub fn span_err
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) {
886 self.parse_sess
.span_diagnostic
.span_err(sp
, msg
);
888 pub fn span_err_with_code
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str, code
: DiagnosticId
) {
889 self.parse_sess
.span_diagnostic
.span_err_with_code(sp
, msg
, code
);
891 pub fn mut_span_err
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str)
892 -> DiagnosticBuilder
<'a
> {
893 self.parse_sess
.span_diagnostic
.mut_span_err(sp
, msg
)
895 pub fn span_warn
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) {
896 self.parse_sess
.span_diagnostic
.span_warn(sp
, msg
);
898 pub fn span_unimpl
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) -> ! {
899 self.parse_sess
.span_diagnostic
.span_unimpl(sp
, msg
);
901 pub fn span_bug
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) -> ! {
902 self.parse_sess
.span_diagnostic
.span_bug(sp
, msg
);
904 pub fn trace_macros_diag(&mut self) {
905 for (sp
, notes
) in self.expansions
.iter() {
906 let mut db
= self.parse_sess
.span_diagnostic
.span_note_diag(*sp
, "trace_macro");
912 // Fixme: does this result in errors?
913 self.expansions
.clear();
915 pub fn bug(&self, msg
: &str) -> ! {
916 self.parse_sess
.span_diagnostic
.bug(msg
);
918 pub fn trace_macros(&self) -> bool
{
921 pub fn set_trace_macros(&mut self, x
: bool
) {
922 self.ecfg
.trace_mac
= x
924 pub fn ident_of(&self, st
: &str) -> ast
::Ident
{
925 ast
::Ident
::from_str(st
)
927 pub fn std_path(&self, components
: &[&str]) -> Vec
<ast
::Ident
> {
928 let def_site
= DUMMY_SP
.apply_mark(self.current_expansion
.mark
);
929 iter
::once(Ident
::new(keywords
::DollarCrate
.name(), def_site
))
930 .chain(components
.iter().map(|s
| self.ident_of(s
)))
933 pub fn name_of(&self, st
: &str) -> ast
::Name
{
937 pub fn check_unused_macros(&self) {
938 self.resolver
.check_unused_macros();
942 /// Extract a string literal from the macro expanded version of `expr`,
943 /// emitting `err_msg` if `expr` is not a string literal. This does not stop
944 /// compilation on error, merely emits a non-fatal error and returns None.
945 pub fn expr_to_spanned_string(cx
: &mut ExtCtxt
, expr
: P
<ast
::Expr
>, err_msg
: &str)
946 -> Option
<Spanned
<(Symbol
, ast
::StrStyle
)>> {
947 // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation.
948 let expr
= expr
.map(|mut expr
| {
949 expr
.span
= expr
.span
.apply_mark(cx
.current_expansion
.mark
);
953 // we want to be able to handle e.g. concat("foo", "bar")
954 let expr
= cx
.expander().fold_expr(expr
);
956 ast
::ExprKind
::Lit(ref l
) => match l
.node
{
957 ast
::LitKind
::Str(s
, style
) => return Some(respan(expr
.span
, (s
, style
))),
958 _
=> cx
.span_err(l
.span
, err_msg
)
960 _
=> cx
.span_err(expr
.span
, err_msg
)
965 pub fn expr_to_string(cx
: &mut ExtCtxt
, expr
: P
<ast
::Expr
>, err_msg
: &str)
966 -> Option
<(Symbol
, ast
::StrStyle
)> {
967 expr_to_spanned_string(cx
, expr
, err_msg
).map(|s
| s
.node
)
970 /// Non-fatally assert that `tts` is empty. Note that this function
971 /// returns even when `tts` is non-empty, macros that *need* to stop
972 /// compilation should call
973 /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
974 /// done as rarely as possible).
975 pub fn check_zero_tts(cx
: &ExtCtxt
,
977 tts
: &[tokenstream
::TokenTree
],
980 cx
.span_err(sp
, &format
!("{} takes no arguments", name
));
984 /// Interpreting `tts` as a comma-separated sequence of expressions,
985 /// expect exactly one string literal, or emit an error and return None.
986 pub fn get_single_str_from_tts(cx
: &mut ExtCtxt
,
988 tts
: &[tokenstream
::TokenTree
],
991 let mut p
= cx
.new_parser_from_tts(tts
);
992 if p
.token
== token
::Eof
{
993 cx
.span_err(sp
, &format
!("{} takes 1 argument", name
));
996 let ret
= panictry
!(p
.parse_expr());
997 let _
= p
.eat(&token
::Comma
);
999 if p
.token
!= token
::Eof
{
1000 cx
.span_err(sp
, &format
!("{} takes 1 argument", name
));
1002 expr_to_string(cx
, ret
, "argument must be a string literal").map(|(s
, _
)| {
1007 /// Extract comma-separated expressions from `tts`. If there is a
1008 /// parsing error, emit a non-fatal error and return None.
1009 pub fn get_exprs_from_tts(cx
: &mut ExtCtxt
,
1011 tts
: &[tokenstream
::TokenTree
]) -> Option
<Vec
<P
<ast
::Expr
>>> {
1012 let mut p
= cx
.new_parser_from_tts(tts
);
1013 let mut es
= Vec
::new();
1014 while p
.token
!= token
::Eof
{
1015 es
.push(cx
.expander().fold_expr(panictry
!(p
.parse_expr())));
1016 if p
.eat(&token
::Comma
) {
1019 if p
.token
!= token
::Eof
{
1020 cx
.span_err(sp
, "expected token: `,`");