Skip to content

Commit 7c3edec

Browse files
committed
Suggest the struct variant pattern syntax on usage of unit variant pattern for a struct variant
1 parent a971212 commit 7c3edec

File tree

7 files changed

+105
-1
lines changed

7 files changed

+105
-1
lines changed

compiler/rustc_hir_typeck/src/lib.rs

+38-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub use coercion::can_coerce;
4545
use fn_ctxt::FnCtxt;
4646
use rustc_data_structures::unord::UnordSet;
4747
use rustc_errors::codes::*;
48-
use rustc_errors::{struct_span_code_err, Applicability, ErrorGuaranteed};
48+
use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
4949
use rustc_hir as hir;
5050
use rustc_hir::def::{DefKind, Res};
5151
use rustc_hir::intravisit::Visitor;
@@ -421,6 +421,43 @@ fn report_unexpected_variant_res(
421421
err.multipart_suggestion_verbose(descr, suggestion, Applicability::MaybeIncorrect);
422422
err
423423
}
424+
Res::Def(DefKind::Variant, _) if expr.is_none() => {
425+
let fields = tcx
426+
.expect_variant_res(res)
427+
.fields
428+
.raw
429+
.iter()
430+
.map(|field| field.name.to_ident_string())
431+
.collect::<Vec<_>>();
432+
433+
err.span_label(span, format!("not a {expected}"));
434+
435+
let span = qpath.span().shrink_to_hi().to(span.shrink_to_hi());
436+
err.span_suggestion_verbose(
437+
span,
438+
"use the struct variant pattern syntax",
439+
if fields.is_empty() {
440+
" {}".to_string()
441+
} else {
442+
format!(" {{ {} }}", fields.join(", "))
443+
},
444+
Applicability::MachineApplicable,
445+
);
446+
447+
if !fields.is_empty() {
448+
let len = fields.len();
449+
450+
let msg = format!(
451+
"if you don't care about {these} field{s}, you can explicitly ignore {them}",
452+
these = pluralize!("this", len),
453+
s = pluralize!(len),
454+
them = if len == 1 { "it" } else { "them" },
455+
);
456+
err.span_suggestion_verbose(span, msg, " { .. }", Applicability::MachineApplicable);
457+
}
458+
459+
err
460+
}
424461
_ => err.with_span_label(span, format!("not a {expected}")),
425462
}
426463
.emit()

tests/ui/empty/empty-struct-braces-pat-1.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,22 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia
33
|
44
LL | E::Empty3 => ()
55
| ^^^^^^^^^ not a unit struct, unit variant or constant
6+
|
7+
help: use the struct variant pattern syntax
8+
|
9+
LL | E::Empty3 {} => ()
10+
| ++
611

712
error[E0533]: expected unit struct, unit variant or constant, found struct variant `XE::XEmpty3`
813
--> $DIR/empty-struct-braces-pat-1.rs:31:9
914
|
1015
LL | XE::XEmpty3 => ()
1116
| ^^^^^^^^^^^ not a unit struct, unit variant or constant
17+
|
18+
help: use the struct variant pattern syntax
19+
|
20+
LL | XE::XEmpty3 {} => ()
21+
| ++
1222

1323
error: aborting due to 2 previous errors
1424

tests/ui/empty/empty-struct-braces-pat-3.stderr

+20
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,44 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `E::E
33
|
44
LL | E::Empty3() => ()
55
| ^^^^^^^^^^^ not a tuple struct or tuple variant
6+
|
7+
help: use the struct variant pattern syntax
8+
|
9+
LL | E::Empty3 {} => ()
10+
| ~~
611

712
error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3`
813
--> $DIR/empty-struct-braces-pat-3.rs:21:9
914
|
1015
LL | XE::XEmpty3() => ()
1116
| ^^^^^^^^^^^^^ not a tuple struct or tuple variant
17+
|
18+
help: use the struct variant pattern syntax
19+
|
20+
LL | XE::XEmpty3 {} => ()
21+
| ~~
1222

1323
error[E0164]: expected tuple struct or tuple variant, found struct variant `E::Empty3`
1424
--> $DIR/empty-struct-braces-pat-3.rs:25:9
1525
|
1626
LL | E::Empty3(..) => ()
1727
| ^^^^^^^^^^^^^ not a tuple struct or tuple variant
28+
|
29+
help: use the struct variant pattern syntax
30+
|
31+
LL | E::Empty3 {} => ()
32+
| ~~
1833

1934
error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3`
2035
--> $DIR/empty-struct-braces-pat-3.rs:29:9
2136
|
2237
LL | XE::XEmpty3(..) => ()
2338
| ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
39+
|
40+
help: use the struct variant pattern syntax
41+
|
42+
LL | XE::XEmpty3 {} => ()
43+
| ~~
2444

2545
error: aborting due to 4 previous errors
2646

tests/ui/issues/issue-63983.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia
1212
|
1313
LL | MyEnum::Struct => "",
1414
| ^^^^^^^^^^^^^^ not a unit struct, unit variant or constant
15+
|
16+
help: use the struct variant pattern syntax
17+
|
18+
LL | MyEnum::Struct { s } => "",
19+
| +++++
20+
help: if you don't care about this field, you can explicitly ignore it
21+
|
22+
LL | MyEnum::Struct { .. } => "",
23+
| ++++++
1524

1625
error: aborting due to 2 previous errors
1726

tests/ui/parser/recover/recover-from-bad-variant.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum
1919
|
2020
LL | Enum::Foo(a, b) => {}
2121
| ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
22+
|
23+
help: use the struct variant pattern syntax
24+
|
25+
LL | Enum::Foo { a, b } => {}
26+
| ~~~~~~~~
27+
help: if you don't care about these fields, you can explicitly ignore them
28+
|
29+
LL | Enum::Foo { .. } => {}
30+
| ~~~~~~
2231

2332
error[E0769]: tuple variant `Enum::Bar` written as struct variant
2433
--> $DIR/recover-from-bad-variant.rs:12:9

tests/ui/suggestions/issue-84700.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `Farm
1212
|
1313
LL | FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(),
1414
| ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
15+
|
16+
help: use the struct variant pattern syntax
17+
|
18+
LL | FarmAnimal::Chicken { num_eggs } => "cluck, cluck!".to_string(),
19+
| ~~~~~~~~~~~~
20+
help: if you don't care about this field, you can explicitly ignore it
21+
|
22+
LL | FarmAnimal::Chicken { .. } => "cluck, cluck!".to_string(),
23+
| ~~~~~~
1524

1625
error: aborting due to 2 previous errors
1726

tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,22 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia
1414
|
1515
LL | let Alias::Braced = panic!();
1616
| ^^^^^^^^^^^^^ not a unit struct, unit variant or constant
17+
|
18+
help: use the struct variant pattern syntax
19+
|
20+
LL | let Alias::Braced {} = panic!();
21+
| ++
1722

1823
error[E0164]: expected tuple struct or tuple variant, found struct variant `Alias::Braced`
1924
--> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9
2025
|
2126
LL | let Alias::Braced(..) = panic!();
2227
| ^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
28+
|
29+
help: use the struct variant pattern syntax
30+
|
31+
LL | let Alias::Braced {} = panic!();
32+
| ~~
2333

2434
error[E0618]: expected function, found enum variant `Alias::Unit`
2535
--> $DIR/incorrect-variant-form-through-alias-caught.rs:15:5

0 commit comments

Comments
 (0)