about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-07-12 13:24:59 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-07-14 20:10:07 +0300
commit431aefb2d4d579b152f7f26f3e70d2fdc3db4bfb (patch)
treec30139184897e67a9138bc21109ddb0be9064f7f /src
parent1731f0af22af16c461b2b7abe58988b8549b2de6 (diff)
downloadrust-431aefb2d4d579b152f7f26f3e70d2fdc3db4bfb.tar.gz
rust-431aefb2d4d579b152f7f26f3e70d2fdc3db4bfb.zip
Functions introducing procedural macros reserve a slot in the macro namespace as well
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ich/impls_syntax.rs3
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs20
-rw-r--r--src/librustc_resolve/macros.rs17
-rw-r--r--src/libsyntax/ext/base.rs3
-rw-r--r--src/libsyntax/ext/expand.rs2
-rw-r--r--src/libsyntax_ext/proc_macro_registrar.rs5
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/define-two.rs2
-rw-r--r--src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.rs56
-rw-r--r--src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.stderr56
-rw-r--r--src/test/ui-fulldeps/proc-macro/macro-namespace-reserved.rs47
-rw-r--r--src/test/ui-fulldeps/proc-macro/macro-namespace-reserved.stderr47
11 files changed, 247 insertions, 11 deletions
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 713e8b561f1..fa9c5cefdf3 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -98,7 +98,8 @@ impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
 impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
     Bang,
     Attr,
-    Derive
+    Derive,
+    ProcMacroStub,
 });
 
 
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index a770f078404..29312912a24 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -34,7 +34,7 @@ use syntax::attr;
 
 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
 use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind, Variant};
-use syntax::ext::base::SyntaxExtension;
+use syntax::ext::base::{MacroKind, SyntaxExtension};
 use syntax::ext::base::Determinacy::Undetermined;
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
@@ -335,6 +335,24 @@ impl<'a> Resolver<'a> {
             ItemKind::Fn(..) => {
                 let def = Def::Fn(self.definitions.local_def_id(item.id));
                 self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
+
+                // Functions introducing procedural macros reserve a slot
+                // in the macro namespace as well (see #52225).
+                if attr::contains_name(&item.attrs, "proc_macro") ||
+                   attr::contains_name(&item.attrs, "proc_macro_attribute") {
+                    let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
+                    self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
+                }
+                if let Some(attr) = attr::find_by_name(&item.attrs, "proc_macro_derive") {
+                    if let Some(trait_attr) =
+                            attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
+                        if let Some(ident) = trait_attr.name().map(Ident::with_empty_ctxt) {
+                            let sp = trait_attr.span;
+                            let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
+                            self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
+                        }
+                    }
+                }
             }
 
             // These items live in the type namespace.
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 024506ed7f8..c99172efc7c 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -321,6 +321,10 @@ impl<'a> base::Resolver for Resolver<'a> {
             InvocationKind::Attr { attr: None, .. } => return Ok(None),
             _ => self.resolve_invoc_to_def(invoc, scope, force)?,
         };
+        if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
+            self.report_proc_macro_stub(invoc.span());
+            return Err(Determinacy::Determined);
+        }
         let def_id = def.def_id();
 
         self.macro_defs.insert(invoc.expansion_data.mark, def_id);
