Skip to content

Commit

Permalink
add suggestion for unit enum variant when matched with a patern
Browse files Browse the repository at this point in the history
  • Loading branch information
ABouttefeux committed May 2, 2021
1 parent fed59d6 commit 5cc21d9
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 35 deletions.
43 changes: 31 additions & 12 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Expand Up @@ -819,6 +819,19 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
_ => 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 (followed_by_brace, closing_brace) = self.followed_by_brace(span);

Expand Down Expand Up @@ -862,18 +875,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
let span = 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 span = find_span(&source, err);
if let Some(span) = self.def_span(def_id) {
err.span_label(span, &format!("`{}` defined here", path_str));
}
Expand Down Expand Up @@ -1047,6 +1049,23 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
) if ns == ValueNS => {
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 => {
if let Some(span) = self.def_span(def_id) {
err.span_label(span, &format!("`{}` defined here", path_str));
Expand Down
102 changes: 86 additions & 16 deletions src/test/ui/empty/empty-struct-unit-pat.stderr
@@ -1,84 +1,154 @@
error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2`
--> $DIR/empty-struct-unit-pat.rs:21:9
|
LL | struct Empty2;
| -------------- `Empty2` defined here
...
LL | Empty2() => ()
| ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
| ^^^^^^^^
|
::: $DIR/auxiliary/empty-struct.rs:3:1
|
LL | pub struct XEmpty6();
| --------------------- 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`
--> $DIR/empty-struct-unit-pat.rs:24:9
|
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();
| --------------------- 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`
--> $DIR/empty-struct-unit-pat.rs:28:9
|
LL | struct Empty2;
| -------------- `Empty2` defined here
...
LL | Empty2(..) => ()
| ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
| ^^^^^^^^^^
|
::: $DIR/auxiliary/empty-struct.rs:3:1
|
LL | pub struct XEmpty6();
| --------------------- 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`
--> $DIR/empty-struct-unit-pat.rs:32:9
|
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();
| --------------------- 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`
--> $DIR/empty-struct-unit-pat.rs:37:9
|
LL | Empty4
| ------ `E::Empty4` defined here
...
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`
--> $DIR/empty-struct-unit-pat.rs:41:9
|
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(),
| --------- 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`
--> $DIR/empty-struct-unit-pat.rs:46:9
|
LL | Empty4
| ------ `E::Empty4` defined here
...
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`
--> $DIR/empty-struct-unit-pat.rs:50:9
|
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(),
| --------- 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

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-32004.stderr
Expand Up @@ -21,8 +21,11 @@ LL | Foo::Baz => {}
error[E0532]: expected tuple struct or tuple variant, found unit struct `S`
--> $DIR/issue-32004.rs:16:9
|
LL | struct S;
| --------- `S` defined here
...
LL | S(()) => {}
| ^ not a tuple struct or tuple variant
| ^^^^^ help: use this syntax instead: `S`

error: aborting due to 2 previous errors

Expand Down
10 changes: 8 additions & 2 deletions src/test/ui/issues/issue-pr29383.stderr
@@ -1,14 +1,20 @@
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::A`
--> $DIR/issue-pr29383.rs:9:14
|
LL | A,
| - `E::A` defined here
...
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`
--> $DIR/issue-pr29383.rs:11:14
|
LL | B,
| - `E::B` defined here
...
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

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/match/match-pattern-field-mismatch-2.stderr
@@ -1,8 +1,11 @@
error[E0532]: expected tuple struct or tuple variant, found unit variant `Color::NoColor`
--> $DIR/match-pattern-field-mismatch-2.rs:12:11
|
LL | NoColor,
| ------- `Color::NoColor` defined here
...
LL | Color::NoColor(_) => { }
| ^^^^^^^^^^^^^^ not a tuple struct or tuple variant
| ^^^^^^^^^^^^^^^^^ help: use this syntax instead: `Color::NoColor`

error: aborting due to previous error

Expand Down
16 changes: 13 additions & 3 deletions src/test/ui/pattern/pattern-error-continue.stderr
Expand Up @@ -9,11 +9,21 @@ error[E0532]: expected tuple struct or tuple variant, found unit variant `A::D`
|
LL | B(isize, isize),
| --------------- similarly named tuple variant `B` defined here
LL | C(isize, isize, isize),
LL | D
| - `A::D` defined here
...
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
--> $DIR/pattern-error-continue.rs:17:9
Expand Down
26 changes: 26 additions & 0 deletions src/test/ui/suggestions/issue-84700.rs
@@ -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 changes: 21 additions & 0 deletions src/test/ui/suggestions/issue-84700.stderr
@@ -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`.

0 comments on commit 5cc21d9

Please sign in to comment.