Rollup merge of #84818 - ABouttefeux:enum-suggest, r=jackh726
suggestion for unit enum variant when matched with a patern resolve #84700 add suggestion for code like ```rust enum FarmAnimal { Worm, Cow, Bull, Chicken { num_eggs: usize }, Dog (String), } fn what_does_the_animal_say(animal: &FarmAnimal) { let noise = match animal { FarmAnimal::Cow(_) => "moo".to_string(), _ => todo!() }; println!("{:?} says: {:?}", animal, noise); } ``` ``` error[E0532]: expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow` --> $DIR/issue-84700.rs:15:9 | LL | Cow, | --- `FarmAnimal::Cow` defined here ... LL | FarmAnimal::Cow(_) => "moo".to_string(), | ^^^^^^^^^^^^^^^^^^ help: use this syntax instead: `FarmAnimal::Cow` ```
This commit is contained in:
commit
b0c7e64de0
8 changed files with 193 additions and 35 deletions
|
@ -819,6 +819,19 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let find_span = |source: &PathSource<'_>, err: &mut DiagnosticBuilder<'_>| {
|
||||||
|
match source {
|
||||||
|
PathSource::Expr(Some(Expr { span, kind: ExprKind::Call(_, _), .. }))
|
||||||
|
| PathSource::TupleStruct(span, _) => {
|
||||||
|
// We want the main underline to cover the suggested code as well for
|
||||||
|
// cleaner output.
|
||||||
|
err.set_span(*span);
|
||||||
|
*span
|
||||||
|
}
|
||||||
|
_ => span,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut bad_struct_syntax_suggestion = |def_id: DefId| {
|
let mut bad_struct_syntax_suggestion = |def_id: DefId| {
|
||||||
let (followed_by_brace, closing_brace) = self.followed_by_brace(span);
|
let (followed_by_brace, closing_brace) = self.followed_by_brace(span);
|
||||||
|
|
||||||
|
@ -862,18 +875,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
|
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
|
||||||
let span = match &source {
|
let span = find_span(&source, err);
|
||||||
PathSource::Expr(Some(Expr {
|
|
||||||
span, kind: ExprKind::Call(_, _), ..
|
|
||||||
}))
|
|
||||||
| PathSource::TupleStruct(span, _) => {
|
|
||||||
// We want the main underline to cover the suggested code as well for
|
|
||||||
// cleaner output.
|
|
||||||
err.set_span(*span);
|
|
||||||
*span
|
|
||||||
}
|
|
||||||
_ => span,
|
|
||||||
};
|
|
||||||
if let Some(span) = self.def_span(def_id) {
|
if let Some(span) = self.def_span(def_id) {
|
||||||
err.span_label(span, &format!("`{}` defined here", path_str));
|
err.span_label(span, &format!("`{}` defined here", path_str));
|
||||||
}
|
}
|
||||||
|
@ -1047,6 +1049,23 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
) if ns == ValueNS => {
|
) if ns == ValueNS => {
|
||||||
bad_struct_syntax_suggestion(def_id);
|
bad_struct_syntax_suggestion(def_id);
|
||||||
}
|
}
|
||||||
|
(Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => {
|
||||||
|
match source {
|
||||||
|
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
|
||||||
|
let span = find_span(&source, err);
|
||||||
|
if let Some(span) = self.def_span(def_id) {
|
||||||
|
err.span_label(span, &format!("`{}` defined here", path_str));
|
||||||
|
}
|
||||||
|
err.span_suggestion(
|
||||||
|
span,
|
||||||
|
&format!("use this syntax instead"),
|
||||||
|
format!("{path_str}"),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => return false,
|
||||||
|
}
|
||||||
|
}
|
||||||
(Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => {
|
(Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => {
|
||||||
if let Some(span) = self.def_span(def_id) {
|
if let Some(span) = self.def_span(def_id) {
|
||||||
err.span_label(span, &format!("`{}` defined here", path_str));
|
err.span_label(span, &format!("`{}` defined here", path_str));
|
||||||
|
|
|
@ -1,84 +1,154 @@
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2`
|
error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2`
|
||||||
--> $DIR/empty-struct-unit-pat.rs:21:9
|
--> $DIR/empty-struct-unit-pat.rs:21:9
|
||||||
|
|
|
|
||||||
|
LL | struct Empty2;
|
||||||
|
| -------------- `Empty2` defined here
|
||||||
|
...
|
||||||
LL | Empty2() => ()
|
LL | Empty2() => ()
|
||||||
| ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
::: $DIR/auxiliary/empty-struct.rs:3:1
|
::: $DIR/auxiliary/empty-struct.rs:3:1
|
||||||
|
|
|
|
||||||
LL | pub struct XEmpty6();
|
LL | pub struct XEmpty6();
|
||||||
| --------------------- similarly named tuple struct `XEmpty6` defined here
|
| --------------------- similarly named tuple struct `XEmpty6` defined here
|
||||||
|
|
|
||||||
|
help: use this syntax instead
|
||||||
|
|
|
||||||
|
LL | Empty2 => ()
|
||||||
|
| ^^^^^^
|
||||||
|
help: a tuple struct with a similar name exists
|
||||||
|
|
|
||||||
|
LL | XEmpty6() => ()
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2`
|
error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2`
|
||||||
--> $DIR/empty-struct-unit-pat.rs:24:9
|
--> $DIR/empty-struct-unit-pat.rs:24:9
|
||||||
|
|
|
|
||||||
LL | XEmpty2() => ()
|
LL | XEmpty2() => ()
|
||||||
| ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
|
| ^^^^^^^^^
|
||||||
|
|
|
|
||||||
::: $DIR/auxiliary/empty-struct.rs:3:1
|
::: $DIR/auxiliary/empty-struct.rs:2:1
|
||||||
|
|
|
|
||||||
|
LL | pub struct XEmpty2;
|
||||||
|
| ------------------- `XEmpty2` defined here
|
||||||
LL | pub struct XEmpty6();
|
LL | pub struct XEmpty6();
|
||||||
| --------------------- similarly named tuple struct `XEmpty6` defined here
|
| --------------------- similarly named tuple struct `XEmpty6` defined here
|
||||||
|
|
|
||||||
|
help: use this syntax instead
|
||||||
|
|
|
||||||
|
LL | XEmpty2 => ()
|
||||||
|
| ^^^^^^^
|
||||||
|
help: a tuple struct with a similar name exists
|
||||||
|
|
|
||||||
|
LL | XEmpty6() => ()
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2`
|
error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2`
|
||||||
--> $DIR/empty-struct-unit-pat.rs:28:9
|
--> $DIR/empty-struct-unit-pat.rs:28:9
|
||||||
|
|
|
|
||||||
|
LL | struct Empty2;
|
||||||
|
| -------------- `Empty2` defined here
|
||||||
|
...
|
||||||
LL | Empty2(..) => ()
|
LL | Empty2(..) => ()
|
||||||
| ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
|
| ^^^^^^^^^^
|
||||||
|
|
|
|
||||||
::: $DIR/auxiliary/empty-struct.rs:3:1
|
::: $DIR/auxiliary/empty-struct.rs:3:1
|
||||||
|
|
|
|
||||||
LL | pub struct XEmpty6();
|
LL | pub struct XEmpty6();
|
||||||
| --------------------- similarly named tuple struct `XEmpty6` defined here
|
| --------------------- similarly named tuple struct `XEmpty6` defined here
|
||||||
|
|
|
||||||
|
help: use this syntax instead
|
||||||
|
|
|
||||||
|
LL | Empty2 => ()
|
||||||
|
| ^^^^^^
|
||||||
|
help: a tuple struct with a similar name exists
|
||||||
|
|
|
||||||
|
LL | XEmpty6(..) => ()
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2`
|
error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2`
|
||||||
--> $DIR/empty-struct-unit-pat.rs:32:9
|
--> $DIR/empty-struct-unit-pat.rs:32:9
|
||||||
|
|
|
|
||||||
LL | XEmpty2(..) => ()
|
LL | XEmpty2(..) => ()
|
||||||
| ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
::: $DIR/auxiliary/empty-struct.rs:3:1
|
::: $DIR/auxiliary/empty-struct.rs:2:1
|
||||||
|
|
|
|
||||||
|
LL | pub struct XEmpty2;
|
||||||
|
| ------------------- `XEmpty2` defined here
|
||||||
LL | pub struct XEmpty6();
|
LL | pub struct XEmpty6();
|
||||||
| --------------------- similarly named tuple struct `XEmpty6` defined here
|
| --------------------- similarly named tuple struct `XEmpty6` defined here
|
||||||
|
|
|
||||||
|
help: use this syntax instead
|
||||||
|
|
|
||||||
|
LL | XEmpty2 => ()
|
||||||
|
| ^^^^^^^
|
||||||
|
help: a tuple struct with a similar name exists
|
||||||
|
|
|
||||||
|
LL | XEmpty6(..) => ()
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4`
|
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4`
|
||||||
--> $DIR/empty-struct-unit-pat.rs:37:9
|
--> $DIR/empty-struct-unit-pat.rs:37:9
|
||||||
|
|
|
|
||||||
|
LL | Empty4
|
||||||
|
| ------ `E::Empty4` defined here
|
||||||
|
...
|
||||||
LL | E::Empty4() => ()
|
LL | E::Empty4() => ()
|
||||||
| ^^^^^^^^^ not a tuple struct or tuple variant
|
| ^^^^^^^^^^^ help: use this syntax instead: `E::Empty4`
|
||||||
|
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit variant `XE::XEmpty4`
|
error[E0532]: expected tuple struct or tuple variant, found unit variant `XE::XEmpty4`
|
||||||
--> $DIR/empty-struct-unit-pat.rs:41:9
|
--> $DIR/empty-struct-unit-pat.rs:41:9
|
||||||
|
|
|
|
||||||
LL | XE::XEmpty4() => (),
|
LL | XE::XEmpty4() => (),
|
||||||
| ^^^^-------
|
| ^^^^^^^^^^^^^
|
||||||
| |
|
|
||||||
| help: a tuple variant with a similar name exists: `XEmpty5`
|
|
||||||
|
|
|
|
||||||
::: $DIR/auxiliary/empty-struct.rs:8:5
|
::: $DIR/auxiliary/empty-struct.rs:7:5
|
||||||
|
|
|
|
||||||
|
LL | XEmpty4,
|
||||||
|
| ------- `XE::XEmpty4` defined here
|
||||||
LL | XEmpty5(),
|
LL | XEmpty5(),
|
||||||
| --------- similarly named tuple variant `XEmpty5` defined here
|
| --------- similarly named tuple variant `XEmpty5` defined here
|
||||||
|
|
|
||||||
|
help: use this syntax instead
|
||||||
|
|
|
||||||
|
LL | XE::XEmpty4 => (),
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
help: a tuple variant with a similar name exists
|
||||||
|
|
|
||||||
|
LL | XE::XEmpty5() => (),
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4`
|
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4`
|
||||||
--> $DIR/empty-struct-unit-pat.rs:46:9
|
--> $DIR/empty-struct-unit-pat.rs:46:9
|
||||||
|
|
|
|
||||||
|
LL | Empty4
|
||||||
|
| ------ `E::Empty4` defined here
|
||||||
|
...
|
||||||
LL | E::Empty4(..) => ()
|
LL | E::Empty4(..) => ()
|
||||||
| ^^^^^^^^^ not a tuple struct or tuple variant
|
| ^^^^^^^^^^^^^ help: use this syntax instead: `E::Empty4`
|
||||||
|
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit variant `XE::XEmpty4`
|
error[E0532]: expected tuple struct or tuple variant, found unit variant `XE::XEmpty4`
|
||||||
--> $DIR/empty-struct-unit-pat.rs:50:9
|
--> $DIR/empty-struct-unit-pat.rs:50:9
|
||||||
|
|
|
|
||||||
LL | XE::XEmpty4(..) => (),
|
LL | XE::XEmpty4(..) => (),
|
||||||
| ^^^^-------
|
| ^^^^^^^^^^^^^^^
|
||||||
| |
|
|
||||||
| help: a tuple variant with a similar name exists: `XEmpty5`
|
|
||||||
|
|
|
|
||||||
::: $DIR/auxiliary/empty-struct.rs:8:5
|
::: $DIR/auxiliary/empty-struct.rs:7:5
|
||||||
|
|
|
|
||||||
|
LL | XEmpty4,
|
||||||
|
| ------- `XE::XEmpty4` defined here
|
||||||
LL | XEmpty5(),
|
LL | XEmpty5(),
|
||||||
| --------- similarly named tuple variant `XEmpty5` defined here
|
| --------- similarly named tuple variant `XEmpty5` defined here
|
||||||
|
|
|
||||||
|
help: use this syntax instead
|
||||||
|
|
|
||||||
|
LL | XE::XEmpty4 => (),
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
help: a tuple variant with a similar name exists
|
||||||
|
|
|
||||||
|
LL | XE::XEmpty5(..) => (),
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,11 @@ LL | Foo::Baz => {}
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit struct `S`
|
error[E0532]: expected tuple struct or tuple variant, found unit struct `S`
|
||||||
--> $DIR/issue-32004.rs:16:9
|
--> $DIR/issue-32004.rs:16:9
|
||||||
|
|
|
|
||||||
|
LL | struct S;
|
||||||
|
| --------- `S` defined here
|
||||||
|
...
|
||||||
LL | S(()) => {}
|
LL | S(()) => {}
|
||||||
| ^ not a tuple struct or tuple variant
|
| ^^^^^ help: use this syntax instead: `S`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,20 @@
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::A`
|
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::A`
|
||||||
--> $DIR/issue-pr29383.rs:9:14
|
--> $DIR/issue-pr29383.rs:9:14
|
||||||
|
|
|
|
||||||
|
LL | A,
|
||||||
|
| - `E::A` defined here
|
||||||
|
...
|
||||||
LL | Some(E::A(..)) => {}
|
LL | Some(E::A(..)) => {}
|
||||||
| ^^^^ not a tuple struct or tuple variant
|
| ^^^^^^^^ help: use this syntax instead: `E::A`
|
||||||
|
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::B`
|
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::B`
|
||||||
--> $DIR/issue-pr29383.rs:11:14
|
--> $DIR/issue-pr29383.rs:11:14
|
||||||
|
|
|
|
||||||
|
LL | B,
|
||||||
|
| - `E::B` defined here
|
||||||
|
...
|
||||||
LL | Some(E::B(..)) => {}
|
LL | Some(E::B(..)) => {}
|
||||||
| ^^^^ not a tuple struct or tuple variant
|
| ^^^^^^^^ help: use this syntax instead: `E::B`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
error[E0532]: expected tuple struct or tuple variant, found unit variant `Color::NoColor`
|
error[E0532]: expected tuple struct or tuple variant, found unit variant `Color::NoColor`
|
||||||
--> $DIR/match-pattern-field-mismatch-2.rs:12:11
|
--> $DIR/match-pattern-field-mismatch-2.rs:12:11
|
||||||
|
|
|
|
||||||
|
LL | NoColor,
|
||||||
|
| ------- `Color::NoColor` defined here
|
||||||
|
...
|
||||||
LL | Color::NoColor(_) => { }
|
LL | Color::NoColor(_) => { }
|
||||||
| ^^^^^^^^^^^^^^ not a tuple struct or tuple variant
|
| ^^^^^^^^^^^^^^^^^ help: use this syntax instead: `Color::NoColor`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,21 @@ error[E0532]: expected tuple struct or tuple variant, found unit variant `A::D`
|
||||||
|
|
|
|
||||||
LL | B(isize, isize),
|
LL | B(isize, isize),
|
||||||
| --------------- similarly named tuple variant `B` defined here
|
| --------------- similarly named tuple variant `B` defined here
|
||||||
|
LL | C(isize, isize, isize),
|
||||||
|
LL | D
|
||||||
|
| - `A::D` defined here
|
||||||
...
|
...
|
||||||
LL | A::D(_) => (),
|
LL | A::D(_) => (),
|
||||||
| ^^^-
|
| ^^^^^^^
|
||||||
| |
|
|
|
||||||
| help: a tuple variant with a similar name exists: `B`
|
help: use this syntax instead
|
||||||
|
|
|
||||||
|
LL | A::D => (),
|
||||||
|
| ^^^^
|
||||||
|
help: a tuple variant with a similar name exists
|
||||||
|
|
|
||||||
|
LL | A::B(_) => (),
|
||||||
|
| ^
|
||||||
|
|
||||||
error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
|
error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
|
||||||
--> $DIR/pattern-error-continue.rs:17:9
|
--> $DIR/pattern-error-continue.rs:17:9
|
||||||
|
|
26
src/test/ui/suggestions/issue-84700.rs
Normal file
26
src/test/ui/suggestions/issue-84700.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// test for suggestion on fieldless enum variant
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
enum FarmAnimal {
|
||||||
|
Worm,
|
||||||
|
Cow,
|
||||||
|
Bull,
|
||||||
|
Chicken { num_eggs: usize },
|
||||||
|
Dog (String),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn what_does_the_animal_say(animal: &FarmAnimal) {
|
||||||
|
|
||||||
|
let noise = match animal {
|
||||||
|
FarmAnimal::Cow(_) => "moo".to_string(),
|
||||||
|
//~^ ERROR expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow`
|
||||||
|
FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(),
|
||||||
|
//~^ ERROR expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken`
|
||||||
|
FarmAnimal::Dog{..} => "woof!".to_string(),
|
||||||
|
_ => todo!()
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{:?} says: {:?}", animal, noise);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
21
src/test/ui/suggestions/issue-84700.stderr
Normal file
21
src/test/ui/suggestions/issue-84700.stderr
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
error[E0532]: expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow`
|
||||||
|
--> $DIR/issue-84700.rs:15:9
|
||||||
|
|
|
||||||
|
LL | Cow,
|
||||||
|
| --- `FarmAnimal::Cow` defined here
|
||||||
|
...
|
||||||
|
LL | FarmAnimal::Cow(_) => "moo".to_string(),
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: use this syntax instead: `FarmAnimal::Cow`
|
||||||
|
|
||||||
|
error[E0532]: expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken`
|
||||||
|
--> $DIR/issue-84700.rs:17:9
|
||||||
|
|
|
||||||
|
LL | Chicken { num_eggs: usize },
|
||||||
|
| --------------------------- `FarmAnimal::Chicken` defined here
|
||||||
|
...
|
||||||
|
LL | FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(),
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `FarmAnimal::Chicken { num_eggs }`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0532`.
|
Loading…
Add table
Add a link
Reference in a new issue