about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2021-08-23 20:45:50 +0200
committerGitHub <noreply@github.com>2021-08-23 20:45:50 +0200
commitc31e02a24caac2a4277475a79eb2934141265dac (patch)
treebaceff4bbe7779168f2a9f387e8481ed0df24291
parent5cf025f076e76d235cc3e795a22499cff9f4fc62 (diff)
parent908ce2fd1f8f87a18f005b6d86276649786475d8 (diff)
Rollup merge of #88232 - m-ou-se:macro-name-imported-but-not-macro, r=estebank
Add notes to macro-not-found diagnostics to point out how things with the same name were not a match.

This adds notes like:
```
error: cannot find derive macro `Serialize` in this scope
  --> $DIR/issue-88206.rs:22:10
   |
LL | #[derive(Serialize)]
   |          ^^^^^^^^^
   |
note: `Serialize` is imported here, but it is not a derive macro
  --> $DIR/issue-88206.rs:17:11
   |
LL | use hey::{Serialize, Deserialize};
   |           ^^^^^^^^^
```

Fixes https://github.com/rust-lang/rust/issues/88206

Includes https://github.com/rust-lang/rust/pull/88229

r? `@estebank`
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs52
-rw-r--r--src/test/ui/issues/issue-11692-2.stderr2
-rw-r--r--src/test/ui/macros/issue-88206.rs66
-rw-r--r--src/test/ui/macros/issue-88206.stderr114
-rw-r--r--src/test/ui/macros/issue-88228.rs1
-rw-r--r--src/test/ui/macros/issue-88228.stderr4
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-3.stderr2
-rw-r--r--src/test/ui/proc-macro/macro-namespace-reserved-2.stderr10
8 files changed, 250 insertions, 1 deletions
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 3cf04268756..ca2c22854c4 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -956,9 +956,61 @@ impl<'a> Resolver<'a> {
         if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
             let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
             err.span_note(ident.span, &msg);
+            return;
         }
         if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
             err.help("have you added the `#[macro_use]` on the module/import?");
+            return;
+        }
+        for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
+            if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
+                ident,
+                ScopeSet::All(ns, false),
+                &parent_scope,
+                false,
+                false,
+                ident.span,
+            ) {
+                let desc = match binding.res() {
+                    Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
+                        "a function-like macro".to_string()
+                    }
+                    Res::Def(DefKind::Macro(MacroKind::Attr), _) | Res::NonMacroAttr(..) => {
+                        format!("an attribute: `#[{}]`", ident)
+                    }
+                    Res::Def(DefKind::Macro(MacroKind::Derive), _) => {
+                        format!("a derive macro: `#[derive({})]`", ident)
+                    }
+                    Res::ToolMod => {
+                        // Don't confuse the user with tool modules.
+                        continue;
+                    }
+                    Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
+                        "only a trait, without a derive macro".to_string()
+                    }
+                    res => format!(
+                        "{} {}, not {} {}",
+                        res.article(),
+                        res.descr(),
+                        macro_kind.article(),
+                        macro_kind.descr_expected(),
+                    ),
+                };
+                if let crate::NameBindingKind::Import { import, .. } = binding.kind {
+                    if !import.span.is_dummy() {
+                        err.span_note(
+                            import.span,
+                            &format!("`{}` is imported here, but it is {}", ident, desc),
+                        );
+                        // Silence the 'unused import' warning we might get,
+                        // since this diagnostic already covers that import.
+                        self.record_use(ident, binding, false);
+                        return;
+                    }
+                }
+                err.note(&format!("`{}` is in scope, but it is {}", ident, desc));
+                return;
+            }
         }
     }
 
diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr
index f021943da32..84746ca2c88 100644
--- a/src/test/ui/issues/issue-11692-2.stderr
+++ b/src/test/ui/issues/issue-11692-2.stderr
@@ -3,6 +3,8 @@ error: cannot find macro `test` in this scope
    |
 LL |     concat!(test!());
    |             ^^^^
