Skip to content

Commit 194a0bb

Browse files
committed
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
2 parents 88fb1b9 + 668a629 commit 194a0bb

8 files changed

+133
-6
lines changed

compiler/rustc_resolve/messages.ftl

+10
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,13 @@ resolve_tool_module_imported =
213213
214214
resolve_module_only =
215215
visibility must resolve to a module
216+
217+
resolve_macro_expected_found =
218+
expected {$expected}, found {$found} `{$macro_path}`
219+
220+
resolve_remove_surrounding_derive =
221+
remove from the surrounding `derive()`
222+
223+
resolve_add_as_non_derive =
224+
add as non-Derive macro
225+
`#[{$macro_path}]`

compiler/rustc_resolve/src/errors.rs

+27
Original file line numberDiff line numberDiff line change
@@ -481,3 +481,30 @@ pub(crate) struct ToolModuleImported {
481481
#[derive(Diagnostic)]
482482
#[diag(resolve_module_only)]
483483
pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span);
484+
485+
#[derive(Diagnostic, Default)]
486+
#[diag(resolve_macro_expected_found)]
487+
pub(crate) struct MacroExpectedFound<'a> {
488+
#[primary_span]
489+
pub(crate) span: Span,
490+
pub(crate) found: &'a str,
491+
pub(crate) expected: &'a str,
492+
pub(crate) macro_path: &'a str,
493+
#[subdiagnostic]
494+
pub(crate) remove_surrounding_derive: Option<RemoveSurroundingDerive>,
495+
#[subdiagnostic]
496+
pub(crate) add_as_non_derive: Option<AddAsNonDerive<'a>>,
497+
}
498+
499+
#[derive(Subdiagnostic)]
500+
#[help(resolve_remove_surrounding_derive)]
501+
pub(crate) struct RemoveSurroundingDerive {
502+
#[primary_span]
503+
pub(crate) span: Span,
504+
}
505+
506+
#[derive(Subdiagnostic)]
507+
#[help(resolve_add_as_non_derive)]
508+
pub(crate) struct AddAsNonDerive<'a> {
509+
pub(crate) macro_path: &'a str,
510+
}

compiler/rustc_resolve/src/macros.rs

+24-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! A bunch of methods and structures more or less related to resolving macros and
22
//! interface provided by `Resolver` to macro expander.
33
4+
use crate::errors::{AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive};
45
use crate::Namespace::*;
56
use crate::{BuiltinMacroState, Determinacy};
67
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
@@ -543,12 +544,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
543544
};
544545
if let Some((article, expected)) = unexpected_res {
545546
let path_str = pprust::path_to_string(path);
546-
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str);
547-
self.tcx
548-
.sess
549-
.struct_span_err(path.span, &msg)
550-
.span_label(path.span, format!("not {} {}", article, expected))
551-
.emit();
547+
548+
let mut err = MacroExpectedFound {
549+
span: path.span,
550+
expected,
551+
found: res.descr(),
552+
macro_path: &path_str,
553+
..Default::default() // Subdiagnostics default to None
554+
};
555+
556+
// Suggest moving the macro out of the derive() if the macro isn't Derive
557+
if !path.span.from_expansion()
558+
&& kind == MacroKind::Derive
559+
&& ext.macro_kind() != MacroKind::Derive
560+
{
561+
err.remove_surrounding_derive = Some(RemoveSurroundingDerive { span: path.span });
562+
err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str });
563+
}
564+
565+
let mut err = self.tcx.sess.create_err(err);
566+
err.span_label(path.span, format!("not {} {}", article, expected));
567+
568+
err.emit();
569+
552570
return Ok((self.dummy_ext(kind), Res::Err));
553571
}
554572

tests/ui/macros/macro-path-prelude-fail-4.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ error: expected derive macro, found built-in attribute `inline`
33
|
44
LL | #[derive(inline)]
55
| ^^^^^^ not a derive macro
6+
|
7+
help: remove from the surrounding `derive()`
8+
--> $DIR/macro-path-prelude-fail-4.rs:1:10
9+
|
10+
LL | #[derive(inline)]
11+
| ^^^^^^
12+
= help: add as non-Derive macro
13+
`#[inline]`
614

