about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-06-30 01:24:34 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-07-06 18:36:35 +0300
commit327450797d460ae011eaaba68fae356117ab883d (patch)
treee62c1ca85f91c9b25a062a8833f266a59474c447
parent920a17a60c13101225a3a50e232c3e44017dab69 (diff)
downloadrust-327450797d460ae011eaaba68fae356117ab883d.tar.gz
rust-327450797d460ae011eaaba68fae356117ab883d.zip
resolve: Reserve cfg/cfg_attr/derive only in attribute sub-namespace
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs16
-rw-r--r--src/librustc_resolve/macros.rs21
-rw-r--r--src/librustc_resolve/resolve_imports.rs20
-rw-r--r--src/test/ui/proc-macro/reserved-macro-names.rs6
-rw-r--r--src/test/ui/proc-macro/reserved-macro-names.stderr6
5 files changed, 38 insertions, 31 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 616728d5418..3921bd30df2 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<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> {
                                                &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
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 6a8c46eaa40..0955c425f2f 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -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);
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 404d728d880..7de1cd29a9c 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,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) {
diff --git a/src/test/ui/proc-macro/reserved-macro-names.rs b/src/test/ui/proc-macro/reserved-macro-names.rs
index 7c66af172fd..9f56eccb7a6 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 5ebe62a4969..f871e43ce51 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 {