+   |
+   = note: `test` is in scope, but it is an attribute: `#[test]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/issue-88206.rs b/src/test/ui/macros/issue-88206.rs
new file mode 100644
index 00000000000..14e2f66068b
--- /dev/null
+++ b/src/test/ui/macros/issue-88206.rs
@@ -0,0 +1,66 @@
+// compile-flags: -Z deduplicate-diagnostics=yes
+
+#![warn(unused_imports)]
+
+use std::str::*;
+//~^ NOTE `from_utf8` is imported here, but it is a function
+//~| NOTE `from_utf8_mut` is imported here, but it is a function
+//~| NOTE `from_utf8_unchecked` is imported here, but it is a function
+
+mod hey {
+    pub trait Serialize {}
+    pub trait Deserialize {}
+
+    pub struct X(i32);
+}
+
+use hey::{Serialize, Deserialize, X};
+//~^ NOTE `Serialize` is imported here, but it is only a trait, without a derive macro
+//~| NOTE `Deserialize` is imported here, but it is a trait
+//~| NOTE `X` is imported here, but it is a struct
+
+#[derive(Serialize)]
+//~^ ERROR cannot find derive macro `Serialize`
+struct A;
+
+#[derive(from_utf8_mut)]
+//~^ ERROR cannot find derive macro `from_utf8_mut`
+struct B;
+
+#[derive(println)]
+//~^ ERROR cannot find derive macro `println`
+//~| NOTE `println` is in scope, but it is a function-like macro
+struct C;
+
+#[Deserialize]
+//~^ ERROR cannot find attribute `Deserialize`
+struct D;
+
+#[from_utf8_unchecked]
+//~^ ERROR cannot find attribute `from_utf8_unchecked`
+struct E;
+
+#[println]
+//~^ ERROR cannot find attribute `println`
+//~| NOTE `println` is in scope, but it is a function-like macro
+struct F;
+
+fn main() {
+    from_utf8!();
+    //~^ ERROR cannot find macro `from_utf8`
+
+    Box!();
+    //~^ ERROR cannot find macro `Box`
+    //~| NOTE `Box` is in scope, but it is a struct
+
+    Copy!();
+    //~^ ERROR cannot find macro `Copy`
+    //~| NOTE `Copy` is in scope, but it is a derive macro
+
+    test!();
+    //~^ ERROR cannot find macro `test`
+    //~| NOTE `test` is in scope, but it is an attribute
+
+    X!();
+    //~^ ERROR cannot find macro `X`
+}
diff --git a/src/test/ui/macros/issue-88206.stderr b/src/test/ui/macros/issue-88206.stderr
new file mode 100644
index 00000000000..f7f5b564880
--- /dev/null
+++ b/src/test/ui/macros/issue-88206.stderr
@@ -0,0 +1,114 @@
+error: cannot find macro `X` in this scope
+  --> $DIR/issue-88206.rs:64:5
+   |
+LL |     X!();
+   |     ^
+   |
+note: `X` is imported here, but it is a struct, not a macro
+  --> $DIR/issue-88206.rs:17:35
+   |
+LL | use hey::{Serialize, Deserialize, X};
+   |                                   ^
+
+error: cannot find macro `test` in this scope
+  --> $DIR/issue-88206.rs:60:5
+   |
+LL |     test!();
+   |     ^^^^
+   |
+   = note: `test` is in scope, but it is an attribute: `#[test]`
+
+error: cannot find macro `Copy` in this scope
+  --> $DIR/issue-88206.rs:56:5
+   |
+LL |     Copy!();
+   |     ^^^^
+   |
+   = note: `Copy` is in scope, but it is a derive macro: `#[derive(Copy)]`
+
+error: cannot find macro `Box` in this scope
+  --> $DIR/issue-88206.rs:52:5
+   |
+LL |     Box!();
+   |     ^^^
+   |
+   = note: `Box` is in scope, but it is a struct, not a macro
+
+error: cannot find macro `from_utf8` in this scope
+  --> $DIR/issue-88206.rs:49:5
+   |
+LL |     from_utf8!();
+   |     ^^^^^^^^^
+   |
+note: `from_utf8` is imported here, but it is a function, not a macro
+  --> $DIR/issue-88206.rs:5:5
+   |
+LL | use std::str::*;
+   |     ^^^^^^^^^^^
+
+error: cannot find attribute `println` in this scope
+  --> $DIR/issue-88206.rs:43:3
+   |
+LL | #[println]
+   |   ^^^^^^^
+   |
+   = note: `println` is in scope, but it is a function-like macro
+
+error: cannot find attribute `from_utf8_unchecked` in this scope
+  --> $DIR/issue-88206.rs:39:3
+   |
+LL | #[from_utf8_unchecked]
+   |   ^^^^^^^^^^^^^^^^^^^
+   |
+note: `from_utf8_unchecked` is imported here, but it is a function, not an attribute
+  --> $DIR/issue-88206.rs:5:5
+   |
+LL | use std::str::*;
+   |     ^^^^^^^^^^^
+
+error: cannot find attribute `Deserialize` in this scope
+  --> $DIR/issue-88206.rs:35:3
+   |
+LL | #[Deserialize]
+   |   ^^^^^^^^^^^
+   |
+note: `Deserialize` is imported here, but it is a trait, not an attribute
+  --> $DIR/issue-88206.rs:17:22
+   |
+LL | use hey::{Serialize, Deserialize, X};
+   |                      ^^^^^^^^^^^
+
+error: cannot find derive macro `println` in this scope
+  --> $DIR/issue-88206.rs:30:10
+   |
+LL | #[derive(println)]
+   |          ^^^^^^^
+   |
+   = note: `println` is in scope, but it is a function-like macro
+
+error: cannot find derive macro `from_utf8_mut` in this scope
+  --> $DIR/issue-88206.rs:26:10
+   |
+LL | #[derive(from_utf8_mut)]
+   |          ^^^^^^^^^^^^^
+   |
+note: `from_utf8_mut` is imported here, but it is a function, not a derive macro
+  --> $DIR/issue-88206.rs:5:5
+   |
+LL | use std::str::*;
+   |     ^^^^^^^^^^^
+
+error: cannot find derive macro `Serialize` in this scope
+  --> $DIR/issue-88206.rs:22:10
+   |
+LL | #[derive(Serialize)]
+   |          ^^^^^^^^^
+   |
+note: `Serialize` is imported here, but it is only a trait, without a derive macro
+  --> $DIR/issue-88206.rs:17:11
+   |
+LL | use hey::{Serialize, Deserialize, X};
+   |           ^^^^^^^^^
+
+error: aborting due to 11 previous errors
+
diff --git a/src/test/ui/macros/issue-88228.rs b/src/test/ui/macros/issue-88228.rs
index 615b865e9f1..cbdef5f0d40 100644
--- a/src/test/ui/macros/issue-88228.rs
+++ b/src/test/ui/macros/issue-88228.rs
@@ -13,6 +13,7 @@ struct A;
 
 #[derive(println)]
 //~^ ERROR cannot find derive macro `println`
