Skip to content

Commit

Permalink
Rollup merge of rust-lang#109638 - NotStirred:suggest/non-derive, r=d…
Browse files Browse the repository at this point in the history
…avidtwco

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 rust-lang#109589
  • Loading branch information
Dylan-DPC authored Apr 10, 2023
2 parents f2c7257 + 668a629 commit f0f5777
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 6 deletions.
10 changes: 10 additions & 0 deletions compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,13 @@ resolve_tool_module_imported =
resolve_module_only =
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}]`
27 changes: 27 additions & 0 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,3 +481,30 @@ pub(crate) struct ToolModuleImported {
#[derive(Diagnostic)]
#[diag(resolve_module_only)]
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,
}
30 changes: 24 additions & 6 deletions compiler/rustc_resolve/src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,6 +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::Namespace::*;
use crate::{BuiltinMacroState, Determinacy};
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
Expand Down Expand Up @@ -543,12 +544,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
};
if let Some((article, expected)) = unexpected_res {
let path_str = pprust::path_to_string(path);
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str);
self.tcx
.sess
.struct_span_err(path.span, &msg)
.span_label(path.span, format!("not {} {}", article, expected))
.emit();

let mut err = MacroExpectedFound {
span: path.span,
expected,
found: res.descr(),
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));
}

Expand Down
8 changes: 8 additions & 0 deletions tests/ui/macros/macro-path-prelude-fail-4.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ error: expected derive macro, found built-in attribute `inline`
|
LL | #[derive(inline)]
| ^^^^^^ 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

10 changes: 10 additions & 0 deletions tests/ui/macros/macro-path-prelude-fail-5.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 30 additions & 0 deletions tests/ui/macros/macro-path-prelude-fail-5.stderr
Original file line number Diff line number Diff line change
@@ -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

16 changes: 16 additions & 0 deletions tests/ui/proc-macro/macro-namespace-reserved-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ error: expected derive macro, found attribute macro `my_macro_attr`
|
LL | #[derive(my_macro_attr)]
| ^^^^^^^^^^^^^ 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
--> $DIR/macro-namespace-reserved-2.rs:56:10
Expand Down Expand Up @@ -87,6 +95,14 @@ error: expected derive macro, found macro `crate::my_macro`
|
LL | #[derive(crate::my_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
--> $DIR/macro-namespace-reserved-2.rs:28:5
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ error: expected derive macro, found tool attribute `rustfmt::skip`
|
LL | #[derive(rustfmt::skip)]
| ^^^^^^^^^^^^^ 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`
--> $DIR/tool-attributes-misplaced-2.rs:5:5
Expand Down

0 comments on commit f0f5777

Please sign in to comment.