@@ -338,9 +342,13 @@ impl<'a> base::Resolver for Resolver<'a> {
 
     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
                      -> Result<Lrc<SyntaxExtension>, Determinacy> {
-        self.resolve_macro_to_def(scope, path, kind, force).map(|def| {
+        self.resolve_macro_to_def(scope, path, kind, force).and_then(|def| {
+            if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
+                self.report_proc_macro_stub(path.span);
+                return Err(Determinacy::Determined);
+            }
             self.unused_macros.remove(&def.def_id());
-            self.get_macro(def)
+            Ok(self.get_macro(def))
         })
     }
 
@@ -363,6 +371,11 @@ impl<'a> base::Resolver for Resolver<'a> {
 }
 
 impl<'a> Resolver<'a> {
+    fn report_proc_macro_stub(&self, span: Span) {
+        self.session.span_err(span,
+                              "can't use a procedural macro from the same crate that defines it");
+    }
+
     fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
                             -> Result<Def, Determinacy> {
         let (attr, traits, item) = match invoc.kind {
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index e49a521040f..b585f887269 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -571,6 +571,8 @@ pub enum MacroKind {
     Attr,
     /// A derive attribute macro - #[derive(Foo)]
     Derive,
+    /// A view of a procedural macro from the same crate that defines it.
+    ProcMacroStub,
 }
 
 impl MacroKind {
@@ -579,6 +581,7 @@ impl MacroKind {
             MacroKind::Bang => "macro",
             MacroKind::Attr => "attribute macro",
             MacroKind::Derive => "derive macro",
+            MacroKind::ProcMacroStub => "crate-local procedural macro",
         }
     }
 }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 865cb3d0d45..281ebaff272 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -232,7 +232,7 @@ pub enum InvocationKind {
 }
 
 impl Invocation {
-    fn span(&self) -> Span {
+    pub fn span(&self) -> Span {
         match self.kind {
             InvocationKind::Bang { span, .. } => span,
             InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span,
diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs
index ab2bb446631..63341c8ce37 100644
--- a/src/libsyntax_ext/proc_macro_registrar.rs
+++ b/src/libsyntax_ext/proc_macro_registrar.rs
@@ -147,11 +147,6 @@ impl<'a> CollectProcMacros<'a> {
                                   "cannot override a built-in #[derive] mode");
         }
 
-        if self.derives.iter().any(|d| d.trait_name == trait_name) {
-            self.handler.span_err(trait_attr.span(),
-                                  "derive mode defined twice in this crate");
-        }
-
         let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
             if !attr.check_name("attributes") {
                 self.handler.span_err(attr.span(), "second argument must be `attributes`")
diff --git a/src/test/compile-fail-fulldeps/proc-macro/define-two.rs b/src/test/compile-fail-fulldeps/proc-macro/define-two.rs
index 87b32096d7b..8321c471b2a 100644
--- a/src/test/compile-fail-fulldeps/proc-macro/define-two.rs
+++ b/src/test/compile-fail-fulldeps/proc-macro/define-two.rs
@@ -21,7 +21,7 @@ pub fn foo(input: TokenStream) -> TokenStream {
     input
 }
 
-#[proc_macro_derive(A)] //~ ERROR: derive mode defined twice in this crate
+#[proc_macro_derive(A)] //~ ERROR the name `A` is defined multiple times
 pub fn bar(input: TokenStream) -> TokenStream {
     input
 }
diff --git a/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.rs b/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.rs
new file mode 100644
index 00000000000..89d5f22da91
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.rs
@@ -0,0 +1,56 @@
+// 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.
+
+// no-prefer-dynamic
+
+#![feature(proc_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn my_macro(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(MyTrait)]
+pub fn my_macro_derive(input: TokenStream) -> TokenStream {
+    input
+}
+
+fn check_bang1() {
+    my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+}
+fn check_bang2() {
+    my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+}
+fn check_bang3() {
+    MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+}
+
+#[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
+fn check_attr1() {}
+#[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
+fn check_attr2() {}
+#[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
+fn check_attr3() {}
+
+#[derive(my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines it
+struct CheckDerive1;
+#[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
+struct CheckDerive2;
+#[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
+struct CheckDerive3;
diff --git a/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.stderr
new file mode 100644
index 00000000000..58a7f974905
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.stderr
@@ -0,0 +1,56 @@
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:35:5
+   |
+LL |     my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+   |     ^^^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:38:5
+   |
+LL |     my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+   |     ^^^^^^^^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:41:5
+   |
+LL |     MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+   |     ^^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:44:1
+   |
+LL | #[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
+   | ^^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:46:1
+   |
+LL | #[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
+   | ^^^^^^^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:48:1
+   |
+LL | #[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
+   | ^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:51:10
+   |
+LL | #[derive(my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines it
+   |          ^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:53:10
+   |
+LL | #[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
+   |          ^^^^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:55:10
+   |
+LL | #[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
+   |          ^^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved.rs b/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved.rs
new file mode 100644
index 00000000000..21d625ae09d
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved.rs
@@ -0,0 +1,47 @@
+// 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.
+
+// no-prefer-dynamic
+
+#![feature(proc_macro, decl_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn my_macro(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(MyTrait)]
+pub fn my_macro_derive(input: TokenStream) -> TokenStream {
+    input
+}
+
+macro my_macro() {} //~ ERROR the name `my_macro` is defined multiple times
+macro my_macro_attr() {} //~ ERROR the name `my_macro_attr` is defined multiple times
+macro MyTrait() {} //~ ERROR the name `MyTrait` is defined multiple times
+
+#[proc_macro_derive(SameName)]
+pub fn foo(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro]
+pub fn SameName(input: TokenStream) -> TokenStream {
+//~^ ERROR the name `SameName` is defined multiple times
+    input
+}
diff --git a/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved.stderr b/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved.stderr
new file mode 100644
index 00000000000..44b51edcc0b
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved.stderr
@@ -0,0 +1,47 @@
+error[E0428]: the name `my_macro` is defined multiple times
+  --> $DIR/macro-namespace-reserved.rs:34:1
+   |
+LL | pub fn my_macro(input: TokenStream) -> TokenStream {
+   | -------------------------------------------------- previous definition of the macro `my_macro` here
+...
+LL | macro my_macro() {} //~ ERROR the name `my_macro` is defined multiple times
+   | ^^^^^^^^^^^^^^^^ `my_macro` redefined here
+   |
+   = note: `my_macro` must be defined only once in the macro namespace of this module
+
+error[E0428]: the name `my_macro_attr` is defined multiple times
+  --> $DIR/macro-namespace-reserved.rs:35:1
+   |
+LL | pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
+   | ----------------------------------------------------------------------- previous definition of the macro `my_macro_attr` here
+...
+LL | macro my_macro_attr() {} //~ ERROR the name `my_macro_attr` is defined multiple times
+   | ^^^^^^^^^^^^^^^^^^^^^ `my_macro_attr` redefined here
+   |
+   = note: `my_macro_attr` must be defined only once in the macro namespace of this module
+
+error[E0428]: the name `MyTrait` is defined multiple times
+  --> $DIR/macro-namespace-reserved.rs:36:1
+   |
+LL | #[proc_macro_derive(MyTrait)]
+   |                     ------- previous definition of the macro `MyTrait` here
+...
+LL | macro MyTrait() {} //~ ERROR the name `MyTrait` is defined multiple times
+   | ^^^^^^^^^^^^^^^ `MyTrait` redefined here
+   |
+   = note: `MyTrait` must be defined only once in the macro namespace of this module
+
+error[E0428]: the name `SameName` is defined multiple times
+  --> $DIR/macro-namespace-reserved.rs:44:1
+   |
+LL | #[proc_macro_derive(SameName)]
+   |                     -------- previous definition of the macro `SameName` here
+...
+LL | pub fn SameName(input: TokenStream) -> TokenStream {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SameName` redefined here
+   |
+   = note: `SameName` must be defined only once in the macro namespace of this module
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0428`.