improve help for multiple #[default] variants
This commit is contained in:
parent
390e3c8b66
commit
f697a00f76
5 changed files with 111 additions and 47 deletions
|
|
@ -127,18 +127,17 @@ fn extract_default_variant<'a>(
|
|||
[first, rest @ ..] => {
|
||||
let suggs = default_variants
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
let spans = default_variants
|
||||
.filter_map(|variant| {
|
||||
let keep = attr::find_by_name(&variant.attrs, kw::Default)?.span;
|
||||
let spans: Vec<Span> = default_variants
|
||||
.iter()
|
||||
.filter_map(|v| {
|
||||
if v.span == variant.span {
|
||||
None
|
||||
} else {
|
||||
Some(attr::find_by_name(&v.attrs, kw::Default)?.span)
|
||||
}
|
||||
.flat_map(|v| {
|
||||
attr::filter_by_name(&v.attrs, kw::Default)
|
||||
.filter_map(|attr| (attr.span != keep).then_some(attr.span))
|
||||
})
|
||||
.collect();
|
||||
errors::MultipleDefaultsSugg { spans, ident: variant.ident }
|
||||
(!spans.is_empty())
|
||||
.then_some(errors::MultipleDefaultsSugg { spans, ident: variant.ident })
|
||||
})
|
||||
.collect();
|
||||
cx.emit_err(errors::MultipleDefaults {
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
// compile-flags: --crate-type=lib
|
||||
|
||||
#[derive(Default)] //~ ERROR multiple declared defaults
|
||||
enum E {
|
||||
#[default]
|
||||
A,
|
||||
#[default]
|
||||
A, //~ ERROR defined multiple times
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
error: multiple declared defaults
|
||||
--> $DIR/issue-105101.rs:3:10
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
...
|
||||
LL | A,
|
||||
| - first default
|
||||
LL | #[default]
|
||||
LL | A,
|
||||
| - additional default
|
||||
|
|
||||
= note: only one variant can be default
|
||||
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0428]: the name `A` is defined multiple times
|
||||
--> $DIR/issue-105101.rs:8:5
|
||||
|
|
||||
LL | A,
|
||||
| - previous definition of the type `A` here
|
||||
LL | #[default]
|
||||
LL | A,
|
||||
| ^ `A` redefined here
|
||||
|
|
||||
= note: `A` must be defined only once in the type namespace of this enum
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0428`.
|
||||
41
tests/ui/deriving/multiple-defaults.rs
Normal file
41
tests/ui/deriving/multiple-defaults.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// compile-flags: --crate-type=lib
|
||||
|
||||
// When we get multiple `#[default]` variants, we emit several tool-only suggestions
|
||||
// to remove all except one of the `#[default]`s.
|
||||
|
||||
#[derive(Default)] //~ ERROR multiple declared defaults
|
||||
enum A {
|
||||
#[default] //~ HELP make `B` default
|
||||
#[default] //~ HELP make `A` default
|
||||
A,
|
||||
#[default] // also "HELP make `A` default", but compiletest can't handle multispans
|
||||
B,
|
||||
}
|
||||
|
||||
// Originally, we took each defaulted variant and emitted the suggestion for every variant
|
||||
// with a different identifier, causing an ICE when multiple variants have the same identifier:
|
||||
// https://github.com/rust-lang/rust/pull/105106
|
||||
#[derive(Default)] //~ ERROR multiple declared defaults
|
||||
enum E {
|
||||
#[default] //~ HELP make `A` default
|
||||
A,
|
||||
#[default] //~ HELP make `A` default
|
||||
A, //~ ERROR defined multiple times
|
||||
}
|
||||
|
||||
// Then, we took each defaulted variant and emitted the suggestion for every variant
|
||||
// with a different span, causing an ICE when multiple variants have the same span:
|
||||
// https://github.com/rust-lang/rust/issues/118119
|
||||
macro_rules! m {
|
||||
{ $($id:ident)* } => {
|
||||
#[derive(Default)] //~ ERROR multiple declared defaults
|
||||
enum F {
|
||||
$(
|
||||
#[default]
|
||||
$id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m! { A B }
|
||||
62
tests/ui/deriving/multiple-defaults.stderr
Normal file
62
tests/ui/deriving/multiple-defaults.stderr
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
error: multiple declared defaults
|
||||
--> $DIR/multiple-defaults.rs:6:10
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
...
|
||||
LL | A,
|
||||
| - first default
|
||||
LL | #[default] // also "HELP make `A` default", but compiletest can't handle multispans
|
||||
LL | B,
|
||||
| - additional default
|
||||
|
|
||||
= note: only one variant can be default
|
||||
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: multiple declared defaults
|
||||
--> $DIR/multiple-defaults.rs:18:10
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
...
|
||||
LL | A,
|
||||
| - first default
|
||||
LL | #[default]
|
||||
LL | A,
|
||||
| - additional default
|
||||
|
|
||||
= note: only one variant can be default
|
||||
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0428]: the name `A` is defined multiple times
|
||||
--> $DIR/multiple-defaults.rs:23:5
|
||||
|
|
||||
LL | A,
|
||||
| - previous definition of the type `A` here
|
||||
LL | #[default]
|
||||
LL | A,
|
||||
| ^ `A` redefined here
|
||||
|
|
||||
= note: `A` must be defined only once in the type namespace of this enum
|
||||
|
||||
error: multiple declared defaults
|
||||
--> $DIR/multiple-defaults.rs:31:18
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
...
|
||||
LL | $id,
|
||||
| ---
|
||||
| |
|
||||
| first default
|
||||
| additional default
|
||||
...
|
||||
LL | m! { A B }
|
||||
| ---------- in this macro invocation
|
||||
|
|
||||
= note: only one variant can be default
|
||||
= note: this error originates in the derive macro `Default` which comes from the expansion of the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0428`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue