Auto merge of #109638 - NotStirred:suggest/non-derive, r=davidtwco
Add suggestion to remove `derive()` if invoked macro is non-derive Adds to the existing `expected derive macro, found {}` error message: ``` help: remove the surrounding "derive()": --> $DIR/macro-path-prelude-fail-4.rs:1:3 | LL | #[derive(inline)] | ^^^^^^^ ^ ``` This suggestion will either fix the issue, in the case that the macro was valid, or provide a better error message if not Not ready for merge yet, as the highlighted span is only valid for trivial formatting. Is there a nice way to get the parent span of the macro path within `smart_resolve_macro_path`? Closes #109589
This commit is contained in:
commit
194a0bb5d6
@ -213,3 +213,13 @@ resolve_tool_module_imported =
|
|||||||
|
|
||||||
resolve_module_only =
|
resolve_module_only =
|
||||||
visibility must resolve to a module
|
visibility must resolve to a module
|
||||||
|
|
||||||
|
resolve_macro_expected_found =
|
||||||
|
expected {$expected}, found {$found} `{$macro_path}`
|
||||||
|
|
||||||
|
resolve_remove_surrounding_derive =
|
||||||
|
remove from the surrounding `derive()`
|
||||||
|
|
||||||
|
resolve_add_as_non_derive =
|
||||||
|
add as non-Derive macro
|
||||||
|
`#[{$macro_path}]`
|
||||||
|
@ -481,3 +481,30 @@ pub(crate) struct ToolModuleImported {
|
|||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(resolve_module_only)]
|
#[diag(resolve_module_only)]
|
||||||
pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span);
|
pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span);
|
||||||
|
|
||||||
|
#[derive(Diagnostic, Default)]
|
||||||
|
#[diag(resolve_macro_expected_found)]
|
||||||
|
pub(crate) struct MacroExpectedFound<'a> {
|
||||||
|
#[primary_span]
|
||||||
|
pub(crate) span: Span,
|
||||||
|
pub(crate) found: &'a str,
|
||||||
|
pub(crate) expected: &'a str,
|
||||||
|
pub(crate) macro_path: &'a str,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub(crate) remove_surrounding_derive: Option<RemoveSurroundingDerive>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub(crate) add_as_non_derive: Option<AddAsNonDerive<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[help(resolve_remove_surrounding_derive)]
|
||||||
|
pub(crate) struct RemoveSurroundingDerive {
|
||||||
|
#[primary_span]
|
||||||
|
pub(crate) span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[help(resolve_add_as_non_derive)]
|
||||||
|
pub(crate) struct AddAsNonDerive<'a> {
|
||||||
|
pub(crate) macro_path: &'a str,
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! A bunch of methods and structures more or less related to resolving macros and
|
//! A bunch of methods and structures more or less related to resolving macros and
|
||||||
//! interface provided by `Resolver` to macro expander.
|
//! interface provided by `Resolver` to macro expander.
|
||||||
|
|
||||||
|
use crate::errors::{AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive};
|
||||||
use crate::Namespace::*;
|
use crate::Namespace::*;
|
||||||
use crate::{BuiltinMacroState, Determinacy};
|
use crate::{BuiltinMacroState, Determinacy};
|
||||||
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
|
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
|
||||||
@ -543,12 +544,29 @@ fn smart_resolve_macro_path(
|
|||||||
};
|
};
|
||||||
if let Some((article, expected)) = unexpected_res {
|
if let Some((article, expected)) = unexpected_res {
|
||||||
let path_str = pprust::path_to_string(path);
|
let path_str = pprust::path_to_string(path);
|
||||||
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str);
|
|
||||||
self.tcx
|
let mut err = MacroExpectedFound {
|
||||||
.sess
|
span: path.span,
|
||||||
.struct_span_err(path.span, &msg)
|
expected,
|
||||||
.span_label(path.span, format!("not {} {}", article, expected))
|
found: res.descr(),
|
||||||
.emit();
|
macro_path: &path_str,
|
||||||
|
..Default::default() // Subdiagnostics default to None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Suggest moving the macro out of the derive() if the macro isn't Derive
|
||||||
|
if !path.span.from_expansion()
|
||||||
|
&& kind == MacroKind::Derive
|
||||||
|
&& ext.macro_kind() != MacroKind::Derive
|
||||||
|
{
|
||||||
|
err.remove_surrounding_derive = Some(RemoveSurroundingDerive { span: path.span });
|
||||||
|
err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str });
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut err = self.tcx.sess.create_err(err);
|
||||||
|
err.span_label(path.span, format!("not {} {}", article, expected));
|
||||||
|
|
||||||
|
err.emit();
|
||||||
|
|
||||||
return Ok((self.dummy_ext(kind), Res::Err));
|
return Ok((self.dummy_ext(kind), Res::Err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,14 @@ error: expected derive macro, found built-in attribute `inline`
|
|||||||
|
|
|
|
||||||
LL | #[derive(inline)]
|
LL | #[derive(inline)]
|
||||||
| ^^^^^^ not a derive macro
|
| ^^^^^^ not a derive macro
|
||||||
|
|
|
||||||
|
help: remove from the surrounding `derive()`
|
||||||
|
--> $DIR/macro-path-prelude-fail-4.rs:1:10
|
||||||
|
|
|
||||||
|
LL | #[derive(inline)]
|
||||||
|
| ^^^^^^
|
||||||
|
= help: add as non-Derive macro
|
||||||
|
`#[inline]`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
10
tests/ui/macros/macro-path-prelude-fail-5.rs
Normal file
10
tests/ui/macros/macro-path-prelude-fail-5.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#[derive(Clone, Debug)] // OK
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
#[derive(Debug, inline)] //~ ERROR expected derive macro, found built-in attribute `inline`
|
||||||
|
struct T;
|
||||||
|
|
||||||
|
#[derive(inline, Debug)] //~ ERROR expected derive macro, found built-in attribute `inline`
|
||||||
|
struct U;
|
||||||
|
|
||||||
|
fn main() {}
|
30
tests/ui/macros/macro-path-prelude-fail-5.stderr
Normal file
30
tests/ui/macros/macro-path-prelude-fail-5.stderr
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
error: expected derive macro, found built-in attribute `inline`
|
||||||
|
--> $DIR/macro-path-prelude-fail-5.rs:4:17
|
||||||
|
|
|
||||||
|
LL | #[derive(Debug, inline)]
|
||||||
|
| ^^^^^^ not a derive macro
|
||||||
|
|
|
||||||
|
help: remove from the surrounding `derive()`
|
||||||
|
--> $DIR/macro-path-prelude-fail-5.rs:4:17
|
||||||
|
|
|
||||||
|
LL | #[derive(Debug, inline)]
|
||||||
|
| ^^^^^^
|
||||||
|
= help: add as non-Derive macro
|
||||||
|
`#[inline]`
|
||||||
|
|
||||||
|
error: expected derive macro, found built-in attribute `inline`
|
||||||
|
--> $DIR/macro-path-prelude-fail-5.rs:7:10
|
||||||
|
|
|
||||||
|
LL | #[derive(inline, Debug)]
|
||||||
|
| ^^^^^^ not a derive macro
|
||||||
|
|
|
||||||
|
help: remove from the surrounding `derive()`
|
||||||
|
--> $DIR/macro-path-prelude-fail-5.rs:7:10
|
||||||
|
|
|
||||||
|
LL | #[derive(inline, Debug)]
|
||||||
|
| ^^^^^^
|
||||||
|
= help: add as non-Derive macro
|
||||||
|
`#[inline]`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
@ -57,6 +57,14 @@ error: expected derive macro, found attribute macro `my_macro_attr`
|
|||||||
|
|
|
|
||||||
LL | #[derive(my_macro_attr)]
|
LL | #[derive(my_macro_attr)]
|
||||||
| ^^^^^^^^^^^^^ not a derive macro
|
| ^^^^^^^^^^^^^ not a derive macro
|
||||||
|
|
|
||||||
|
help: remove from the surrounding `derive()`
|
||||||
|
--> $DIR/macro-namespace-reserved-2.rs:53:10
|
||||||
|
|
|
||||||
|
LL | #[derive(my_macro_attr)]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
= help: add as non-Derive macro
|
||||||
|
`#[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:56:10
|
--> $DIR/macro-namespace-reserved-2.rs:56:10
|
||||||
@ -87,6 +95,14 @@ error: expected derive macro, found macro `crate::my_macro`
|
|||||||
|
|
|
|
||||||
LL | #[derive(crate::my_macro)]
|
LL | #[derive(crate::my_macro)]
|
||||||
| ^^^^^^^^^^^^^^^ not a derive macro
|
| ^^^^^^^^^^^^^^^ not a derive macro
|
||||||
|
|
|
||||||
|
help: remove from the surrounding `derive()`
|
||||||
|
--> $DIR/macro-namespace-reserved-2.rs:50:10
|
||||||
|
|
|
||||||
|
LL | #[derive(crate::my_macro)]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
= help: add as non-Derive macro
|
||||||
|
`#[crate::my_macro]`
|
||||||
|
|
||||||
error: cannot find macro `my_macro_attr` in this scope
|
error: cannot find macro `my_macro_attr` in this scope
|
||||||
--> $DIR/macro-namespace-reserved-2.rs:28:5
|
--> $DIR/macro-namespace-reserved-2.rs:28:5
|
||||||
|
@ -3,6 +3,14 @@ error: expected derive macro, found tool attribute `rustfmt::skip`
|
|||||||
|
|
|
|
||||||
LL | #[derive(rustfmt::skip)]
|
LL | #[derive(rustfmt::skip)]
|
||||||
| ^^^^^^^^^^^^^ not a derive macro
|
| ^^^^^^^^^^^^^ not a derive macro
|
||||||
|
|
|
||||||
|
help: remove from the surrounding `derive()`
|
||||||
|
--> $DIR/tool-attributes-misplaced-2.rs:1:10
|
||||||
|
|
|
||||||
|
LL | #[derive(rustfmt::skip)]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
= help: add as non-Derive macro
|
||||||
|
`#[rustfmt::skip]`
|
||||||
|
|
||||||
error: expected macro, found tool attribute `rustfmt::skip`
|
error: expected macro, found tool attribute `rustfmt::skip`
|
||||||
--> $DIR/tool-attributes-misplaced-2.rs:5:5
|
--> $DIR/tool-attributes-misplaced-2.rs:5:5
|
||||||
|
Loading…
Reference in New Issue
Block a user