resolve: Reserve cfg/cfg_attr/derive only in attribute sub-namespace
This commit is contained in:
parent
920a17a60c
commit
327450797d
|
@ -770,19 +770,25 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
|
||||
pub fn get_macro(&mut self, res: Res) -> Lrc<SyntaxExtension> {
|
||||
self.opt_get_macro(res).expect("expected `DefKind::Macro` or `Res::NonMacroAttr`")
|
||||
}
|
||||
|
||||
crate fn opt_get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
|
||||
let def_id = match res {
|
||||
Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) =>
|
||||
return Some(self.non_macro_attr(true)), // some dummy extension
|
||||
Res::Def(DefKind::Macro(..), def_id) => def_id,
|
||||
Res::NonMacroAttr(attr_kind) =>
|
||||
return self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool),
|
||||
_ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
|
||||
return Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
|
||||
_ => return None,
|
||||
};
|
||||
if let Some(ext) = self.macro_map.get(&def_id) {
|
||||
return ext.clone();
|
||||
return Some(ext.clone());
|
||||
}
|
||||
|
||||
let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) {
|
||||
LoadedMacro::MacroDef(macro_def) => macro_def,
|
||||
LoadedMacro::ProcMacro(ext) => return ext,
|
||||
LoadedMacro::ProcMacro(ext) => return Some(ext),
|
||||
};
|
||||
|
||||
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
|
||||
|
@ -790,7 +796,7 @@ impl<'a> Resolver<'a> {
|
|||
¯o_def,
|
||||
self.cstore.crate_edition_untracked(def_id.krate)));
|
||||
self.macro_map.insert(def_id, ext.clone());
|
||||
ext
|
||||
Some(ext)
|
||||
}
|
||||
|
||||
/// Ensures that the reduced graph rooted at the given external module
|
||||
|
|
|
@ -1106,6 +1106,19 @@ impl<'a> Resolver<'a> {
|
|||
});
|
||||
}
|
||||
|
||||
crate fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) {
|
||||
// Reserve some names that are not quite covered by the general check
|
||||
// performed on `Resolver::builtin_attrs`.
|
||||
if ident.name == sym::cfg || ident.name == sym::cfg_attr || ident.name == sym::derive {
|
||||
let macro_kind = self.opt_get_macro(res).map(|ext| ext.macro_kind());
|
||||
if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
|
||||
self.session.span_err(
|
||||
ident.span, &format!("name `{}` is reserved in attribute namespace", ident)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn define_macro(&mut self,
|
||||
item: &ast::Item,
|
||||
expansion: Mark,
|
||||
|
@ -1117,13 +1130,14 @@ impl<'a> Resolver<'a> {
|
|||
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
|
||||
&self.session.features_untracked(),
|
||||
item, self.session.edition()));
|
||||
let macro_kind = ext.macro_kind();
|
||||
let res = Res::Def(DefKind::Macro(macro_kind), def_id);
|
||||
self.macro_map.insert(def_id, ext);
|
||||
|
||||
let def = match item.node { ast::ItemKind::MacroDef(ref def) => def, _ => unreachable!() };
|
||||
if def.legacy {
|
||||
let ident = ident.modern();
|
||||
self.macro_names.insert(ident);
|
||||
let res = Res::Def(DefKind::Macro(MacroKind::Bang), def_id);
|
||||
let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
|
||||
let vis = if is_macro_export {
|
||||
ty::Visibility::Public
|
||||
|
@ -1142,14 +1156,11 @@ impl<'a> Resolver<'a> {
|
|||
self.define(module, ident, MacroNS,
|
||||
(res, vis, item.span, expansion, IsMacroExport));
|
||||
} else {
|
||||
if !attr::contains_name(&item.attrs, sym::rustc_builtin_macro) {
|
||||
self.check_reserved_macro_name(ident, MacroNS);
|
||||
}
|
||||
self.check_reserved_macro_name(ident, res);
|
||||
self.unused_macros.insert(def_id);
|
||||
}
|
||||
} else {
|
||||
let module = self.current_module;
|
||||
let res = Res::Def(DefKind::Macro(MacroKind::Bang), def_id);
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
if vis != ty::Visibility::Public {
|
||||
self.unused_macros.insert(def_id);
|
||||
|
|
|
@ -29,7 +29,7 @@ use rustc::{bug, span_bug};
|
|||
use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
|
||||
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::symbol::{kw, sym};
|
||||
use syntax::symbol::kw;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use syntax::{struct_span_err, unwrap_or};
|
||||
use syntax_pos::{MultiSpan, Span};
|
||||
|
@ -492,17 +492,6 @@ impl<'a> Resolver<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
crate fn check_reserved_macro_name(&self, ident: Ident, ns: Namespace) {
|
||||
// Reserve some names that are not quite covered by the general check
|
||||
// performed on `Resolver::builtin_attrs`.
|
||||
if ns == MacroNS &&
|
||||
(ident.name == sym::cfg || ident.name == sym::cfg_attr ||
|
||||
ident.name == sym::derive) {
|
||||
self.session.span_err(ident.span,
|
||||
&format!("name `{}` is reserved in macro namespace", ident));
|
||||
}
|
||||
}
|
||||
|
||||
// Define the name or return the existing binding if there is a collision.
|
||||
pub fn try_define(&mut self,
|
||||
module: Module<'a>,
|
||||
|
@ -510,17 +499,18 @@ impl<'a> Resolver<'a> {
|
|||
ns: Namespace,
|
||||
binding: &'a NameBinding<'a>)
|
||||
-> Result<(), &'a NameBinding<'a>> {
|
||||
self.check_reserved_macro_name(ident, ns);
|
||||
let res = binding.res();
|
||||
self.check_reserved_macro_name(ident, res);
|
||||
self.set_binding_parent_module(binding, module);
|
||||
self.update_resolution(module, ident, ns, |this, resolution| {
|
||||
if let Some(old_binding) = resolution.binding {
|
||||
if binding.res() == Res::Err {
|
||||
if res == Res::Err {
|
||||
// Do not override real bindings with `Res::Err`s from error recovery.
|
||||
return Ok(());
|
||||
}
|
||||
match (old_binding.is_glob_import(), binding.is_glob_import()) {
|
||||
(true, true) => {
|
||||
if binding.res() != old_binding.res() {
|
||||
if res != old_binding.res() {
|
||||
resolution.binding = Some(this.ambiguity(AmbiguityKind::GlobVsGlob,
|
||||
old_binding, binding));
|
||||
} else if !old_binding.vis.is_at_least(binding.vis, &*this) {
|
||||
|
|
|
@ -8,18 +8,18 @@ use proc_macro::*;
|
|||
|
||||
#[proc_macro_attribute]
|
||||
pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
//~^ ERROR name `cfg` is reserved in macro namespace
|
||||
//~^ ERROR name `cfg` is reserved in attribute namespace
|
||||
input
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
//~^ ERROR name `cfg_attr` is reserved in macro namespace
|
||||
//~^ ERROR name `cfg_attr` is reserved in attribute namespace
|
||||
input
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn derive(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
//~^ ERROR name `derive` is reserved in macro namespace
|
||||
//~^ ERROR name `derive` is reserved in attribute namespace
|
||||
input
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
error: name `cfg` is reserved in macro namespace
|
||||
error: name `cfg` is reserved in attribute namespace
|
||||
--> $DIR/reserved-macro-names.rs:10:8
|
||||
|
|
||||
LL | pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
| ^^^
|
||||
|
||||
error: name `cfg_attr` is reserved in macro namespace
|
||||
error: name `cfg_attr` is reserved in attribute namespace
|
||||
--> $DIR/reserved-macro-names.rs:16:8
|
||||
|
|
||||
LL | pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
| ^^^^^^^^
|
||||
|
||||
error: name `derive` is reserved in macro namespace
|
||||
error: name `derive` is reserved in attribute namespace
|
||||
--> $DIR/reserved-macro-names.rs:22:8
|
||||
|
|
||||
LL | pub fn derive(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
|
|
Loading…
Reference in New Issue