715
error: aborting due to previous error
816

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#[derive(Clone, Debug)] // OK
2+
struct S;
3+
4+
#[derive(Debug, inline)] //~ ERROR expected derive macro, found built-in attribute `inline`
5+
struct T;
6+
7+
#[derive(inline, Debug)] //~ ERROR expected derive macro, found built-in attribute `inline`
8+
struct U;
9+
10+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error: expected derive macro, found built-in attribute `inline`
2+
--> $DIR/macro-path-prelude-fail-5.rs:4:17
3+
|
4+
LL | #[derive(Debug, inline)]
5+
| ^^^^^^ not a derive macro
6+
|
7+
help: remove from the surrounding `derive()`
8+
--> $DIR/macro-path-prelude-fail-5.rs:4:17
9+
|
10+
LL | #[derive(Debug, inline)]
11+
| ^^^^^^
12+
= help: add as non-Derive macro
13+
`#[inline]`
14+
15+
error: expected derive macro, found built-in attribute `inline`
16+
--> $DIR/macro-path-prelude-fail-5.rs:7:10
17+
|
18+
LL | #[derive(inline, Debug)]
19+
| ^^^^^^ not a derive macro
20+
|
21+
help: remove from the surrounding `derive()`
22+
--> $DIR/macro-path-prelude-fail-5.rs:7:10
23+
|
24+
LL | #[derive(inline, Debug)]
25+
| ^^^^^^
26+
= help: add as non-Derive macro
27+
`#[inline]`
28+
29+
error: aborting due to 2 previous errors
30+

tests/ui/proc-macro/macro-namespace-reserved-2.stderr

+16
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ error: expected derive macro, found attribute macro `my_macro_attr`
5757
|
5858
LL | #[derive(my_macro_attr)]
5959
| ^^^^^^^^^^^^^ not a derive macro
60+
|
61+
help: remove from the surrounding `derive()`
62+
--> $DIR/macro-namespace-reserved-2.rs:53:10
63+
|
64+
LL | #[derive(my_macro_attr)]
65+
| ^^^^^^^^^^^^^
66+
= help: add as non-Derive macro
67+
`#[my_macro_attr]`
6068

6169
error: can't use a procedural macro from the same crate that defines it
6270
--> $DIR/macro-namespace-reserved-2.rs:56:10
@@ -87,6 +95,14 @@ error: expected derive macro, found macro `crate::my_macro`
8795
|
8896
LL | #[derive(crate::my_macro)]
8997
| ^^^^^^^^^^^^^^^ not a derive macro
98+
|
99+
help: remove from the surrounding `derive()`
100+
--> $DIR/macro-namespace-reserved-2.rs:50:10
101+
|
102+
LL | #[derive(crate::my_macro)]
103+
| ^^^^^^^^^^^^^^^
104+
= help: add as non-Derive macro
105+
`#[crate::my_macro]`
90106

91107
error: cannot find macro `my_macro_attr` in this scope
92108
--> $DIR/macro-namespace-reserved-2.rs:28:5

tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ error: expected derive macro, found tool attribute `rustfmt::skip`
33
|
44
LL | #[derive(rustfmt::skip)]
55
| ^^^^^^^^^^^^^ not a derive macro
6+
|
7+
help: remove from the surrounding `derive()`
8+
--> $DIR/tool-attributes-misplaced-2.rs:1:10
9+
|
10+
LL | #[derive(rustfmt::skip)]
11+
| ^^^^^^^^^^^^^
12+
= help: add as non-Derive macro
13+
`#[rustfmt::skip]`
614

715
error: expected macro, found tool attribute `rustfmt::skip`
816
--> $DIR/tool-attributes-misplaced-2.rs:5:5

0 commit comments

Comments
 (0)