about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_resolve/messages.ftl3
-rw-r--r--compiler/rustc_resolve/src/errors.rs9
-rw-r--r--compiler/rustc_resolve/src/macros.rs10
-rw-r--r--tests/ui/proc-macro/test-same-crate.rs16
-rw-r--r--tests/ui/proc-macro/test-same-crate.stderr10
5 files changed, 43 insertions, 5 deletions
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 01f002c9408..192badcbc37 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -223,3 +223,6 @@ resolve_remove_surrounding_derive =
 resolve_add_as_non_derive =
     add as non-Derive macro
     `#[{$macro_path}]`
+
+resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
+    .help = you can define integration tests in a directory named `tests`
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index af0ec236df0..6197af105a9 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -508,3 +508,12 @@ pub(crate) struct RemoveSurroundingDerive {
 pub(crate) struct AddAsNonDerive<'a> {
     pub(crate) macro_path: &'a str,
 }
+
+#[derive(Diagnostic)]
+#[diag(resolve_proc_macro_same_crate)]
+pub(crate) struct ProcMacroSameCrate {
+    #[primary_span]
+    pub(crate) span: Span,
+    #[help]
+    pub(crate) is_test: bool,
+}
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 22b014c0651..2211fb56ccd 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -1,7 +1,7 @@
 //! A bunch of methods and structures more or less related to resolving macros and
 //! interface provided by `Resolver` to macro expander.
 
-use crate::errors::{AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive};
+use crate::errors::{self, AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive};
 use crate::Namespace::*;
 use crate::{BuiltinMacroState, Determinacy};
 use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
@@ -513,10 +513,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 if let Some(def_id) = def_id.as_local() {
                     self.unused_macros.remove(&def_id);
                     if self.proc_macro_stubs.contains(&def_id) {
-                        self.tcx.sess.span_err(
-                            path.span,
-                            "can't use a procedural macro from the same crate that defines it",
-                        );
+                        self.tcx.sess.emit_err(errors::ProcMacroSameCrate {
+                            span: path.span,
+                            is_test: self.tcx.sess.is_test_crate(),
+                        });
                     }
                 }
             }
diff --git a/tests/ui/proc-macro/test-same-crate.rs b/tests/ui/proc-macro/test-same-crate.rs
new file mode 100644
index 00000000000..c13f384fa3a
--- /dev/null
+++ b/tests/ui/proc-macro/test-same-crate.rs
@@ -0,0 +1,16 @@
+// compile-flags: --test
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn mac(input: TokenStream) -> TokenStream { loop {} }
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn t() { crate::mac!(A) }
+    //~^ ERROR can't use a procedural macro from the same crate that defines it
+    //~| HELP you can define integration tests in a directory named `tests`
+}
diff --git a/tests/ui/proc-macro/test-same-crate.stderr b/tests/ui/proc-macro/test-same-crate.stderr
new file mode 100644
index 00000000000..5d12e149c3c
--- /dev/null
+++ b/tests/ui/proc-macro/test-same-crate.stderr
@@ -0,0 +1,10 @@
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/test-same-crate.rs:13:14
+   |
+LL |     fn t() { crate::mac!(A) }
+   |              ^^^^^^^^^^
+   |
+   = help: you can define integration tests in a directory named `tests`
+
+error: aborting due to previous error
+