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, DUMMY_SP}
;
17 use errors
::DiagnosticBuilder
;
18 use ext
::expand
::{self, Expansion, Invocation}
;
19 use ext
::hygiene
::{Mark, SyntaxContext}
;
20 use fold
::{self, Folder}
;
21 use parse
::{self, parser, DirectoryOwnership}
;
25 use util
::small_vector
::SmallVector
;
27 use std
::collections
::HashMap
;
28 use std
::path
::PathBuf
;
30 use std
::default::Default
;
31 use tokenstream
::{self, TokenStream}
;
34 #[derive(Debug,Clone)]
35 pub enum Annotatable
{
37 TraitItem(P
<ast
::TraitItem
>),
38 ImplItem(P
<ast
::ImplItem
>),
41 impl HasAttrs
for Annotatable
{
42 fn attrs(&self) -> &[Attribute
] {
44 Annotatable
::Item(ref item
) => &item
.attrs
,
45 Annotatable
::TraitItem(ref trait_item
) => &trait_item
.attrs
,
46 Annotatable
::ImplItem(ref impl_item
) => &impl_item
.attrs
,
50 fn map_attrs
<F
: FnOnce(Vec
<Attribute
>) -> Vec
<Attribute
>>(self, f
: F
) -> Self {
52 Annotatable
::Item(item
) => Annotatable
::Item(item
.map_attrs(f
)),
53 Annotatable
::TraitItem(trait_item
) => Annotatable
::TraitItem(trait_item
.map_attrs(f
)),
54 Annotatable
::ImplItem(impl_item
) => Annotatable
::ImplItem(impl_item
.map_attrs(f
)),
60 pub fn span(&self) -> Span
{
62 Annotatable
::Item(ref item
) => item
.span
,
63 Annotatable
::TraitItem(ref trait_item
) => trait_item
.span
,
64 Annotatable
::ImplItem(ref impl_item
) => impl_item
.span
,
68 pub fn expect_item(self) -> P
<ast
::Item
> {
70 Annotatable
::Item(i
) => i
,
71 _
=> panic
!("expected Item")
75 pub fn map_item_or
<F
, G
>(self, mut f
: F
, mut or
: G
) -> Annotatable
76 where F
: FnMut(P
<ast
::Item
>) -> P
<ast
::Item
>,
77 G
: FnMut(Annotatable
) -> Annotatable
80 Annotatable
::Item(i
) => Annotatable
::Item(f(i
)),
85 pub fn expect_trait_item(self) -> ast
::TraitItem
{
87 Annotatable
::TraitItem(i
) => i
.unwrap(),
88 _
=> panic
!("expected Item")
92 pub fn expect_impl_item(self) -> ast
::ImplItem
{
94 Annotatable
::ImplItem(i
) => i
.unwrap(),
95 _
=> panic
!("expected Item")
100 // A more flexible ItemDecorator.
101 pub trait MultiItemDecorator
{
105 meta_item
: &ast
::MetaItem
,
107 push
: &mut FnMut(Annotatable
));
110 impl<F
> MultiItemDecorator
for F
111 where F
: Fn(&mut ExtCtxt
, Span
, &ast
::MetaItem
, &Annotatable
, &mut FnMut(Annotatable
))
116 meta_item
: &ast
::MetaItem
,
118 push
: &mut FnMut(Annotatable
)) {
119 (*self)(ecx
, sp
, meta_item
, item
, push
)
123 // `meta_item` is the annotation, and `item` is the item being modified.
124 // FIXME Decorators should follow the same pattern too.
125 pub trait MultiItemModifier
{
129 meta_item
: &ast
::MetaItem
,
134 impl<F
, T
> MultiItemModifier
for F
135 where F
: Fn(&mut ExtCtxt
, Span
, &ast
::MetaItem
, Annotatable
) -> T
,
136 T
: Into
<Vec
<Annotatable
>>,
141 meta_item
: &ast
::MetaItem
,
143 -> Vec
<Annotatable
> {
144 (*self)(ecx
, span
, meta_item
, item
).into()
148 impl Into
<Vec
<Annotatable
>> for Annotatable
{
149 fn into(self) -> Vec
<Annotatable
> {
154 pub trait ProcMacro
{
155 fn expand
<'cx
>(&self,
156 ecx
: &'cx
mut ExtCtxt
,
162 impl<F
> ProcMacro
for F
163 where F
: Fn(TokenStream
) -> TokenStream
165 fn expand
<'cx
>(&self,
166 _ecx
: &'cx
mut ExtCtxt
,
170 // FIXME setup implicit context in TLS before calling self.
175 pub trait AttrProcMacro
{
176 fn expand
<'cx
>(&self,
177 ecx
: &'cx
mut ExtCtxt
,
179 annotation
: TokenStream
,
180 annotated
: TokenStream
)
184 impl<F
> AttrProcMacro
for F
185 where F
: Fn(TokenStream
, TokenStream
) -> TokenStream
187 fn expand
<'cx
>(&self,
188 _ecx
: &'cx
mut ExtCtxt
,
190 annotation
: TokenStream
,
191 annotated
: TokenStream
)
193 // FIXME setup implicit context in TLS before calling self.
194 (*self)(annotation
, annotated
)
198 /// Represents a thing that maps token trees to Macro Results
199 pub trait TTMacroExpander
{
200 fn expand
<'cx
>(&self, ecx
: &'cx
mut ExtCtxt
, span
: Span
, input
: TokenStream
)
201 -> Box
<MacResult
+'cx
>;
204 pub type MacroExpanderFn
=
205 for<'cx
> fn(&'cx
mut ExtCtxt
, Span
, &[tokenstream
::TokenTree
])
206 -> Box
<MacResult
+'cx
>;
208 impl<F
> TTMacroExpander
for F
209 where F
: for<'cx
> Fn(&'cx
mut ExtCtxt
, Span
, &[tokenstream
::TokenTree
]) -> Box
<MacResult
+'cx
>
211 fn expand
<'cx
>(&self, ecx
: &'cx
mut ExtCtxt
, span
: Span
, input
: TokenStream
)
212 -> Box
<MacResult
+'cx
> {
213 struct AvoidInterpolatedIdents
;
215 impl Folder
for AvoidInterpolatedIdents
{
216 fn fold_tt(&mut self, tt
: tokenstream
::TokenTree
) -> tokenstream
::TokenTree
{
217 if let tokenstream
::TokenTree
::Token(_
, token
::Interpolated(ref nt
)) = tt
{
218 if let token
::NtIdent(ident
) = nt
.0 {
219 return tokenstream
::TokenTree
::Token(ident
.span
, token
::Ident(ident
.node
));
222 fold
::noop_fold_tt(tt
, self)
225 fn fold_mac(&mut self, mac
: ast
::Mac
) -> ast
::Mac
{
226 fold
::noop_fold_mac(mac
, self)
231 input
.trees().map(|tt
| AvoidInterpolatedIdents
.fold_tt(tt
)).collect();
232 (*self)(ecx
, span
, &input
)
236 pub trait IdentMacroExpander
{
237 fn expand
<'cx
>(&self,
238 cx
: &'cx
mut ExtCtxt
,
241 token_tree
: Vec
<tokenstream
::TokenTree
>)
242 -> Box
<MacResult
+'cx
>;
245 pub type IdentMacroExpanderFn
=
246 for<'cx
> fn(&'cx
mut ExtCtxt
, Span
, ast
::Ident
, Vec
<tokenstream
::TokenTree
>)
247 -> Box
<MacResult
+'cx
>;
249 impl<F
> IdentMacroExpander
for F
250 where F
: for<'cx
> Fn(&'cx
mut ExtCtxt
, Span
, ast
::Ident
,
251 Vec
<tokenstream
::TokenTree
>) -> Box
<MacResult
+'cx
>
253 fn expand
<'cx
>(&self,
254 cx
: &'cx
mut ExtCtxt
,
257 token_tree
: Vec
<tokenstream
::TokenTree
>)
258 -> Box
<MacResult
+'cx
>
260 (*self)(cx
, sp
, ident
, token_tree
)
264 // Use a macro because forwarding to a simple function has type system issues
265 macro_rules
! make_stmts_default
{
267 $me
.make_expr().map(|e
| SmallVector
::one(ast
::Stmt
{
268 id
: ast
::DUMMY_NODE_ID
,
270 node
: ast
::StmtKind
::Expr(e
),
275 /// The result of a macro expansion. The return values of the various
276 /// methods are spliced into the AST at the callsite of the macro.
277 pub trait MacResult
{
278 /// Create an expression.
279 fn make_expr(self: Box
<Self>) -> Option
<P
<ast
::Expr
>> {
282 /// Create zero or more items.
283 fn make_items(self: Box
<Self>) -> Option
<SmallVector
<P
<ast
::Item
>>> {
287 /// Create zero or more impl items.
288 fn make_impl_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::ImplItem
>> {
292 /// Create zero or more trait items.
293 fn make_trait_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::TraitItem
>> {
297 /// Create a pattern.
298 fn make_pat(self: Box
<Self>) -> Option
<P
<ast
::Pat
>> {
302 /// Create zero or more statements.
304 /// By default this attempts to create an expression statement,
305 /// returning None if that fails.
306 fn make_stmts(self: Box
<Self>) -> Option
<SmallVector
<ast
::Stmt
>> {
307 make_stmts_default
!(self)
310 fn make_ty(self: Box
<Self>) -> Option
<P
<ast
::Ty
>> {
315 macro_rules
! make_MacEager
{
316 ( $
( $fld
:ident
: $t
:ty
, )* ) => {
317 /// `MacResult` implementation for the common case where you've already
318 /// built each form of AST that you might return.
320 pub struct MacEager
{
322 pub $fld
: Option
<$t
>,
328 pub fn $
fld(v
: $t
) -> Box
<MacResult
> {
342 items
: SmallVector
<P
<ast
::Item
>>,
343 impl_items
: SmallVector
<ast
::ImplItem
>,
344 trait_items
: SmallVector
<ast
::TraitItem
>,
345 stmts
: SmallVector
<ast
::Stmt
>,
349 impl MacResult
for MacEager
{
350 fn make_expr(self: Box
<Self>) -> Option
<P
<ast
::Expr
>> {
354 fn make_items(self: Box
<Self>) -> Option
<SmallVector
<P
<ast
::Item
>>> {
358 fn make_impl_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::ImplItem
>> {
362 fn make_trait_items(self: Box
<Self>) -> Option
<SmallVector
<ast
::TraitItem
>> {
366 fn make_stmts(self: Box
<Self>) -> Option
<SmallVector
<ast
::Stmt
>> {
367 match self.stmts
.as_ref().map_or(0, |s
| s
.len()) {
368 0 => make_stmts_default
!(self),
373 fn make_pat(self: Box
<Self>) -> Option
<P
<ast
::Pat
>> {
374 if let Some(p
) = self.pat
{
377 if let Some(e
) = self.expr
{
378 if let ast
::ExprKind
::Lit(_
) = e
.node
{
379 return Some(P(ast
::Pat
{
380 id
: ast
::DUMMY_NODE_ID
,
382 node
: PatKind
::Lit(e
),
389 fn make_ty(self: Box
<Self>) -> Option
<P
<ast
::Ty
>> {
394 /// Fill-in macro expansion result, to allow compilation to continue
395 /// after hitting errors.
396 #[derive(Copy, Clone)]
397 pub struct DummyResult
{
403 /// Create a default MacResult that can be anything.
405 /// Use this as a return value after hitting any errors and
406 /// calling `span_err`.
407 pub fn any(sp
: Span
) -> Box
<MacResult
+'
static> {
408 Box
::new(DummyResult { expr_only: false, span: sp }
)
411 /// Create a default MacResult that can only be an expression.
413 /// Use this for macros that must expand to an expression, so even
414 /// if an error is encountered internally, the user will receive
415 /// an error that they also used it in the wrong place.
416 pub fn expr(sp
: Span
) -> Box
<MacResult
+'
static> {
417 Box
::new(DummyResult { expr_only: true, span: sp }
)
420 /// A plain dummy expression.
421 pub fn raw_expr(sp
: Span
) -> P
<ast
::Expr
> {
423 id
: ast
::DUMMY_NODE_ID
,
424 node
: ast
::ExprKind
::Lit(P(codemap
::respan(sp
, ast
::LitKind
::Bool(false)))),
426 attrs
: ast
::ThinVec
::new(),
430 /// A plain dummy pattern.
431 pub fn raw_pat(sp
: Span
) -> ast
::Pat
{
433 id
: ast
::DUMMY_NODE_ID
,
439 pub fn raw_ty(sp
: Span
) -> P
<ast
::Ty
> {
441 id
: ast
::DUMMY_NODE_ID
,
442 node
: ast
::TyKind
::Infer
,
448 impl MacResult
for DummyResult
{
449 fn make_expr(self: Box
<DummyResult
>) -> Option
<P
<ast
::Expr
>> {
450 Some(DummyResult
::raw_expr(self.span
))
453 fn make_pat(self: Box
<DummyResult
>) -> Option
<P
<ast
::Pat
>> {
454 Some(P(DummyResult
::raw_pat(self.span
)))
457 fn make_items(self: Box
<DummyResult
>) -> Option
<SmallVector
<P
<ast
::Item
>>> {
458 // this code needs a comment... why not always just return the Some() ?
462 Some(SmallVector
::new())
466 fn make_impl_items(self: Box
<DummyResult
>) -> Option
<SmallVector
<ast
::ImplItem
>> {
470 Some(SmallVector
::new())
474 fn make_trait_items(self: Box
<DummyResult
>) -> Option
<SmallVector
<ast
::TraitItem
>> {
478 Some(SmallVector
::new())
482 fn make_stmts(self: Box
<DummyResult
>) -> Option
<SmallVector
<ast
::Stmt
>> {
483 Some(SmallVector
::one(ast
::Stmt
{
484 id
: ast
::DUMMY_NODE_ID
,
485 node
: ast
::StmtKind
::Expr(DummyResult
::raw_expr(self.span
)),
490 fn make_ty(self: Box
<DummyResult
>) -> Option
<P
<ast
::Ty
>> {
491 Some(DummyResult
::raw_ty(self.span
))
495 pub type BuiltinDeriveFn
=
496 for<'cx
> fn(&'cx
mut ExtCtxt
, Span
, &MetaItem
, &Annotatable
, &mut FnMut(Annotatable
));
498 /// Represents different kinds of macro invocations that can be resolved.
499 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
501 /// A bang macro - foo!()
503 /// An attribute macro - #[foo]
505 /// A derive attribute macro - #[derive(Foo)]
509 /// An enum representing the different kinds of syntax extensions.
510 pub enum SyntaxExtension
{
511 /// A syntax extension that is attached to an item and creates new items
514 /// `#[derive(...)]` is a `MultiItemDecorator`.
516 /// Prefer ProcMacro or MultiModifier since they are more flexible.
517 MultiDecorator(Box
<MultiItemDecorator
>),
519 /// A syntax extension that is attached to an item and modifies it
520 /// in-place. Also allows decoration, i.e., creating new items.
521 MultiModifier(Box
<MultiItemModifier
>),
523 /// A function-like procedural macro. TokenStream -> TokenStream.
524 ProcMacro(Box
<ProcMacro
>),
526 /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
527 /// The first TokenSteam is the attribute, the second is the annotated item.
528 /// Allows modification of the input items and adding new items, similar to
529 /// MultiModifier, but uses TokenStreams, rather than AST nodes.
530 AttrProcMacro(Box
<AttrProcMacro
>),
532 /// A normal, function-like syntax extension.
534 /// `bytes!` is a `NormalTT`.
536 expander
: Box
<TTMacroExpander
>,
537 def_info
: Option
<(ast
::NodeId
, Span
)>,
538 /// Whether the contents of the macro can
539 /// directly use `#[unstable]` things (true == yes).
540 allow_internal_unstable
: bool
,
541 /// Whether the contents of the macro can use `unsafe`
542 /// without triggering the `unsafe_code` lint.
543 allow_internal_unsafe
: bool
,
546 /// A function-like syntax extension that has an extra ident before
549 IdentTT(Box
<IdentMacroExpander
>, Option
<Span
>, bool
),
551 /// An attribute-like procedural macro. TokenStream -> TokenStream.
552 /// The input is the annotated item.
553 /// Allows generating code to implement a Trait for a given struct
555 ProcMacroDerive(Box
<MultiItemModifier
>, Vec
<Symbol
> /* inert attribute names */),
557 /// An attribute-like procedural macro that derives a builtin trait.
558 BuiltinDerive(BuiltinDeriveFn
),
560 /// A declarative macro, e.g. `macro m() {}`.
562 /// The second element is the definition site span.
563 DeclMacro(Box
<TTMacroExpander
>, Option
<(ast
::NodeId
, Span
)>),
566 impl SyntaxExtension
{
567 /// Return which kind of macro calls this syntax extension.
568 pub fn kind(&self) -> MacroKind
{
570 SyntaxExtension
::DeclMacro(..) |
571 SyntaxExtension
::NormalTT { .. }
|
572 SyntaxExtension
::IdentTT(..) |
573 SyntaxExtension
::ProcMacro(..) =>
575 SyntaxExtension
::MultiDecorator(..) |
576 SyntaxExtension
::MultiModifier(..) |
577 SyntaxExtension
::AttrProcMacro(..) =>
579 SyntaxExtension
::ProcMacroDerive(..) |
580 SyntaxExtension
::BuiltinDerive(..) =>
585 pub fn is_modern(&self) -> bool
{
587 SyntaxExtension
::DeclMacro(..) |
588 SyntaxExtension
::ProcMacro(..) |
589 SyntaxExtension
::AttrProcMacro(..) |
590 SyntaxExtension
::ProcMacroDerive(..) => true,
596 pub type NamedSyntaxExtension
= (Name
, SyntaxExtension
);
599 fn next_node_id(&mut self) -> ast
::NodeId
;
600 fn get_module_scope(&mut self, id
: ast
::NodeId
) -> Mark
;
601 fn eliminate_crate_var(&mut self, item
: P
<ast
::Item
>) -> P
<ast
::Item
>;
602 fn is_whitelisted_legacy_custom_derive(&self, name
: Name
) -> bool
;
604 fn visit_expansion(&mut self, mark
: Mark
, expansion
: &Expansion
, derives
: &[Mark
]);
605 fn add_builtin(&mut self, ident
: ast
::Ident
, ext
: Rc
<SyntaxExtension
>);
607 fn resolve_imports(&mut self);
608 // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
609 fn find_legacy_attr_invoc(&mut self, attrs
: &mut Vec
<Attribute
>) -> Option
<Attribute
>;
610 fn resolve_invoc(&mut self, invoc
: &mut Invocation
, scope
: Mark
, force
: bool
)
611 -> Result
<Option
<Rc
<SyntaxExtension
>>, Determinacy
>;
612 fn resolve_macro(&mut self, scope
: Mark
, path
: &ast
::Path
, kind
: MacroKind
, force
: bool
)
613 -> Result
<Rc
<SyntaxExtension
>, Determinacy
>;
614 fn check_unused_macros(&self);
617 #[derive(Copy, Clone, Debug, PartialEq)]
618 pub enum Determinacy
{
623 pub struct DummyResolver
;
625 impl Resolver
for DummyResolver
{
626 fn next_node_id(&mut self) -> ast
::NodeId { ast::DUMMY_NODE_ID }
627 fn get_module_scope(&mut self, _id
: ast
::NodeId
) -> Mark { Mark::root() }
628 fn eliminate_crate_var(&mut self, item
: P
<ast
::Item
>) -> P
<ast
::Item
> { item }
629 fn is_whitelisted_legacy_custom_derive(&self, _name
: Name
) -> bool { false }
631 fn visit_expansion(&mut self, _invoc
: Mark
, _expansion
: &Expansion
, _derives
: &[Mark
]) {}
632 fn add_builtin(&mut self, _ident
: ast
::Ident
, _ext
: Rc
<SyntaxExtension
>) {}
634 fn resolve_imports(&mut self) {}
635 fn find_legacy_attr_invoc(&mut self, _attrs
: &mut Vec
<Attribute
>) -> Option
<Attribute
> { None }
636 fn resolve_invoc(&mut self, _invoc
: &mut Invocation
, _scope
: Mark
, _force
: bool
)
637 -> Result
<Option
<Rc
<SyntaxExtension
>>, Determinacy
> {
638 Err(Determinacy
::Determined
)
640 fn resolve_macro(&mut self, _scope
: Mark
, _path
: &ast
::Path
, _kind
: MacroKind
,
641 _force
: bool
) -> Result
<Rc
<SyntaxExtension
>, Determinacy
> {
642 Err(Determinacy
::Determined
)
644 fn check_unused_macros(&self) {}
648 pub struct ModuleData
{
649 pub mod_path
: Vec
<ast
::Ident
>,
650 pub directory
: PathBuf
,
654 pub struct ExpansionData
{
657 pub module
: Rc
<ModuleData
>,
658 pub directory_ownership
: DirectoryOwnership
,
661 /// One of these is made during expansion and incrementally updated as we go;
662 /// when a macro expansion occurs, the resulting nodes have the `backtrace()
663 /// -> expn_info` of their expansion context stored into their span.
664 pub struct ExtCtxt
<'a
> {
665 pub parse_sess
: &'a parse
::ParseSess
,
666 pub ecfg
: expand
::ExpansionConfig
<'a
>,
667 pub crate_root
: Option
<&'
static str>,
668 pub resolver
: &'a
mut Resolver
,
669 pub resolve_err_count
: usize,
670 pub current_expansion
: ExpansionData
,
671 pub expansions
: HashMap
<Span
, Vec
<String
>>,
674 impl<'a
> ExtCtxt
<'a
> {
675 pub fn new(parse_sess
: &'a parse
::ParseSess
,
676 ecfg
: expand
::ExpansionConfig
<'a
>,
677 resolver
: &'a
mut Resolver
)
684 resolve_err_count
: 0,
685 current_expansion
: ExpansionData
{
688 module
: Rc
::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }
),
689 directory_ownership
: DirectoryOwnership
::Owned
,
691 expansions
: HashMap
::new(),
695 /// Returns a `Folder` for deeply expanding all macros in an AST node.
696 pub fn expander
<'b
>(&'b
mut self) -> expand
::MacroExpander
<'b
, 'a
> {
697 expand
::MacroExpander
::new(self, false)
700 /// Returns a `Folder` that deeply expands all macros and assigns all node ids in an AST node.
701 /// Once node ids are assigned, the node may not be expanded, removed, or otherwise modified.
702 pub fn monotonic_expander
<'b
>(&'b
mut self) -> expand
::MacroExpander
<'b
, 'a
> {
703 expand
::MacroExpander
::new(self, true)
706 pub fn new_parser_from_tts(&self, tts
: &[tokenstream
::TokenTree
]) -> parser
::Parser
<'a
> {
707 parse
::stream_to_parser(self.parse_sess
, tts
.iter().cloned().collect())
709 pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() }
710 pub fn parse_sess(&self) -> &'a parse
::ParseSess { self.parse_sess }
711 pub fn cfg(&self) -> &ast
::CrateConfig { &self.parse_sess.config }
712 pub fn call_site(&self) -> Span
{
713 match self.current_expansion
.mark
.expn_info() {
714 Some(expn_info
) => expn_info
.call_site
,
718 pub fn backtrace(&self) -> SyntaxContext
{
719 SyntaxContext
::empty().apply_mark(self.current_expansion
.mark
)
722 /// Returns span for the macro which originally caused the current expansion to happen.
724 /// Stops backtracing at include! boundary.
725 pub fn expansion_cause(&self) -> Option
<Span
> {
726 let mut ctxt
= self.backtrace();
727 let mut last_macro
= None
;
729 if ctxt
.outer().expn_info().map_or(None
, |info
| {
730 if info
.callee
.name() == "include" {
731 // Stop going up the backtrace once include! is encountered
734 ctxt
= info
.call_site
.ctxt
;
735 last_macro
= Some(info
.call_site
);
744 pub fn struct_span_warn(&self,
747 -> DiagnosticBuilder
<'a
> {
748 self.parse_sess
.span_diagnostic
.struct_span_warn(sp
, msg
)
750 pub fn struct_span_err(&self,
753 -> DiagnosticBuilder
<'a
> {
754 self.parse_sess
.span_diagnostic
.struct_span_err(sp
, msg
)
756 pub fn struct_span_fatal(&self,
759 -> DiagnosticBuilder
<'a
> {
760 self.parse_sess
.span_diagnostic
.struct_span_fatal(sp
, msg
)
763 /// Emit `msg` attached to `sp`, and stop compilation immediately.
765 /// `span_err` should be strongly preferred where-ever possible:
766 /// this should *only* be used when
767 /// - continuing has a high risk of flow-on errors (e.g. errors in
768 /// declaring a macro would cause all uses of that macro to
769 /// complain about "undefined macro"), or
770 /// - there is literally nothing else that can be done (however,
771 /// in most cases one can construct a dummy expression/item to
772 /// substitute; we never hit resolve/type-checking so the dummy
773 /// value doesn't have to match anything)
774 pub fn span_fatal(&self, sp
: Span
, msg
: &str) -> ! {
775 panic
!(self.parse_sess
.span_diagnostic
.span_fatal(sp
, msg
));
778 /// Emit `msg` attached to `sp`, without immediately stopping
781 /// Compilation will be stopped in the near future (at the end of
782 /// the macro expansion phase).
783 pub fn span_err(&self, sp
: Span
, msg
: &str) {
784 self.parse_sess
.span_diagnostic
.span_err(sp
, msg
);
786 pub fn span_warn(&self, sp
: Span
, msg
: &str) {
787 self.parse_sess
.span_diagnostic
.span_warn(sp
, msg
);
789 pub fn span_unimpl(&self, sp
: Span
, msg
: &str) -> ! {
790 self.parse_sess
.span_diagnostic
.span_unimpl(sp
, msg
);
792 pub fn span_bug(&self, sp
: Span
, msg
: &str) -> ! {
793 self.parse_sess
.span_diagnostic
.span_bug(sp
, msg
);
795 pub fn trace_macros_diag(&self) {
796 for (sp
, notes
) in self.expansions
.iter() {
797 let mut db
= self.parse_sess
.span_diagnostic
.span_note_diag(*sp
, "trace_macro");
804 pub fn bug(&self, msg
: &str) -> ! {
805 self.parse_sess
.span_diagnostic
.bug(msg
);
807 pub fn trace_macros(&self) -> bool
{
810 pub fn set_trace_macros(&mut self, x
: bool
) {
811 self.ecfg
.trace_mac
= x
813 pub fn ident_of(&self, st
: &str) -> ast
::Ident
{
814 ast
::Ident
::from_str(st
)
816 pub fn std_path(&self, components
: &[&str]) -> Vec
<ast
::Ident
> {
817 let mut v
= Vec
::new();
818 if let Some(s
) = self.crate_root
{
819 v
.push(self.ident_of(s
));
821 v
.extend(components
.iter().map(|s
| self.ident_of(s
)));
824 pub fn name_of(&self, st
: &str) -> ast
::Name
{
828 pub fn check_unused_macros(&self) {
829 self.resolver
.check_unused_macros();
833 /// Extract a string literal from the macro expanded version of `expr`,
834 /// emitting `err_msg` if `expr` is not a string literal. This does not stop
835 /// compilation on error, merely emits a non-fatal error and returns None.
836 pub fn expr_to_spanned_string(cx
: &mut ExtCtxt
, expr
: P
<ast
::Expr
>, err_msg
: &str)
837 -> Option
<Spanned
<(Symbol
, ast
::StrStyle
)>> {
838 // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation.
839 let expr
= expr
.map(|mut expr
| {
840 expr
.span
.ctxt
= expr
.span
.ctxt
.apply_mark(cx
.current_expansion
.mark
);
844 // we want to be able to handle e.g. concat("foo", "bar")
845 let expr
= cx
.expander().fold_expr(expr
);
847 ast
::ExprKind
::Lit(ref l
) => match l
.node
{
848 ast
::LitKind
::Str(s
, style
) => return Some(respan(expr
.span
, (s
, style
))),
849 _
=> cx
.span_err(l
.span
, err_msg
)
851 _
=> cx
.span_err(expr
.span
, err_msg
)
856 pub fn expr_to_string(cx
: &mut ExtCtxt
, expr
: P
<ast
::Expr
>, err_msg
: &str)
857 -> Option
<(Symbol
, ast
::StrStyle
)> {
858 expr_to_spanned_string(cx
, expr
, err_msg
).map(|s
| s
.node
)
861 /// Non-fatally assert that `tts` is empty. Note that this function
862 /// returns even when `tts` is non-empty, macros that *need* to stop
863 /// compilation should call
864 /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
865 /// done as rarely as possible).
866 pub fn check_zero_tts(cx
: &ExtCtxt
,
868 tts
: &[tokenstream
::TokenTree
],
871 cx
.span_err(sp
, &format
!("{} takes no arguments", name
));
875 /// Extract the string literal from the first token of `tts`. If this
876 /// is not a string literal, emit an error and return None.
877 pub fn get_single_str_from_tts(cx
: &mut ExtCtxt
,
879 tts
: &[tokenstream
::TokenTree
],
882 let mut p
= cx
.new_parser_from_tts(tts
);
883 if p
.token
== token
::Eof
{
884 cx
.span_err(sp
, &format
!("{} takes 1 argument", name
));
887 let ret
= panictry
!(p
.parse_expr());
888 if p
.token
!= token
::Eof
{
889 cx
.span_err(sp
, &format
!("{} takes 1 argument", name
));
891 expr_to_string(cx
, ret
, "argument must be a string literal").map(|(s
, _
)| {
896 /// Extract comma-separated expressions from `tts`. If there is a
897 /// parsing error, emit a non-fatal error and return None.
898 pub fn get_exprs_from_tts(cx
: &mut ExtCtxt
,
900 tts
: &[tokenstream
::TokenTree
]) -> Option
<Vec
<P
<ast
::Expr
>>> {
901 let mut p
= cx
.new_parser_from_tts(tts
);
902 let mut es
= Vec
::new();
903 while p
.token
!= token
::Eof
{
904 es
.push(cx
.expander().fold_expr(panictry
!(p
.parse_expr())));
905 if p
.eat(&token
::Comma
) {
908 if p
.token
!= token
::Eof
{
909 cx
.span_err(sp
, "expected token: `,`");