+//~|`println` is in scope, but it is a function-like macro
 struct B;
 
 fn main() {
diff --git a/src/test/ui/macros/issue-88228.stderr b/src/test/ui/macros/issue-88228.stderr
index b164e39064c..62afa67a783 100644
--- a/src/test/ui/macros/issue-88228.stderr
+++ b/src/test/ui/macros/issue-88228.stderr
@@ -1,5 +1,5 @@
 error: cannot find macro `bla` in this scope
-  --> $DIR/issue-88228.rs:19:5
+  --> $DIR/issue-88228.rs:20:5
    |
 LL |     bla!();
    |     ^^^
@@ -12,6 +12,8 @@ error: cannot find derive macro `println` in this scope
    |
 LL | #[derive(println)]
    |          ^^^^^^^
+   |
+   = note: `println` is in scope, but it is a function-like macro
 
 error: cannot find derive macro `Bla` in this scope
   --> $DIR/issue-88228.rs:9:10
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 1abb501ec80..70900a6bc81 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
@@ -8,6 +8,8 @@ LL |     inline!();
    |
 LL |     macro_rules! line {
    |     ----------------- similarly named macro `line` defined here
+   |
+   = note: `inline` is in scope, but it is an attribute: `#[inline]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
index a617319faea..633a6c6a0d3 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -93,30 +93,40 @@ error: cannot find macro `my_macro_attr` in this scope
    |
 LL |     my_macro_attr!();
    |     ^^^^^^^^^^^^^
+   |
+   = note: `my_macro_attr` is in scope, but it is an attribute: `#[my_macro_attr]`
 
 error: cannot find macro `MyTrait` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:33:5
    |
 LL |     MyTrait!();
    |     ^^^^^^^
+   |
+   = note: `MyTrait` is in scope, but it is a derive macro: `#[derive(MyTrait)]`
 
 error: cannot find attribute `my_macro` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:38:3
    |
 LL | #[my_macro]
    |   ^^^^^^^^
+   |
+   = note: `my_macro` is in scope, but it is a function-like macro
 
 error: cannot find derive macro `my_macro` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:48:10
    |
 LL | #[derive(my_macro)]
    |          ^^^^^^^^
+   |
+   = note: `my_macro` is in scope, but it is a function-like macro
 
 error: cannot find derive macro `my_macro` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:48:10
    |
 LL | #[derive(my_macro)]
    |          ^^^^^^^^
+   |
+   = note: `my_macro` is in scope, but it is a function-like macro
 
 error: aborting due to 20 previous errors