Skip to content

Commit 255ceeb

Browse files
committed
Auto merge of #76612 - estebank:pat-missing-fields-suggestion, r=davidtwco
Provide suggestion for missing fields in patterns
2 parents 9b41541 + 21f8326 commit 255ceeb

File tree

7 files changed

+96
-38
lines changed

7 files changed

+96
-38
lines changed

compiler/rustc_typeck/src/check/pat.rs

+49-9
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11501150
if no_accessible_unmentioned_fields {
11511151
unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
11521152
} else {
1153-
unmentioned_err = Some(self.error_unmentioned_fields(pat, &unmentioned_fields));
1153+
unmentioned_err =
1154+
Some(self.error_unmentioned_fields(pat, &unmentioned_fields, &fields));
11541155
}
11551156
}
11561157
match (inexistent_fields_err, unmentioned_err) {
@@ -1405,6 +1406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14051406
&self,
14061407
pat: &Pat<'_>,
14071408
unmentioned_fields: &[(&ty::FieldDef, Ident)],
1409+
fields: &'tcx [hir::FieldPat<'tcx>],
14081410
) -> DiagnosticBuilder<'tcx> {
14091411
let field_names = if unmentioned_fields.len() == 1 {
14101412
format!("field `{}`", unmentioned_fields[0].1)
@@ -1424,14 +1426,52 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14241426
field_names
14251427
);
14261428
err.span_label(pat.span, format!("missing {}", field_names));
1427-
if self.tcx.sess.teach(&err.get_code().unwrap()) {
1428-
err.note(
1429-
"This error indicates that a pattern for a struct fails to specify a \
1430-
sub-pattern for every one of the struct's fields. Ensure that each field \
1431-
from the struct's definition is mentioned in the pattern, or use `..` to \
1432-
ignore unwanted fields.",
1433-
);
1434-
}
1429+
let len = unmentioned_fields.len();
1430+
let (prefix, postfix, sp) = match fields {
1431+
[] => match &pat.kind {
1432+
PatKind::Struct(path, [], false) => {
1433+
(" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi()))
1434+
}
1435+
_ => return err,
1436+
},
1437+
[.., field] => (
1438+
match pat.kind {
1439+
PatKind::Struct(_, [_, ..], _) => ", ",
1440+
_ => "",
1441+
},
1442+
"",
1443+
field.span.shrink_to_hi(),
1444+
),
1445+
};
1446+
err.span_suggestion(
1447+
sp,
1448+
&format!(
1449+
"include the missing field{} in the pattern",
1450+
if len == 1 { "" } else { "s" },
1451+
),
1452+
format!(
1453+
"{}{}{}",
1454+
prefix,
1455+
unmentioned_fields
1456+
.iter()
1457+
.map(|(_, name)| name.to_string())
1458+
.collect::<Vec<_>>()
1459+
.join(", "),
1460+
postfix,
1461+
),
1462+
Applicability::MachineApplicable,
1463+
);
1464+
err.span_suggestion(
1465+
sp,
1466+
&format!(
1467+
"if you don't care about {} missing field{}, you can explicitely ignore {}",
1468+
if len == 1 { "this" } else { "these" },
1469+
if len == 1 { "" } else { "s" },
1470+
if len == 1 { "it" } else { "them" },
1471+
),
1472+
format!("{}..{}", prefix, postfix),
1473+
Applicability::MachineApplicable,
1474+
);
14351475
err
14361476
}
14371477

src/test/ui/error-codes/E0027-teach.rs

-15
This file was deleted.

src/test/ui/error-codes/E0027-teach.stderr

-11
This file was deleted.

src/test/ui/error-codes/E0027.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ fn main() {
77
let d = Dog { name: "Rusty".to_string(), age: 8 };
88

99
match d {
10-
Dog { age: x } => {}
11-
//~^ ERROR pattern does not mention field `name`
10+
Dog { age: x } => {} //~ ERROR pattern does not mention field `name`
11+
}
12+
match d {
13+
Dog {} => {} //~ ERROR pattern does not mention fields `name`, `age`
1214
}
1315
}

src/test/ui/error-codes/E0027.stderr

+25-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,31 @@ error[E0027]: pattern does not mention field `name`
33
|
44
LL | Dog { age: x } => {}
55
| ^^^^^^^^^^^^^^ missing field `name`
6+
|
7+
help: include the missing field in the pattern
8+
|
9+
LL | Dog { age: x, name } => {}
10+
| ^^^^^^
11+
help: if you don't care about this missing field, you can explicitely ignore it
12+
|
13+
LL | Dog { age: x, .. } => {}
14+
| ^^^^
15+
16+
error[E0027]: pattern does not mention fields `name`, `age`
17+
--> $DIR/E0027.rs:13:9
18+
|
19+
LL | Dog {} => {}
20+
| ^^^^^^ missing fields `name`, `age`
21+
|
22+
help: include the missing fields in the pattern
23+
|
24+
LL | Dog { name, age } => {}
25+
| ^^^^^^^^^^^^^
26+
help: if you don't care about these missing fields, you can explicitely ignore them
27+
|
28+
LL | Dog { .. } => {}
29+
| ^^^^^^
630

7-
error: aborting due to previous error
31+
error: aborting due to 2 previous errors
832

933
For more information about this error, try `rustc --explain E0027`.

src/test/ui/structs/struct-field-cfg.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ error[E0027]: pattern does not mention field `present`
1717
|
1818
LL | let Foo { #[cfg(any())] present: () } = foo;
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `present`
20+
|
21+
help: include the missing field in the pattern
22+
|
23+
LL | let Foo { present } = foo;
24+
| ^^^^^^^^^^^
25+
help: if you don't care about this missing field, you can explicitely ignore it
26+
|
27+
LL | let Foo { .. } = foo;
28+
| ^^^^^^
2029

2130
error[E0026]: struct `Foo` does not have a field named `absent`
2231
--> $DIR/struct-field-cfg.rs:16:42

src/test/ui/structs/struct-pat-derived-error.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ error[E0027]: pattern does not mention fields `b`, `c`
1515
|
1616
LL | let A { x, y } = self.d;
1717
| ^^^^^^^^^^ missing fields `b`, `c`
18+
|
19+
help: include the missing fields in the pattern
20+
|
21+
LL | let A { x, y, b, c } = self.d;
22+
| ^^^^^^
23+
help: if you don't care about these missing fields, you can explicitely ignore them
24+
|
25+
LL | let A { x, y, .. } = self.d;
26+
| ^^^^
1827

1928
error: aborting due to 3 previous errors
2029

0 commit comments

Comments
 (0)