syntax: Factor out common fields from SyntaxExtension
variants
This commit is contained in:
parent
704ab2ba10
commit
961ba8f9ef
@ -132,7 +132,7 @@ The advantages over a simple `fn(&str) -> u32` are:
|
||||
In addition to procedural macros, you can define new
|
||||
[`derive`](../../reference/attributes/derive.md)-like attributes and other kinds
|
||||
of extensions. See `Registry::register_syntax_extension` and the
|
||||
`SyntaxExtension` enum. For a more involved macro example, see
|
||||
`SyntaxExtension` struct. For a more involved macro example, see
|
||||
[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs).
|
||||
|
||||
|
||||
|
@ -91,7 +91,7 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> {
|
||||
call_site: item.span, // use the call site of the static
|
||||
def_site: None,
|
||||
format: MacroAttribute(Symbol::intern(name)),
|
||||
allow_internal_unstable: Some(vec![sym::rustc_attrs].into()),
|
||||
allow_internal_unstable: Some([sym::rustc_attrs][..].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: self.sess.edition,
|
||||
|
@ -26,7 +26,7 @@ use std::{cmp, fs};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
use syntax::visit;
|
||||
use syntax::{span_err, span_fatal};
|
||||
@ -611,33 +611,31 @@ impl<'a> CrateLoader<'a> {
|
||||
};
|
||||
|
||||
let extensions = decls.iter().map(|&decl| {
|
||||
match decl {
|
||||
let (name, kind, helper_attrs) = match decl {
|
||||
ProcMacro::CustomDerive { trait_name, attributes, client } => {
|
||||
let attrs = attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
|
||||
(trait_name, SyntaxExtension::Derive(
|
||||
Box::new(ProcMacroDerive {
|
||||
client,
|
||||
attrs: attrs.clone(),
|
||||
}),
|
||||
attrs,
|
||||
root.edition,
|
||||
))
|
||||
let helper_attrs =
|
||||
attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
|
||||
(
|
||||
trait_name,
|
||||
SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive {
|
||||
client, attrs: helper_attrs.clone()
|
||||
})),
|
||||
helper_attrs,
|
||||
)
|
||||
}
|
||||
ProcMacro::Attr { name, client } => {
|
||||
(name, SyntaxExtension::Attr(
|
||||
Box::new(AttrProcMacro { client }),
|
||||
root.edition,
|
||||
))
|
||||
}
|
||||
ProcMacro::Bang { name, client } => {
|
||||
(name, SyntaxExtension::Bang {
|
||||
expander: Box::new(BangProcMacro { client }),
|
||||
allow_internal_unstable: None,
|
||||
edition: root.edition,
|
||||
})
|
||||
}
|
||||
}
|
||||
}).map(|(name, ext)| (Symbol::intern(name), Lrc::new(ext))).collect();
|
||||
ProcMacro::Attr { name, client } => (
|
||||
name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()
|
||||
),
|
||||
ProcMacro::Bang { name, client } => (
|
||||
name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
|
||||
)
|
||||
};
|
||||
|
||||
(Symbol::intern(name), Lrc::new(SyntaxExtension {
|
||||
helper_attrs,
|
||||
..SyntaxExtension::default(kind, root.edition)
|
||||
}))
|
||||
}).collect();
|
||||
|
||||
// Intentionally leak the dynamic library. We can't ever unload it
|
||||
// since the library can make things that will live arbitrarily long.
|
||||
|
@ -30,9 +30,11 @@ use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::source_map;
|
||||
use syntax::edition::Edition;
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::parse::source_file_to_stream;
|
||||
use syntax::parse::parser::emit_unclosed_delims;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
use syntax_ext::proc_macro_impl::BangProcMacro;
|
||||
use syntax_pos::{Span, NO_EXPANSION, FileName};
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
|
||||
@ -427,14 +429,11 @@ impl cstore::CStore {
|
||||
if let Some(ref proc_macros) = data.proc_macros {
|
||||
return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
|
||||
} else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote {
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax_ext::proc_macro_impl::BangProcMacro;
|
||||
|
||||
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
|
||||
let ext = SyntaxExtension::Bang {
|
||||
expander: Box::new(BangProcMacro { client }),
|
||||
allow_internal_unstable: Some(vec![sym::proc_macro_def_site].into()),
|
||||
edition: data.root.edition,
|
||||
let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }));
|
||||
let ext = SyntaxExtension {
|
||||
allow_internal_unstable: Some([sym::proc_macro_def_site][..].into()),
|
||||
..SyntaxExtension::default(kind, data.root.edition)
|
||||
};
|
||||
return LoadedMacro::ProcMacro(Lrc::new(ext));
|
||||
}
|
||||
|
@ -511,8 +511,9 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
if !self.is_proc_macro(index) {
|
||||
self.entry(index).kind.def_kind()
|
||||
} else {
|
||||
let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind();
|
||||
Some(DefKind::Macro(kind))
|
||||
Some(DefKind::Macro(
|
||||
self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.macro_kind()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -739,7 +740,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
if id == CRATE_DEF_INDEX {
|
||||
for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
|
||||
let res = Res::Def(
|
||||
DefKind::Macro(ext.kind()),
|
||||
DefKind::Macro(ext.macro_kind()),
|
||||
self.local_def_id(DefIndex::from_proc_macro_index(id)),
|
||||
);
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
|
@ -4,9 +4,8 @@ use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
|
||||
use rustc::session::Session;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
|
||||
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension};
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension};
|
||||
use syntax::ext::base::MacroExpanderFn;
|
||||
use syntax::ext::hygiene::Transparency;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
use syntax::ast;
|
||||
use syntax::feature_gate::AttributeType;
|
||||
@ -89,8 +88,8 @@ impl<'a> Registry<'a> {
|
||||
if name == sym::macro_rules {
|
||||
panic!("user-defined macros may not be named `macro_rules`");
|
||||
}
|
||||
if let SyntaxExtension::LegacyBang { def_info: ref mut def_info @ None, .. } = extension {
|
||||
*def_info = Some((ast::CRATE_NODE_ID, self.krate_span));
|
||||
if extension.def_info.is_none() {
|
||||
extension.def_info = Some((ast::CRATE_NODE_ID, self.krate_span));
|
||||
}
|
||||
self.syntax_exts.push((name, extension));
|
||||
}
|
||||
@ -98,19 +97,12 @@ impl<'a> Registry<'a> {
|
||||
/// Register a macro of the usual kind.
|
||||
///
|
||||
/// This is a convenience wrapper for `register_syntax_extension`.
|
||||
/// It builds for you a `SyntaxExtension::LegacyBang` that calls `expander`,
|
||||
/// It builds for you a `SyntaxExtensionKind::LegacyBang` that calls `expander`,
|
||||
/// and also takes care of interning the macro's name.
|
||||
pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
|
||||
self.register_syntax_extension(Symbol::intern(name), SyntaxExtension::LegacyBang {
|
||||
expander: Box::new(expander),
|
||||
def_info: None,
|
||||
transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition: self.sess.edition(),
|
||||
});
|
||||
let kind = SyntaxExtensionKind::LegacyBang(Box::new(expander));
|
||||
let ext = SyntaxExtension::default(kind, self.sess.edition());
|
||||
self.register_syntax_extension(Symbol::intern(name), ext);
|
||||
}
|
||||
|
||||
/// Register a compiler lint pass.
|
||||
|
@ -29,7 +29,7 @@ use syntax::attr;
|
||||
|
||||
use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
|
||||
use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::ext::base::Determinacy::Undetermined;
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::ext::tt::macro_rules;
|
||||
@ -772,9 +772,12 @@ impl<'a> Resolver<'a> {
|
||||
pub fn get_macro(&mut self, res: Res) -> Lrc<SyntaxExtension> {
|
||||
let def_id = match res {
|
||||
Res::Def(DefKind::Macro(..), def_id) => def_id,
|
||||
Res::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::NonMacroAttr {
|
||||
mark_used: attr_kind == NonMacroAttrKind::Tool,
|
||||
}),
|
||||
Res::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::default(
|
||||
SyntaxExtensionKind::NonMacroAttr {
|
||||
mark_used: attr_kind == NonMacroAttrKind::Tool
|
||||
},
|
||||
self.session.edition(),
|
||||
)),
|
||||
_ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
|
||||
};
|
||||
if let Some(ext) = self.macro_map.get(&def_id) {
|
||||
|
@ -15,7 +15,7 @@ use syntax::ast::{self, Ident};
|
||||
use syntax::attr;
|
||||
use syntax::errors::DiagnosticBuilder;
|
||||
use syntax::ext::base::{self, Determinacy};
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::ext::tt::macro_rules;
|
||||
@ -174,7 +174,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
krate: CrateNum::BuiltinMacros,
|
||||
index: DefIndex::from(self.macro_map.len()),
|
||||
};
|
||||
let kind = ext.kind();
|
||||
let kind = ext.macro_kind();
|
||||
self.macro_map.insert(def_id, ext);
|
||||
let binding = self.arenas.alloc_name_binding(NameBinding {
|
||||
kind: NameBindingKind::Res(Res::Def(DefKind::Macro(kind), def_id), false),
|
||||
@ -211,7 +211,8 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
Ok((res, ext)) => (res, ext),
|
||||
Err(Determinacy::Determined) if kind == MacroKind::Attr => {
|
||||
// Replace unresolved attributes with used inert attributes for better recovery.
|
||||
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr { mark_used: true })));
|
||||
let kind = SyntaxExtensionKind::NonMacroAttr { mark_used: true };
|
||||
return Ok(Some(Lrc::new(SyntaxExtension::default(kind, self.session.edition()))));
|
||||
}
|
||||
Err(determinacy) => return Err(determinacy),
|
||||
};
|
||||
@ -226,7 +227,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
|
||||
self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark,
|
||||
normal_module_def_id);
|
||||
invoc.expansion_data.mark.set_default_transparency(ext.default_transparency());
|
||||
invoc.expansion_data.mark.set_default_transparency(ext.default_transparency);
|
||||
}
|
||||
|
||||
Ok(Some(ext))
|
||||
@ -241,11 +242,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
|
||||
fn check_unused_macros(&self) {
|
||||
for did in self.unused_macros.iter() {
|
||||
let id_span = match *self.macro_map[did] {
|
||||
SyntaxExtension::LegacyBang { def_info, .. } => def_info,
|
||||
_ => None,
|
||||
};
|
||||
if let Some((id, span)) = id_span {
|
||||
if let Some((id, span)) = self.macro_map[did].def_info {
|
||||
let lint = lint::builtin::UNUSED_MACROS;
|
||||
let msg = "unused macro definition";
|
||||
self.session.buffer_lint(lint, id, span, msg);
|
||||
@ -585,17 +582,12 @@ impl<'a> Resolver<'a> {
|
||||
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
|
||||
match self.resolve_macro_to_res(derive, MacroKind::Derive,
|
||||
&parent_scope, true, force) {
|
||||
Ok((_, ext)) => {
|
||||
if let SyntaxExtension::Derive(_, helpers, _) = &*ext {
|
||||
if helpers.contains(&ident.name) {
|
||||
let binding =
|
||||
(Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
||||
ty::Visibility::Public, derive.span, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
result = Ok((binding, Flags::empty()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok((_, ext)) => if ext.helper_attrs.contains(&ident.name) {
|
||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
||||
ty::Visibility::Public, derive.span, Mark::root())
|
||||
.to_name_binding(self.arenas);
|
||||
result = Ok((binding, Flags::empty()));
|
||||
break;
|
||||
}
|
||||
Err(Determinacy::Determined) => {}
|
||||
Err(Determinacy::Undetermined) =>
|
||||
|
@ -3,7 +3,7 @@
|
||||
use std::iter::once;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax::symbol::sym;
|
||||
use syntax_pos::Span;
|
||||
|
||||
@ -470,18 +470,12 @@ fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemE
|
||||
})
|
||||
}
|
||||
LoadedMacro::ProcMacro(ext) => {
|
||||
let helpers = match &*ext {
|
||||
&SyntaxExtension::Derive(_, ref syms, ..) => { syms.clean(cx) }
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
clean::ProcMacroItem(clean::ProcMacro {
|
||||
kind: ext.kind(),
|
||||
helpers,
|
||||
kind: ext.macro_kind(),
|
||||
helpers: ext.helper_attrs.clean(cx),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// A trait's generics clause actually contains all of the predicates for all of
|
||||
|
@ -423,7 +423,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||
|
||||
/// Resolves a string as a macro.
|
||||
fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtensionKind};
|
||||
let segment = ast::PathSegment::from_ident(Ident::from_str(path_str));
|
||||
let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
|
||||
cx.enter_resolver(|resolver| {
|
||||
@ -433,7 +433,7 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
|
||||
if let Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) = res {
|
||||
// skip proc-macro stubs, they'll cause `get_macro` to crash
|
||||
} else {
|
||||
if let SyntaxExtension::LegacyBang { .. } = *resolver.get_macro(res) {
|
||||
if let SyntaxExtensionKind::LegacyBang(..) = resolver.get_macro(res).kind {
|
||||
return Some(res.map_id(|_| panic!("unexpected id")));
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use crate::tokenstream::{self, TokenStream};
|
||||
use errors::{DiagnosticBuilder, DiagnosticId};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
|
||||
use syntax_pos::hygiene::{ExpnInfo, ExpnFormat};
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::{self, Lrc};
|
||||
@ -548,37 +549,19 @@ impl MacroKind {
|
||||
}
|
||||
}
|
||||
|
||||
/// An enum representing the different kinds of syntax extensions.
|
||||
pub enum SyntaxExtension {
|
||||
/// A syntax extension kind.
|
||||
pub enum SyntaxExtensionKind {
|
||||
/// A token-based function-like macro.
|
||||
Bang {
|
||||
Bang(
|
||||
/// An expander with signature TokenStream -> TokenStream.
|
||||
expander: Box<dyn ProcMacro + sync::Sync + sync::Send>,
|
||||
/// Whitelist of unstable features that are treated as stable inside this macro.
|
||||
allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||
/// Edition of the crate in which this macro is defined.
|
||||
edition: Edition,
|
||||
},
|
||||
Box<dyn ProcMacro + sync::Sync + sync::Send>,
|
||||
),
|
||||
|
||||
/// An AST-based function-like macro.
|
||||
LegacyBang {
|
||||
LegacyBang(
|
||||
/// An expander with signature TokenStream -> AST.
|
||||
expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
|
||||
/// Some info about the macro's definition point.
|
||||
def_info: Option<(ast::NodeId, Span)>,
|
||||
/// Hygienic properties of identifiers produced by this macro.
|
||||
transparency: Transparency,
|
||||
/// Whitelist of unstable features that are treated as stable inside this macro.
|
||||
allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||
/// Suppresses the `unsafe_code` lint for code produced by this macro.
|
||||
allow_internal_unsafe: bool,
|
||||
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
|
||||
local_inner_macros: bool,
|
||||
/// The macro's feature name and tracking issue number if it is unstable.
|
||||
unstable_feature: Option<(Symbol, u32)>,
|
||||
/// Edition of the crate in which this macro is defined.
|
||||
edition: Edition,
|
||||
},
|
||||
Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
|
||||
),
|
||||
|
||||
/// A token-based attribute macro.
|
||||
Attr(
|
||||
@ -586,8 +569,6 @@ pub enum SyntaxExtension {
|
||||
/// The first TokenSteam is the attribute itself, the second is the annotated item.
|
||||
/// The produced TokenSteam replaces the input TokenSteam.
|
||||
Box<dyn AttrProcMacro + sync::Sync + sync::Send>,
|
||||
/// Edition of the crate in which this macro is defined.
|
||||
Edition,
|
||||
),
|
||||
|
||||
/// An AST-based attribute macro.
|
||||
@ -599,7 +580,8 @@ pub enum SyntaxExtension {
|
||||
),
|
||||
|
||||
/// A trivial attribute "macro" that does nothing,
|
||||
/// only keeps the attribute and marks it as known.
|
||||
/// only keeps the attribute and marks it as inert,
|
||||
/// thus making it ineligible for further expansion.
|
||||
NonMacroAttr {
|
||||
/// Suppresses the `unused_attributes` lint for this attribute.
|
||||
mark_used: bool,
|
||||
@ -610,10 +592,6 @@ pub enum SyntaxExtension {
|
||||
/// An expander with signature TokenStream -> TokenStream (not yet).
|
||||
/// The produced TokenSteam is appended to the input TokenSteam.
|
||||
Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
|
||||
/// Names of helper attributes registered by this macro.
|
||||
Vec<Symbol>,
|
||||
/// Edition of the crate in which this macro is defined.
|
||||
Edition,
|
||||
),
|
||||
|
||||
/// An AST-based derive macro.
|
||||
@ -624,42 +602,90 @@ pub enum SyntaxExtension {
|
||||
),
|
||||
}
|
||||
|
||||
/// A struct representing a macro definition in "lowered" form ready for expansion.
|
||||
pub struct SyntaxExtension {
|
||||
/// A syntax extension kind.
|
||||
pub kind: SyntaxExtensionKind,
|
||||
/// Some info about the macro's definition point.
|
||||
pub def_info: Option<(ast::NodeId, Span)>,
|
||||
/// Hygienic properties of spans produced by this macro by default.
|
||||
pub default_transparency: Transparency,
|
||||
/// Whitelist of unstable features that are treated as stable inside this macro.
|
||||
pub allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||
/// Suppresses the `unsafe_code` lint for code produced by this macro.
|
||||
pub allow_internal_unsafe: bool,
|
||||
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
|
||||
pub local_inner_macros: bool,
|
||||
/// The macro's feature name and tracking issue number if it is unstable.
|
||||
pub unstable_feature: Option<(Symbol, u32)>,
|
||||
/// Names of helper attributes registered by this macro.
|
||||
pub helper_attrs: Vec<Symbol>,
|
||||
/// Edition of the crate in which this macro is defined.
|
||||
pub edition: Edition,
|
||||
}
|
||||
|
||||
impl SyntaxExtensionKind {
|
||||
/// When a syntax extension is constructed,
|
||||
/// its transparency can often be inferred from its kind.
|
||||
fn default_transparency(&self) -> Transparency {
|
||||
match self {
|
||||
SyntaxExtensionKind::Bang(..) |
|
||||
SyntaxExtensionKind::Attr(..) |
|
||||
SyntaxExtensionKind::Derive(..) |
|
||||
SyntaxExtensionKind::NonMacroAttr { .. } => Transparency::Opaque,
|
||||
SyntaxExtensionKind::LegacyBang(..) |
|
||||
SyntaxExtensionKind::LegacyAttr(..) |
|
||||
SyntaxExtensionKind::LegacyDerive(..) => Transparency::SemiTransparent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SyntaxExtension {
|
||||
/// Returns which kind of macro calls this syntax extension.
|
||||
pub fn kind(&self) -> MacroKind {
|
||||
match *self {
|
||||
SyntaxExtension::Bang { .. } |
|
||||
SyntaxExtension::LegacyBang { .. } => MacroKind::Bang,
|
||||
SyntaxExtension::Attr(..) |
|
||||
SyntaxExtension::LegacyAttr(..) |
|
||||
SyntaxExtension::NonMacroAttr { .. } => MacroKind::Attr,
|
||||
SyntaxExtension::Derive(..) |
|
||||
SyntaxExtension::LegacyDerive(..) => MacroKind::Derive,
|
||||
pub fn macro_kind(&self) -> MacroKind {
|
||||
match self.kind {
|
||||
SyntaxExtensionKind::Bang(..) |
|
||||
SyntaxExtensionKind::LegacyBang(..) => MacroKind::Bang,
|
||||
SyntaxExtensionKind::Attr(..) |
|
||||
SyntaxExtensionKind::LegacyAttr(..) |
|
||||
SyntaxExtensionKind::NonMacroAttr { .. } => MacroKind::Attr,
|
||||
SyntaxExtensionKind::Derive(..) |
|
||||
SyntaxExtensionKind::LegacyDerive(..) => MacroKind::Derive,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_transparency(&self) -> Transparency {
|
||||
match *self {
|
||||
SyntaxExtension::LegacyBang { transparency, .. } => transparency,
|
||||
SyntaxExtension::Bang { .. } |
|
||||
SyntaxExtension::Attr(..) |
|
||||
SyntaxExtension::Derive(..) |
|
||||
SyntaxExtension::NonMacroAttr { .. } => Transparency::Opaque,
|
||||
SyntaxExtension::LegacyAttr(..) |
|
||||
SyntaxExtension::LegacyDerive(..) => Transparency::SemiTransparent,
|
||||
/// Constructs a syntax extension with default properties.
|
||||
pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension {
|
||||
SyntaxExtension {
|
||||
def_info: None,
|
||||
default_transparency: kind.default_transparency(),
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
helper_attrs: Vec::new(),
|
||||
edition,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edition(&self, default_edition: Edition) -> Edition {
|
||||
match *self {
|
||||
SyntaxExtension::Bang { edition, .. } |
|
||||
SyntaxExtension::LegacyBang { edition, .. } |
|
||||
SyntaxExtension::Attr(.., edition) |
|
||||
SyntaxExtension::Derive(.., edition) => edition,
|
||||
// Unstable legacy stuff
|
||||
SyntaxExtension::NonMacroAttr { .. } |
|
||||
SyntaxExtension::LegacyAttr(..) |
|
||||
SyntaxExtension::LegacyDerive(..) => default_edition,
|
||||
fn expn_format(&self, symbol: Symbol) -> ExpnFormat {
|
||||
match self.kind {
|
||||
SyntaxExtensionKind::Bang(..) |
|
||||
SyntaxExtensionKind::LegacyBang(..) => ExpnFormat::MacroBang(symbol),
|
||||
_ => ExpnFormat::MacroAttribute(symbol),
|
||||
}
|
||||
}
|
||||
|
||||
crate fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo {
|
||||
ExpnInfo {
|
||||
call_site,
|
||||
def_site: self.def_info.map(|(_, span)| span),
|
||||
format: self.expn_format(Symbol::intern(format)),
|
||||
allow_internal_unstable: self.allow_internal_unstable.clone(),
|
||||
allow_internal_unsafe: self.allow_internal_unsafe,
|
||||
local_inner_macros: self.local_inner_macros,
|
||||
edition: self.edition,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P
|
||||
call_site: span,
|
||||
def_site: None,
|
||||
format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
|
||||
allow_internal_unstable: Some(vec![sym::rustc_attrs, sym::structural_match].into()),
|
||||
allow_internal_unstable: Some([sym::rustc_attrs, sym::structural_match][..].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: cx.parse_sess.edition,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path};
|
||||
use crate::ast::{MacStmtStyle, StmtKind, ItemKind};
|
||||
use crate::attr::{self, HasAttrs};
|
||||
use crate::source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
|
||||
use crate::source_map::{dummy_spanned, respan};
|
||||
use crate::config::StripUnconfigured;
|
||||
use crate::ext::base::*;
|
||||
use crate::ext::derive::{add_derived_markers, collect_derives};
|
||||
@ -22,7 +22,6 @@ use crate::util::map_in_place::MapInPlace;
|
||||
use errors::{Applicability, FatalError};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use syntax_pos::{Span, DUMMY_SP, FileName};
|
||||
use syntax_pos::hygiene::ExpnFormat;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
@ -189,10 +188,10 @@ impl AstFragmentKind {
|
||||
}
|
||||
}
|
||||
|
||||
fn macro_bang_format(path: &ast::Path) -> ExpnFormat {
|
||||
// We don't want to format a path using pretty-printing,
|
||||
// `format!("{}", path)`, because that tries to insert
|
||||
// line-breaks and is slow.
|
||||
// We don't want to format a path using pretty-printing,
|
||||
// `format!("{}", path)`, because that tries to insert
|
||||
// line-breaks and is slow.
|
||||
fn fast_print_path(path: &ast::Path) -> String {
|
||||
let mut path_str = String::with_capacity(64);
|
||||
for (i, segment) in path.segments.iter().enumerate() {
|
||||
if i != 0 {
|
||||
@ -202,8 +201,7 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat {
|
||||
path_str.push_str(&segment.ident.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
MacroBang(Symbol::intern(&path_str))
|
||||
path_str
|
||||
}
|
||||
|
||||
pub struct Invocation {
|
||||
@ -388,8 +386,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
derives.push(mark);
|
||||
let item = match self.cx.resolver.resolve_macro_path(
|
||||
path, MacroKind::Derive, Mark::root(), Vec::new(), false) {
|
||||
Ok(ext) => match *ext {
|
||||
SyntaxExtension::LegacyDerive(..) => item_with_markers.clone(),
|
||||
Ok(ext) => match ext.kind {
|
||||
SyntaxExtensionKind::LegacyDerive(..) => item_with_markers.clone(),
|
||||
_ => item.clone(),
|
||||
},
|
||||
_ => item.clone(),
|
||||
@ -509,7 +507,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> {
|
||||
if invoc.fragment_kind == AstFragmentKind::ForeignItems &&
|
||||
!self.cx.ecfg.macros_in_extern_enabled() {
|
||||
if let SyntaxExtension::NonMacroAttr { .. } = *ext {} else {
|
||||
if let SyntaxExtensionKind::NonMacroAttr { .. } = ext.kind {} else {
|
||||
emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern,
|
||||
invoc.span(), GateIssue::Language,
|
||||
"macro invocations in `extern {}` blocks are experimental");
|
||||
@ -548,34 +546,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if let SyntaxExtension::NonMacroAttr { mark_used: false } = *ext {} else {
|
||||
// Macro attrs are always used when expanded,
|
||||
// non-macro attrs are considered used when the field says so.
|
||||
attr::mark_used(&attr);
|
||||
}
|
||||
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
|
||||
call_site: attr.span,
|
||||
def_site: None,
|
||||
format: MacroAttribute(Symbol::intern(&attr.path.to_string())),
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: ext.edition(self.cx.parse_sess.edition),
|
||||
});
|
||||
let expn_info = ext.expn_info(attr.span, &fast_print_path(&attr.path));
|
||||
invoc.expansion_data.mark.set_expn_info(expn_info);
|
||||
|
||||
match *ext {
|
||||
SyntaxExtension::NonMacroAttr { .. } => {
|
||||
match &ext.kind {
|
||||
SyntaxExtensionKind::NonMacroAttr { mark_used } => {
|
||||
attr::mark_known(&attr);
|
||||
if *mark_used {
|
||||
attr::mark_used(&attr);
|
||||
}
|
||||
item.visit_attrs(|attrs| attrs.push(attr));
|
||||
Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item)))
|
||||
}
|
||||
SyntaxExtension::LegacyAttr(ref mac) => {
|
||||
SyntaxExtensionKind::LegacyAttr(expander) => {
|
||||
let meta = attr.parse_meta(self.cx.parse_sess)
|
||||
.map_err(|mut e| { e.emit(); }).ok()?;
|
||||
let item = mac.expand(self.cx, attr.span, &meta, item);
|
||||
let item = expander.expand(self.cx, attr.span, &meta, item);
|
||||
Some(invoc.fragment_kind.expect_from_annotatables(item))
|
||||
}
|
||||
SyntaxExtension::Attr(ref mac, ..) => {
|
||||
SyntaxExtensionKind::Attr(expander) => {
|
||||
self.gate_proc_macro_attr_item(attr.span, &item);
|
||||
let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
|
||||
Annotatable::Item(item) => token::NtItem(item),
|
||||
@ -586,13 +575,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
Annotatable::Expr(expr) => token::NtExpr(expr),
|
||||
})), DUMMY_SP).into();
|
||||
let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
|
||||
let tok_result = mac.expand(self.cx, attr.span, input, item_tok);
|
||||
let tok_result = expander.expand(self.cx, attr.span, input, item_tok);
|
||||
let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind,
|
||||
&attr.path, attr.span);
|
||||
self.gate_proc_macro_expansion(attr.span, &res);
|
||||
res
|
||||
}
|
||||
SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => {
|
||||
SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
|
||||
self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path));
|
||||
self.cx.trace_macros_diag();
|
||||
invoc.fragment_kind.dummy(attr.span)
|
||||
@ -701,21 +690,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
let path = &mac.node.path;
|
||||
|
||||
let ident = ident.unwrap_or_else(|| Ident::invalid());
|
||||
let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture
|
||||
def_site_span: Option<Span>,
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
// can't infer this type
|
||||
unstable_feature: Option<(Symbol, u32)>,
|
||||
edition| {
|
||||
|
||||
let validate_and_set_expn_info = |this: &mut Self| {
|
||||
// feature-gate the macro invocation
|
||||
if let Some((feature, issue)) = unstable_feature {
|
||||
if let Some((feature, issue)) = ext.unstable_feature {
|
||||
let crate_span = this.cx.current_expansion.crate_span.unwrap();
|
||||
// don't stability-check macros in the same crate
|
||||
// (the only time this is null is for syntax extensions registered as macros)
|
||||
if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span))
|
||||
if ext.def_info.map_or(false, |(_, def_span)| !crate_span.contains(def_span))
|
||||
&& !span.allows_unstable(feature)
|
||||
&& this.cx.ecfg.features.map_or(true, |feats| {
|
||||
// macro features will count as lib features
|
||||
@ -734,62 +715,40 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
this.cx.trace_macros_diag();
|
||||
return Err(kind.dummy(span));
|
||||
}
|
||||
mark.set_expn_info(ExpnInfo {
|
||||
call_site: span,
|
||||
def_site: def_site_span,
|
||||
format: macro_bang_format(path),
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
edition,
|
||||
});
|
||||
mark.set_expn_info(ext.expn_info(span, &fast_print_path(path)));
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let opt_expanded = match *ext {
|
||||
SyntaxExtension::LegacyBang {
|
||||
ref expander,
|
||||
def_info,
|
||||
ref allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
unstable_feature,
|
||||
edition,
|
||||
..
|
||||
} => {
|
||||
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
|
||||
allow_internal_unstable.clone(),
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
unstable_feature,
|
||||
edition) {
|
||||
let opt_expanded = match &ext.kind {
|
||||
SyntaxExtensionKind::LegacyBang(expander) => {
|
||||
if let Err(dummy_span) = validate_and_set_expn_info(self) {
|
||||
dummy_span
|
||||
} else {
|
||||
kind.make_from(expander.expand(
|
||||
self.cx,
|
||||
span,
|
||||
mac.node.stream(),
|
||||
def_info.map(|(_, s)| s),
|
||||
ext.def_info.map(|(_, s)| s),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
SyntaxExtension::Attr(..) |
|
||||
SyntaxExtension::LegacyAttr(..) |
|
||||
SyntaxExtension::NonMacroAttr { .. } => {
|
||||
SyntaxExtensionKind::Attr(..) |
|
||||
SyntaxExtensionKind::LegacyAttr(..) |
|
||||
SyntaxExtensionKind::NonMacroAttr { .. } => {
|
||||
self.cx.span_err(path.span,
|
||||
&format!("`{}` can only be used in attributes", path));
|
||||
self.cx.trace_macros_diag();
|
||||
kind.dummy(span)
|
||||
}
|
||||
|
||||
SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => {
|
||||
SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
|
||||
self.cx.span_err(path.span, &format!("`{}` is a derive macro", path));
|
||||
self.cx.trace_macros_diag();
|
||||
kind.dummy(span)
|
||||
}
|
||||
|
||||
SyntaxExtension::Bang { ref expander, ref allow_internal_unstable, edition } => {
|
||||
SyntaxExtensionKind::Bang(expander) => {
|
||||
if ident.name != kw::Invalid {
|
||||
let msg =
|
||||
format!("macro {}! expects no ident argument, given '{}'", path, ident);
|
||||
@ -798,19 +757,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
kind.dummy(span)
|
||||
} else {
|
||||
self.gate_proc_macro_expansion_kind(span, kind);
|
||||
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
|
||||
call_site: span,
|
||||
// FIXME procedural macros do not have proper span info
|
||||
// yet, when they do, we should use it here.
|
||||
def_site: None,
|
||||
format: macro_bang_format(path),
|
||||
// FIXME probably want to follow macro_rules macros here.
|
||||
allow_internal_unstable: allow_internal_unstable.clone(),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition,
|
||||
});
|
||||
|
||||
let expn_info = ext.expn_info(span, &fast_print_path(path));
|
||||
invoc.expansion_data.mark.set_expn_info(expn_info);
|
||||
let tok_result = expander.expand(self.cx, span, mac.node.stream());
|
||||
let result = self.parse_ast_fragment(tok_result, kind, path, span);
|
||||
self.gate_proc_macro_expansion(span, &result);
|
||||
@ -867,55 +815,23 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let pretty_name = Symbol::intern(&format!("derive({})", path));
|
||||
let span = path.span;
|
||||
let attr = ast::Attribute {
|
||||
path, span,
|
||||
tokens: TokenStream::empty(),
|
||||
// irrelevant:
|
||||
id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false,
|
||||
};
|
||||
|
||||
let mut expn_info = ExpnInfo {
|
||||
call_site: span,
|
||||
def_site: None,
|
||||
format: MacroAttribute(pretty_name),
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: ext.edition(self.cx.parse_sess.edition),
|
||||
};
|
||||
|
||||
match ext {
|
||||
SyntaxExtension::Derive(expander, ..) | SyntaxExtension::LegacyDerive(expander) => {
|
||||
let meta = match ext {
|
||||
SyntaxExtension::Derive(..) => ast::MetaItem { // FIXME(jseyfried) avoid this
|
||||
path: Path::from_ident(Ident::invalid()),
|
||||
span: DUMMY_SP,
|
||||
node: ast::MetaItemKind::Word,
|
||||
},
|
||||
_ => {
|
||||
expn_info.allow_internal_unstable = Some(vec![
|
||||
sym::rustc_attrs,
|
||||
Symbol::intern("derive_clone_copy"),
|
||||
Symbol::intern("derive_eq"),
|
||||
// RustcDeserialize and RustcSerialize
|
||||
Symbol::intern("libstd_sys_internals"),
|
||||
].into());
|
||||
attr.meta()?
|
||||
}
|
||||
};
|
||||
|
||||
match &ext.kind {
|
||||
SyntaxExtensionKind::Derive(expander) |
|
||||
SyntaxExtensionKind::LegacyDerive(expander) => {
|
||||
let expn_info =
|
||||
ext.expn_info(path.span, &format!("derive({})", fast_print_path(&path)));
|
||||
invoc.expansion_data.mark.set_expn_info(expn_info);
|
||||
let span = span.with_ctxt(self.cx.backtrace());
|
||||
|
||||
let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span: path.span, path };
|
||||
let span = meta.span.with_ctxt(self.cx.backtrace());
|
||||
let items = expander.expand(self.cx, span, &meta, item);
|
||||
Some(invoc.fragment_kind.expect_from_annotatables(items))
|
||||
}
|
||||
_ => {
|
||||
let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
|
||||
self.cx.span_err(span, msg);
|
||||
let msg = &format!("macro `{}` may not be used for derive attributes", path);
|
||||
self.cx.span_err(path.span, msg);
|
||||
self.cx.trace_macros_diag();
|
||||
invoc.fragment_kind.dummy(span)
|
||||
invoc.fragment_kind.dummy(path.span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{ast, attr};
|
||||
use crate::edition::Edition;
|
||||
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension, TTMacroExpander};
|
||||
use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
|
||||
use crate::ext::expand::{AstFragment, AstFragmentKind};
|
||||
use crate::ext::hygiene::Transparency;
|
||||
use crate::ext::tt::macro_parser::{Success, Error, Failure};
|
||||
@ -376,7 +377,7 @@ pub fn compile(
|
||||
valid,
|
||||
});
|
||||
|
||||
let transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) {
|
||||
let default_transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) {
|
||||
Transparency::Transparent
|
||||
} else if body.legacy {
|
||||
Transparency::SemiTransparent
|
||||
@ -426,14 +427,15 @@ pub fn compile(
|
||||
}
|
||||
});
|
||||
|
||||
SyntaxExtension::LegacyBang {
|
||||
expander,
|
||||
SyntaxExtension {
|
||||
kind: SyntaxExtensionKind::LegacyBang(expander),
|
||||
def_info: Some((def.id, def.span)),
|
||||
transparency,
|
||||
default_transparency,
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
unstable_feature,
|
||||
helper_attrs: Vec::new(),
|
||||
edition,
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ fn ignored_span(sp: Span, edition: Edition) -> Span {
|
||||
call_site: DUMMY_SP,
|
||||
def_site: None,
|
||||
format: MacroAttribute(Symbol::intern("std_inject")),
|
||||
allow_internal_unstable: Some(vec![sym::prelude_import].into()),
|
||||
allow_internal_unstable: Some([sym::prelude_import][..].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition,
|
||||
|
@ -284,7 +284,7 @@ fn generate_test_harness(sess: &ParseSess,
|
||||
call_site: DUMMY_SP,
|
||||
def_site: None,
|
||||
format: MacroAttribute(sym::test_case),
|
||||
allow_internal_unstable: Some(vec![sym::main, sym::test, sym::rustc_attrs].into()),
|
||||
allow_internal_unstable: Some([sym::main, sym::test, sym::rustc_attrs][..].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: sess.edition,
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use syntax::ast::{self, MetaItem};
|
||||
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver, MultiItemModifier};
|
||||
use syntax::edition::Edition;
|
||||
use syntax::ext::base::{Annotatable, ExtCtxt, Resolver, MultiItemModifier};
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
||||
use syntax::ptr::P;
|
||||
@ -67,11 +69,24 @@ macro_rules! derive_traits {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_builtin_derives(resolver: &mut dyn Resolver) {
|
||||
pub fn register_builtin_derives(resolver: &mut dyn Resolver, edition: Edition) {
|
||||
let allow_internal_unstable = Some([
|
||||
sym::rustc_attrs,
|
||||
Symbol::intern("derive_clone_copy"),
|
||||
Symbol::intern("derive_eq"),
|
||||
Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize
|
||||
][..].into());
|
||||
|
||||
$(
|
||||
resolver.add_builtin(
|
||||
ast::Ident::with_empty_ctxt(Symbol::intern($name)),
|
||||
Lrc::new(SyntaxExtension::LegacyDerive(Box::new(BuiltinDerive($func))))
|
||||
Lrc::new(SyntaxExtension {
|
||||
allow_internal_unstable: allow_internal_unstable.clone(),
|
||||
..SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($func))),
|
||||
edition,
|
||||
)
|
||||
}),
|
||||
);
|
||||
)*
|
||||
}
|
||||
|
@ -43,32 +43,31 @@ pub mod proc_macro_impl;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use syntax::ast;
|
||||
|
||||
use syntax::ext::base::{MacroExpanderFn, NamedSyntaxExtension, SyntaxExtension};
|
||||
use syntax::ext::hygiene::Transparency;
|
||||
use syntax::ext::base::MacroExpanderFn;
|
||||
use syntax::ext::base::{NamedSyntaxExtension, SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::edition::Edition;
|
||||
use syntax::symbol::{sym, Symbol};
|
||||
|
||||
pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
|
||||
user_exts: Vec<NamedSyntaxExtension>,
|
||||
edition: Edition) {
|
||||
deriving::register_builtin_derives(resolver);
|
||||
deriving::register_builtin_derives(resolver, edition);
|
||||
|
||||
let mut register = |name, ext| {
|
||||
resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext));
|
||||
};
|
||||
macro_rules! register {
|
||||
($( $name:ident: $f:expr, )*) => { $(
|
||||
register(Symbol::intern(stringify!($name)),
|
||||
SyntaxExtension::LegacyBang {
|
||||
expander: Box::new($f as MacroExpanderFn),
|
||||
def_info: None,
|
||||
transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition,
|
||||
});
|
||||
register(Symbol::intern(stringify!($name)), SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition
|
||||
));
|
||||
)* }
|
||||
}
|
||||
macro_rules! register_attr {
|
||||
($( $name:ident: $f:expr, )*) => { $(
|
||||
register(Symbol::intern(stringify!($name)), SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyAttr(Box::new($f)), edition
|
||||
));
|
||||
)* }
|
||||
}
|
||||
|
||||
@ -97,33 +96,25 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
|
||||
assert: assert::expand_assert,
|
||||
}
|
||||
|
||||
register(sym::test_case, SyntaxExtension::LegacyAttr(Box::new(test_case::expand)));
|
||||
register(sym::test, SyntaxExtension::LegacyAttr(Box::new(test::expand_test)));
|
||||
register(sym::bench, SyntaxExtension::LegacyAttr(Box::new(test::expand_bench)));
|
||||
register_attr! {
|
||||
test_case: test_case::expand,
|
||||
test: test::expand_test,
|
||||
bench: test::expand_bench,
|
||||
}
|
||||
|
||||
// format_args uses `unstable` things internally.
|
||||
register(Symbol::intern("format_args"),
|
||||
SyntaxExtension::LegacyBang {
|
||||
expander: Box::new(format::expand_format_args),
|
||||
def_info: None,
|
||||
transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition,
|
||||
});
|
||||
register(sym::format_args_nl,
|
||||
SyntaxExtension::LegacyBang {
|
||||
expander: Box::new(format::expand_format_args_nl),
|
||||
def_info: None,
|
||||
transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition,
|
||||
});
|
||||
register(Symbol::intern("format_args"), SyntaxExtension {
|
||||
allow_internal_unstable: Some([sym::fmt_internals][..].into()),
|
||||
..SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args)), edition
|
||||
)
|
||||
});
|
||||
register(sym::format_args_nl, SyntaxExtension {
|
||||
allow_internal_unstable: Some([sym::fmt_internals][..].into()),
|
||||
..SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args_nl)), edition
|
||||
)
|
||||
});
|
||||
|
||||
for (name, ext) in user_exts {
|
||||
register(name, ext);
|
||||
|
@ -351,10 +351,9 @@ fn mk_decls(
|
||||
call_site: DUMMY_SP,
|
||||
def_site: None,
|
||||
format: MacroAttribute(sym::proc_macro),
|
||||
allow_internal_unstable: Some(vec![
|
||||
sym::rustc_attrs,
|
||||
Symbol::intern("proc_macro_internals"),
|
||||
].into()),
|
||||
allow_internal_unstable: Some([
|
||||
sym::rustc_attrs, Symbol::intern("proc_macro_internals")
|
||||
][..].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: cx.parse_sess.edition,
|
||||
|
@ -66,7 +66,7 @@ pub fn expand_test_or_bench(
|
||||
call_site: DUMMY_SP,
|
||||
def_site: None,
|
||||
format: MacroAttribute(sym::test),
|
||||
allow_internal_unstable: Some(vec![sym::rustc_attrs, sym::test].into()),
|
||||
allow_internal_unstable: Some([sym::rustc_attrs, sym::test][..].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: cx.parse_sess.edition,
|
||||
|
@ -41,7 +41,7 @@ pub fn expand(
|
||||
call_site: DUMMY_SP,
|
||||
def_site: None,
|
||||
format: MacroAttribute(sym::test_case),
|
||||
allow_internal_unstable: Some(vec![sym::test, sym::rustc_attrs].into()),
|
||||
allow_internal_unstable: Some([sym::test, sym::rustc_attrs][..].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: ecx.parse_sess.edition,
|
||||
|
@ -11,8 +11,8 @@ extern crate rustc_plugin;
|
||||
use std::borrow::ToOwned;
|
||||
use syntax::ast;
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::base::{SyntaxExtension, TTMacroExpander, ExtCtxt, MacResult, MacEager};
|
||||
use syntax::ext::hygiene::Transparency;
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager};
|
||||
use syntax::print::pprust;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
@ -38,15 +38,7 @@ impl TTMacroExpander for Expander {
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
let args = reg.args().to_owned();
|
||||
reg.register_syntax_extension(Symbol::intern("plugin_args"),
|
||||
SyntaxExtension::LegacyBang {
|
||||
expander: Box::new(Expander { args: args, }),
|
||||
def_info: None,
|
||||
transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition: reg.sess.edition(),
|
||||
});
|
||||
reg.register_syntax_extension(Symbol::intern("plugin_args"), SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyBang(Box::new(Expander { args })), reg.sess.edition()
|
||||
));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user