Skip to content

Commit 14eb94f

Browse files
committed
don't suggest erroneous trailing comma after ..
In #76612, suggestions were added for missing fields in patterns. However, the suggestions are being inserted just at the end of the last field in the pattern—before any trailing comma after the last field. This resulted in the "if you don't care about missing fields" suggestion to recommend code with a trailing comma after the field ellipsis (`..,`), which is actually not legal ("`..` must be at the end and cannot have a trailing comma")! Incidentally, the doc-comment on `error_unmentioned_fields` was using `you_cant_use_this_field` as an example field name (presumably copy-paste inherited from the description of Issue #76077), but the present author found this confusing, because unmentioned fields aren't necessarily unusable. The suggested code in the diff this commit introduces to `destructuring-assignment/struct_destructure_fail.stderr` doesn't work, but it didn't work beforehand, either (because of the "found reserved identifier `_`" thing), so you can't really call it a regression; it could be fixed in a separate PR. Resolves #78511.
1 parent 63a83c5 commit 14eb94f

File tree

4 files changed

+66
-15
lines changed

4 files changed

+66
-15
lines changed

Diff for: compiler/rustc_typeck/src/check/pat.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -1486,11 +1486,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14861486
/// Returns a diagnostic reporting a struct pattern which does not mention some fields.
14871487
///
14881488
/// ```text
1489-
/// error[E0027]: pattern does not mention field `you_cant_use_this_field`
1489+
/// error[E0027]: pattern does not mention field `bar`
14901490
/// --> src/main.rs:15:9
14911491
/// |
14921492
/// LL | let foo::Foo {} = foo::Foo::new();
1493-
/// | ^^^^^^^^^^^ missing field `you_cant_use_this_field`
1493+
/// | ^^^^^^^^^^^ missing field `bar`
14941494
/// ```
14951495
fn error_unmentioned_fields(
14961496
&self,
@@ -1524,14 +1524,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15241524
}
15251525
_ => return err,
15261526
},
1527-
[.., field] => (
1528-
match pat.kind {
1529-
PatKind::Struct(_, [_, ..], _) => ", ",
1530-
_ => "",
1531-
},
1532-
"",
1533-
field.span.shrink_to_hi(),
1534-
),
1527+
[.., field] => {
1528+
// if last field has a trailing comma, use the comma
1529+
// as the span to avoid trailing comma in ultimate
1530+
// suggestion (Issue #78511)
1531+
let tail = field.span.shrink_to_hi().until(pat.span.shrink_to_hi());
1532+
let tail_through_comma = self.tcx.sess.source_map().span_through_char(tail, ',');
1533+
let sp = if tail_through_comma == tail {
1534+
field.span.shrink_to_hi()
1535+
} else {
1536+
tail_through_comma
1537+
};
1538+
(
1539+
match pat.kind {
1540+
PatKind::Struct(_, [_, ..], _) => ", ",
1541+
_ => "",
1542+
},
1543+
"",
1544+
sp,
1545+
)
1546+
}
15351547
};
15361548
err.span_suggestion(
15371549
sp,

Diff for: src/test/ui/destructuring-assignment/struct_destructure_fail.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ LL | Struct { a, _ } = Struct { a: 1, b: 2 };
3232
|
3333
help: include the missing field in the pattern
3434
|
35-
LL | Struct { a, b, _ } = Struct { a: 1, b: 2 };
35+
LL | Struct { a, b _ } = Struct { a: 1, b: 2 };
3636
| ^^^
3737
help: if you don't care about this missing field, you can explicitly ignore it
3838
|
39-
LL | Struct { a, .., _ } = Struct { a: 1, b: 2 };
39+
LL | Struct { a, .. _ } = Struct { a: 1, b: 2 };
4040
| ^^^^
4141

4242
error: aborting due to 5 previous errors

Diff for: src/test/ui/error-codes/E0027.rs

+9
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,21 @@ struct Dog {
33
age: u32,
44
}
55

6+
67
fn main() {
78
let d = Dog { name: "Rusty".to_string(), age: 8 };
89

910
match d {
1011
Dog { age: x } => {} //~ ERROR pattern does not mention field `name`
1112
}
13+
match d {
14+
// trailing comma
15+
Dog { name: x, } => {} //~ ERROR pattern does not mention field `age`
16+
}
17+
match d {
18+
// trailing comma with weird whitespace
19+
Dog { name: x , } => {} //~ ERROR pattern does not mention field `age`
20+
}
1221
match d {
1322
Dog {} => {} //~ ERROR pattern does not mention fields `name`, `age`
1423
}

Diff for: src/test/ui/error-codes/E0027.stderr

+33-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0027]: pattern does not mention field `name`
2-
--> $DIR/E0027.rs:10:9
2+
--> $DIR/E0027.rs:11:9
33
|
44
LL | Dog { age: x } => {}
55
| ^^^^^^^^^^^^^^ missing field `name`
@@ -13,8 +13,38 @@ help: if you don't care about this missing field, you can explicitly ignore it
1313
LL | Dog { age: x, .. } => {}
1414
| ^^^^
1515

16+
error[E0027]: pattern does not mention field `age`
17+
--> $DIR/E0027.rs:15:9
18+
|
19+
LL | Dog { name: x, } => {}
20+
| ^^^^^^^^^^^^^^^^ missing field `age`
21+
|
22+
help: include the missing field in the pattern
23+
|
24+
LL | Dog { name: x, age } => {}
25+
| ^^^^^
26+
help: if you don't care about this missing field, you can explicitly ignore it
27+
|
28+
LL | Dog { name: x, .. } => {}
29+
| ^^^^
30+
31+
error[E0027]: pattern does not mention field `age`
32+
--> $DIR/E0027.rs:19:9
33+
|
34+
LL | Dog { name: x , } => {}
35+
| ^^^^^^^^^^^^^^^^^^ missing field `age`
36+
|
37+
help: include the missing field in the pattern
38+
|
39+
LL | Dog { name: x, age } => {}
40+
| ^^^^^
41+
help: if you don't care about this missing field, you can explicitly ignore it
42+
|
43+
LL | Dog { name: x, .. } => {}
44+
| ^^^^
45+
1646
error[E0027]: pattern does not mention fields `name`, `age`
17-
--> $DIR/E0027.rs:13:9
47+
--> $DIR/E0027.rs:22:9
1848
|
1949
LL | Dog {} => {}
2050
| ^^^^^^ missing fields `name`, `age`
@@ -28,6 +58,6 @@ help: if you don't care about these missing fields, you can explicitly ignore th
2858
LL | Dog { .. } => {}
2959
| ^^^^^^
3060

31-
error: aborting due to 2 previous errors
61+
error: aborting due to 4 previous errors
3262

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

0 commit comments

Comments
 (0)