Skip to content

Commit b0c7e64

Browse files
authored
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` ```
2 parents 37ce332 + 5cc21d9 commit b0c7e64

File tree

8 files changed

+193
-35
lines changed

8 files changed

+193
-35
lines changed

compiler/rustc_resolve/src/late/diagnostics.rs

+31-12
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,19 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
819819
_ => false,
820820
};
821821

822+
let find_span = |source: &PathSource<'_>, err: &mut DiagnosticBuilder<'_>| {
823+
match source {
824+
PathSource::Expr(Some(Expr { span, kind: ExprKind::Call(_, _), .. }))
825+
| PathSource::TupleStruct(span, _) => {
826+
// We want the main underline to cover the suggested code as well for
827+
// cleaner output.
828+
err.set_span(*span);
829+
*span
830+
}
831+
_ => span,
832+
}
833+
};
834+
822835
let mut bad_struct_syntax_suggestion = |def_id: DefId| {
823836
let (followed_by_brace, closing_brace) = self.followed_by_brace(span);
824837

@@ -862,18 +875,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
862875
}
863876
}
864877
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
865-
let span = match &source {
866-
PathSource::Expr(Some(Expr {
867-
span, kind: ExprKind::Call(_, _), ..
868-
}))
869-
| PathSource::TupleStruct(span, _) => {
870-
// We want the main underline to cover the suggested code as well for
871-
// cleaner output.
872-
err.set_span(*span);
873-
*span
874-
}
875-
_ => span,
876-
};
878+
let span = find_span(&source, err);
877879
if let Some(span) = self.def_span(def_id) {
878880
err.span_label(span, &format!("`{}` defined here", path_str));
879881
}
@@ -1047,6 +1049,23 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
10471049
) if ns == ValueNS => {
10481050
bad_struct_syntax_suggestion(def_id);
10491051
}
1052+
(Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => {
1053+
match source {
1054+
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
1055+
let span = find_span(&source, err);
1056+
if let Some(span) = self.def_span(def_id) {
1057+
err.span_label(span, &format!("`{}` defined here", path_str));
1058+
}
1059+
err.span_suggestion(
1060+
span,
1061+
&format!("use this syntax instead"),
1062+
format!("{path_str}"),
1063+
Applicability::MaybeIncorrect,
1064+
);
1065+
}
1066+
_ => return false,
1067+
}
1068+
}
10501069
(Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => {
10511070
if let Some(span) = self.def_span(def_id) {
10521071
err.span_label(span, &format!("`{}` defined here", path_str));

src/test/ui/empty/empty-struct-unit-pat.stderr

+86-16
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,154 @@
11
error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2`
22
--> $DIR/empty-struct-unit-pat.rs:21:9
33
|
4+
LL | struct Empty2;
5+
| -------------- `Empty2` defined here
6+
...
47
LL | Empty2() => ()
5-
| ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
8+
| ^^^^^^^^
69
|
710
::: $DIR/auxiliary/empty-struct.rs:3:1
811
|
912
LL | pub struct XEmpty6();
1013
| --------------------- similarly named tuple struct `XEmpty6` defined here
14+
|
15+
help: use this syntax instead
16+
|
17+
LL | Empty2 => ()
18+
| ^^^^^^
19+
help: a tuple struct with a similar name exists
20+
|
21+
LL | XEmpty6() => ()
22+
| ^^^^^^^
1123

1224
error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2`
1325
--> $DIR/empty-struct-unit-pat.rs:24:9
1426
|
1527
LL | XEmpty2() => ()
16-
| ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
28+
| ^^^^^^^^^
1729
|
18-
::: $DIR/auxiliary/empty-struct.rs:3:1
30+
::: $DIR/auxiliary/empty-struct.rs:2:1
1931
|
32+
LL | pub struct XEmpty2;
33+
| ------------------- `XEmpty2` defined here
2034
LL | pub struct XEmpty6();
2135
| --------------------- similarly named tuple struct `XEmpty6` defined here
36+
|
37+
help: use this syntax instead
38+
|
39+
LL | XEmpty2 => ()
40+
| ^^^^^^^
41+
help: a tuple struct with a similar name exists
42+
|
43+
LL | XEmpty6() => ()
44+
| ^^^^^^^
2245

2346
error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2`
2447
--> $DIR/empty-struct-unit-pat.rs:28:9
2548
|
49+
LL | struct Empty2;
50+
| -------------- `Empty2` defined here
51+
...
2652
LL | Empty2(..) => ()
27-
| ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
53+
| ^^^^^^^^^^
2854
|
2955
::: $DIR/auxiliary/empty-struct.rs:3:1
3056
|
3157
LL | pub struct XEmpty6();
3258
| --------------------- similarly named tuple struct `XEmpty6` defined here
59+
|
60+
help: use this syntax instead
61+
|
62+
LL | Empty2 => ()
63+
| ^^^^^^
64+
help: a tuple struct with a similar name exists
65+
|
66+
LL | XEmpty6(..) => ()
67+
| ^^^^^^^
3368

3469
error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2`
3570
--> $DIR/empty-struct-unit-pat.rs:32:9
3671
|
3772
LL | XEmpty2(..) => ()
38-
| ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
73+
| ^^^^^^^^^^^
3974
|
40-
::: $DIR/auxiliary/empty-struct.rs:3:1
75+
::: $DIR/auxiliary/empty-struct.rs:2:1
4176
|
77+
LL | pub struct XEmpty2;
78+
| ------------------- `XEmpty2` defined here
4279
LL | pub struct XEmpty6();
4380
| --------------------- similarly named tuple struct `XEmpty6` defined here
81+
|
82+
help: use this syntax instead
83+
|
84+
LL | XEmpty2 => ()
85+
| ^^^^^^^
86+
help: a tuple struct with a similar name exists
87+
|
88+
LL | XEmpty6(..) => ()
89+
| ^^^^^^^
4490

4591
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4`
4692
--> $DIR/empty-struct-unit-pat.rs:37:9
4793
|
94+
LL | Empty4
95+
| ------ `E::Empty4` defined here
96+
...
4897
LL | E::Empty4() => ()
49-
| ^^^^^^^^^ not a tuple struct or tuple variant
98+
| ^^^^^^^^^^^ help: use this syntax instead: `E::Empty4`
5099

51100
error[E0532]: expected tuple struct or tuple variant, found unit variant `XE::XEmpty4`
52101
--> $DIR/empty-struct-unit-pat.rs:41:9
53102
|
54103
LL | XE::XEmpty4() => (),
55-
| ^^^^-------
56-
| |
57-
| help: a tuple variant with a similar name exists: `XEmpty5`
104+
| ^^^^^^^^^^^^^
58105
|
59-
::: $DIR/auxiliary/empty-struct.rs:8:5
106+
::: $DIR/auxiliary/empty-struct.rs:7:5
60107
|
108+
LL | XEmpty4,
109+
| ------- `XE::XEmpty4` defined here
61110
LL | XEmpty5(),
62111
| --------- similarly named tuple variant `XEmpty5` defined here
112+
|
113+
help: use this syntax instead
114+
|
115+
LL | XE::XEmpty4 => (),
116+
| ^^^^^^^^^^^
117+
help: a tuple variant with a similar name exists
118+
|
119+
LL | XE::XEmpty5() => (),
120+
| ^^^^^^^
63121

64122
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4`
65123
--> $DIR/empty-struct-unit-pat.rs:46:9
66124
|
125+
LL | Empty4
126+
| ------ `E::Empty4` defined here
127+
...
67128
LL | E::Empty4(..) => ()
68-
| ^^^^^^^^^ not a tuple struct or tuple variant
129+
| ^^^^^^^^^^^^^ help: use this syntax instead: `E::Empty4`
69130

70131
error[E0532]: expected tuple struct or tuple variant, found unit variant `XE::XEmpty4`
71132
--> $DIR/empty-struct-unit-pat.rs:50:9
72133
|
73134
LL | XE::XEmpty4(..) => (),
74-
| ^^^^-------
75-
| |
76-
| help: a tuple variant with a similar name exists: `XEmpty5`
135+
| ^^^^^^^^^^^^^^^
77136
|
78-
::: $DIR/auxiliary/empty-struct.rs:8:5
137+
::: $DIR/auxiliary/empty-struct.rs:7:5
79138
|
139+
LL | XEmpty4,
140+
| ------- `XE::XEmpty4` defined here
80141
LL | XEmpty5(),
81142
| --------- similarly named tuple variant `XEmpty5` defined here
143+
|
144+
help: use this syntax instead
145+
|
146+
LL | XE::XEmpty4 => (),
147+
| ^^^^^^^^^^^
148+
help: a tuple variant with a similar name exists
149+
|
150+
LL | XE::XEmpty5(..) => (),
151+
| ^^^^^^^
82152

83153
error: aborting due to 8 previous errors
84154

src/test/ui/issues/issue-32004.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ LL | Foo::Baz => {}
2121
error[E0532]: expected tuple struct or tuple variant, found unit struct `S`
2222
--> $DIR/issue-32004.rs:16:9
2323
|
24+
LL | struct S;
25+
| --------- `S` defined here
26+
...
2427
LL | S(()) => {}
25-
| ^ not a tuple struct or tuple variant
28+
| ^^^^^ help: use this syntax instead: `S`
2629

2730
error: aborting due to 2 previous errors
2831

src/test/ui/issues/issue-pr29383.stderr

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::A`
22
--> $DIR/issue-pr29383.rs:9:14
33
|
4+
LL | A,
5+
| - `E::A` defined here
6+
...
47
LL | Some(E::A(..)) => {}
5-
| ^^^^ not a tuple struct or tuple variant
8+
| ^^^^^^^^ help: use this syntax instead: `E::A`
69

710
error[E0532]: expected tuple struct or tuple variant, found unit variant `E::B`
811
--> $DIR/issue-pr29383.rs:11:14
912
|
13+
LL | B,
14+
| - `E::B` defined here
15+
...
1016
LL | Some(E::B(..)) => {}
11-
| ^^^^ not a tuple struct or tuple variant
17+
| ^^^^^^^^ help: use this syntax instead: `E::B`
1218

1319
error: aborting due to 2 previous errors
1420

src/test/ui/match/match-pattern-field-mismatch-2.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
error[E0532]: expected tuple struct or tuple variant, found unit variant `Color::NoColor`
22
--> $DIR/match-pattern-field-mismatch-2.rs:12:11
33
|
4+
LL | NoColor,
5+
| ------- `Color::NoColor` defined here
6+
...
47
LL | Color::NoColor(_) => { }
5-
| ^^^^^^^^^^^^^^ not a tuple struct or tuple variant
8+
| ^^^^^^^^^^^^^^^^^ help: use this syntax instead: `Color::NoColor`
69

710
error: aborting due to previous error
811

src/test/ui/pattern/pattern-error-continue.stderr

+13-3
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,21 @@ error[E0532]: expected tuple struct or tuple variant, found unit variant `A::D`
99
|
1010
LL | B(isize, isize),
1111
| --------------- similarly named tuple variant `B` defined here
12+
LL | C(isize, isize, isize),
13+
LL | D
14+
| - `A::D` defined here
1215
...
1316
LL | A::D(_) => (),
14-
| ^^^-
15-
| |
16-
| help: a tuple variant with a similar name exists: `B`
17+
| ^^^^^^^
18+
|
19+
help: use this syntax instead
20+
|
21+
LL | A::D => (),
22+
| ^^^^
23+
help: a tuple variant with a similar name exists
24+
|
25+
LL | A::B(_) => (),
26+
| ^
1727

1828
error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
1929
--> $DIR/pattern-error-continue.rs:17:9
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// test for suggestion on fieldless enum variant
2+
3+
#[derive(PartialEq, Debug)]
4+
enum FarmAnimal {
5+
Worm,
6+
Cow,
7+
Bull,
8+
Chicken { num_eggs: usize },
9+
Dog (String),
10+
}
11+
12+
fn what_does_the_animal_say(animal: &FarmAnimal) {
13+
14+
let noise = match animal {
15+
FarmAnimal::Cow(_) => "moo".to_string(),
16+
//~^ ERROR expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow`
17+
FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(),
18+
//~^ ERROR expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken`
19+
FarmAnimal::Dog{..} => "woof!".to_string(),
20+
_ => todo!()
21+
};
22+
23+
println!("{:?} says: {:?}", animal, noise);
24+
}
25+
26+
fn main() {}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0532]: expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow`
2+
--> $DIR/issue-84700.rs:15:9
3+
|
4+
LL | Cow,
5+
| --- `FarmAnimal::Cow` defined here
6+
...
7+
LL | FarmAnimal::Cow(_) => "moo".to_string(),
8+
| ^^^^^^^^^^^^^^^^^^ help: use this syntax instead: `FarmAnimal::Cow`
9+
10+
error[E0532]: expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken`
11+
--> $DIR/issue-84700.rs:17:9
12+
|
13+
LL | Chicken { num_eggs: usize },
14+
| --------------------------- `FarmAnimal::Chicken` defined here
15+
...
16+
LL | FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(),
17+
| ^^^^^^^^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `FarmAnimal::Chicken { num_eggs }`
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0532`.

0 commit comments

Comments
 (0)