diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 616728d541848..3921bd30df25c 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -770,19 +770,25 @@ impl<'a> Resolver<'a> { } pub fn get_macro(&mut self, res: Res) -> Lrc { + self.opt_get_macro(res).expect("expected `DefKind::Macro` or `Res::NonMacroAttr`") + } + + crate fn opt_get_macro(&mut self, res: Res) -> Option> { 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 diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 6a8c46eaa40fb..7b509191d589f 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -1106,6 +1106,17 @@ impl<'a> Resolver<'a> { }); } + crate fn check_reserved_macro_name(&self, ident: Ident, macro_kind: Option) { + // 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, @@ -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 @@ -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); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 404d728d8808c..3b20647d0bf9c 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -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,19 @@ 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(); + 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) { diff --git a/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr b/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr index 5d3e88e4e58c2..bf45b9d9021bc 100644 --- a/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr +++ b/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr @@ -1,17 +1,17 @@ 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 @@ -19,10 +19,10 @@ LL | const X: () = unimplemented!(); = 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 diff --git a/src/test/ui/proc-macro/reserved-macro-names.rs b/src/test/ui/proc-macro/reserved-macro-names.rs index 7c66af172fd5e..9f56eccb7a61c 100644 --- a/src/test/ui/proc-macro/reserved-macro-names.rs +++ b/src/test/ui/proc-macro/reserved-macro-names.rs @@ -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 } diff --git a/src/test/ui/proc-macro/reserved-macro-names.stderr b/src/test/ui/proc-macro/reserved-macro-names.stderr index 5ebe62a4969bb..f871e43ce51df 100644 --- a/src/test/ui/proc-macro/reserved-macro-names.stderr +++ b/src/test/ui/proc-macro/reserved-macro-names.stderr @@ -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 {