Skip to content

Commit

Permalink
resolve: Reserve cfg/cfg_attr/derive only in attribute sub-namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Jul 5, 2019
1 parent f993107 commit 848b2d2
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 39 deletions.
16 changes: 11 additions & 5 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,27 +770,33 @@ 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,
&self.session.features_untracked(),
&macro_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
Expand Down
19 changes: 14 additions & 5 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,17 @@ impl<'a> Resolver<'a> {
});
}

crate fn check_reserved_macro_name(&self, ident: Ident, macro_kind: Option<MacroKind>) {
// Reserve some names that are not quite covered by the general check
// performed on `Resolver::builtin_attrs`.
if (macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr))) &&
(ident.name == sym::cfg || ident.name == sym::cfg_attr || ident.name == sym::derive) {
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,
Expand All @@ -1117,13 +1128,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
Expand All @@ -1142,14 +1154,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, Some(macro_kind));
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);
Expand Down
21 changes: 6 additions & 15 deletions src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -492,35 +492,26 @@ 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>,
ident: Ident,
ns: Namespace,
binding: &'a NameBinding<'a>)
-> Result<(), &'a NameBinding<'a>> {
self.check_reserved_macro_name(ident, ns);
let res = binding.res();
let macro_kind = self.opt_get_macro(res).map(|ext| ext.macro_kind());
self.check_reserved_macro_name(ident, macro_kind);
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) {
Expand Down
16 changes: 8 additions & 8 deletions src/test/ui/consts/const-eval/feature-gate-const_panic.stderr
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
error[E0658]: panicking in constants is unstable
--> $DIR/feature-gate-const_panic.rs:3:15
--> $DIR/feature-gate-const_panic.rs:6:15
|
LL | const Z: () = panic!("cheese");
| ^^^^^^^^^^^^^^^^
LL | const Y: () = unreachable!();
| ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/51999
= help: add #![feature(const_panic)] to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0658]: panicking in constants is unstable
--> $DIR/feature-gate-const_panic.rs:9:15
--> $DIR/feature-gate-const_panic.rs:3:15
|
LL | const X: () = unimplemented!();
LL | const Z: () = panic!("cheese");
| ^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/51999
= help: add #![feature(const_panic)] to the crate attributes to enable
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0658]: panicking in constants is unstable
--> $DIR/feature-gate-const_panic.rs:6:15
--> $DIR/feature-gate-const_panic.rs:9:15
|
LL | const Y: () = unreachable!();
| ^^^^^^^^^^^^^^
LL | const X: () = unimplemented!();
| ^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/51999
= help: add #![feature(const_panic)] to the crate attributes to enable
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/proc-macro/reserved-macro-names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
6 changes: 3 additions & 3 deletions src/test/ui/proc-macro/reserved-macro-names.stderr
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down

0 comments on commit 848b2d2

Please sign in to comment.