diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 3cf042687562b..ca2c22854c4f5 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 f021943da32da..84746ca2c889c 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 0000000000000..14e2f66068b01 --- /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 0000000000000..f7f5b56488007 --- /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 615b865e9f1e1..cbdef5f0d40a9 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 b164e39064c97..62afa67a783c9 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 1abb501ec8051..70900a6bc81d3 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 a617319faea80..633a6c6a0d3cb 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