about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-09-08 22:19:53 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-09-13 14:48:50 +0300
commitbeb3b5d22c709c19600ca6514d94f9cf1be44dca (patch)
treede1432273793bc9c6b2716d6f0f51344d265bcb1 /src
parent994cdd918589535d705177545bf503cd0c3c5148 (diff)
downloadrust-beb3b5d22c709c19600ca6514d94f9cf1be44dca.tar.gz
rust-beb3b5d22c709c19600ca6514d94f9cf1be44dca.zip
resolve: Introduce two sub-namespaces in macro namespace
Diffstat (limited to 'src')
-rw-r--r--src/librustc_resolve/macros.rs29
-rw-r--r--src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs2
-rw-r--r--src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs11
-rw-r--r--src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs16
-rw-r--r--src/test/ui/issues/issue-11692-2.rs2
-rw-r--r--src/test/ui/issues/issue-11692-2.stderr4
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-3.rs13
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-3.stderr10
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-4.rs4
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-4.stderr8
10 files changed, 64 insertions, 35 deletions
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index f687e022a41..cf5a53b6318 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -118,11 +118,21 @@ pub struct ProcMacError {
     warn_msg: &'static str,
 }
 
-// For compatibility bang macros are skipped when resolving potentially built-in attributes.
-fn macro_kind_mismatch(name: Name, requirement: Option<MacroKind>, candidate: Option<MacroKind>)
-                       -> bool {
-    requirement == Some(MacroKind::Attr) && candidate == Some(MacroKind::Bang) &&
-    (name == "test" || name == "bench" || is_builtin_attr_name(name))
+// Macro namespace is separated into two sub-namespaces, one for bang macros and
+// one for attribute-like macros (attributes, derives).
+// We ignore resolutions from one sub-namespace when searching names in scope for another.
+fn sub_namespace_mismatch(requirement: Option<MacroKind>, candidate: Option<MacroKind>) -> bool {
+    #[derive(PartialEq)]
+    enum SubNS { Bang, AttrLike }
+    let sub_ns = |kind| match kind {
+        MacroKind::Bang => Some(SubNS::Bang),
+        MacroKind::Attr | MacroKind::Derive => Some(SubNS::AttrLike),
+        MacroKind::ProcMacroStub => None,
+    };
+    let requirement = requirement.and_then(|kind| sub_ns(kind));
+    let candidate = candidate.and_then(|kind| sub_ns(kind));
+    // "No specific sub-namespace" means "matches anything" for both requirements and candidates.
+    candidate.is_some() && requirement.is_some() && candidate != requirement
 }
 
 impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
@@ -641,10 +651,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     }
                 }
                 WhereToResolve::BuiltinAttrs => {
-                    // FIXME: Only built-in attributes are not considered as candidates for
-                    // non-attributes to fight off regressions on stable channel (#53205).
-                    // We need to come up with some more principled approach instead.
-                    if kind == Some(MacroKind::Attr) && is_builtin_attr_name(ident.name) {
+                    if is_builtin_attr_name(ident.name) {
                         let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
                                        ty::Visibility::Public, ident.span, Mark::root())
                                        .to_name_binding(self.arenas);
@@ -765,7 +772,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
 
             match result {
                 Ok(result) => {
-                    if macro_kind_mismatch(ident.name, kind, result.0.macro_kind()) {
+                    if sub_namespace_mismatch(kind, result.0.macro_kind()) {
                         continue_search!();
                     }
 
@@ -829,7 +836,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         parent_scope: &ParentScope<'a>,
         record_used: bool,
     ) -> Option<&'a NameBinding<'a>> {
-        if macro_kind_mismatch(ident.name, kind, Some(MacroKind::Bang)) {
+        if sub_namespace_mismatch(kind, Some(MacroKind::Bang)) {
             return None;
         }
 
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs
new file mode 100644
index 00000000000..9912a89dafb
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs
@@ -0,0 +1,2 @@
+#[macro_export]
+macro_rules! my_attr { () => () }
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs
new file mode 100644
index 00000000000..4e701710f42
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs
@@ -0,0 +1,11 @@
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_derive(MyTrait, attributes(my_attr))]
+pub fn foo(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs
new file mode 100644
index 00000000000..792b54b3b94
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// aux-build:derive-helper-shadowed.rs
+// aux-build:derive-helper-shadowed-2.rs
+
+#[macro_use]
+extern crate derive_helper_shadowed;
+#[macro_use(my_attr)]
+extern crate derive_helper_shadowed_2;
+
+macro_rules! my_attr { () => () }
+
+#[derive(MyTrait)]
+#[my_attr] // OK
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-11692-2.rs b/src/test/ui/issues/issue-11692-2.rs
index 2e94a27838e..a4b8b48384d 100644
--- a/src/test/ui/issues/issue-11692-2.rs
+++ b/src/test/ui/issues/issue-11692-2.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    concat!(test!()); //~ ERROR `test` can only be used in attributes
+    concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
 }
diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr
index 186c59a6149..85f600dbff2 100644
--- a/src/test/ui/issues/issue-11692-2.stderr
+++ b/src/test/ui/issues/issue-11692-2.stderr
@@ -1,7 +1,7 @@
-error: `test` can only be used in attributes
+error: cannot find macro `test!` in this scope
   --> $DIR/issue-11692-2.rs:12:13
    |
-LL |     concat!(test!()); //~ ERROR `test` can only be used in attributes
+LL |     concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
    |             ^^^^
 
 error: aborting due to previous error
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.rs b/src/test/ui/macros/macro-path-prelude-fail-3.rs
index c706b8f613d..597053d6251 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.rs
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.rs
@@ -1,16 +1,3 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[derive(inline)] //~ ERROR cannot find derive macro `inline` in this scope
-struct S;
-
 fn main() {
     inline!(); //~ ERROR cannot find macro `inline!` in this scope
 }
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
index a8edf54d220..17723251181 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
@@ -1,14 +1,8 @@
-error: cannot find derive macro `inline` in this scope
-  --> $DIR/macro-path-prelude-fail-3.rs:11:10
-   |
-LL | #[derive(inline)] //~ ERROR cannot find derive macro `inline` in this scope
-   |          ^^^^^^
-
 error: cannot find macro `inline!` in this scope
-  --> $DIR/macro-path-prelude-fail-3.rs:15:5
+  --> $DIR/macro-path-prelude-fail-3.rs:2:5
    |
 LL |     inline!(); //~ ERROR cannot find macro `inline!` in this scope
    |     ^^^^^^ help: you could try the macro: `line`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macro-path-prelude-fail-4.rs b/src/test/ui/macros/macro-path-prelude-fail-4.rs
new file mode 100644
index 00000000000..283427b9ace
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-fail-4.rs
@@ -0,0 +1,4 @@
+#[derive(inline)] //~ ERROR expected a macro, found built-in attribute
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-path-prelude-fail-4.stderr b/src/test/ui/macros/macro-path-prelude-fail-4.stderr
new file mode 100644
index 00000000000..e354f345a4c
--- /dev/null
+++ b/src/test/ui/macros/macro-path-prelude-fail-4.stderr
@@ -0,0 +1,8 @@
+error: expected a macro, found built-in attribute
+  --> $DIR/macro-path-prelude-fail-4.rs:1:10
+   |
+LL | #[derive(inline)] //~ ERROR expected a macro, found built-in attribute
+   |          ^^^^^^
+
+error: aborting due to previous error
+