Skip to content

Commit f5d3b15

Browse files
committed
Don’t report missing fields in struct exprs with syntax errors.
This prevents spurious errors when a field is intended to be present but a preceding syntax error caused it not to be parsed. For example, StructName { foo: 1 bar: 2 } will not successfully parse a field `bar`, and we will report the syntax error but not the missing field.
1 parent d6eefce commit f5d3b15

14 files changed

+129
-49
lines changed

‎compiler/rustc_hir_typeck/src/expr.rs‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2202,7 +2202,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22022202
};
22032203
self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr.hir_id, fru_tys);
22042204
}
2205-
rustc_hir::StructTailExpr::None | rustc_hir::StructTailExpr::NoneWithError(_) => {
2205+
rustc_hir::StructTailExpr::NoneWithError(ErrorGuaranteed { .. }) => {
2206+
// If parsing the struct recovered from a syntax error, do not report missing
2207+
// fields. This prevents spurious errors when a field is intended to be present
2208+
// but a preceding syntax error caused it not to be parsed. For example, if a
2209+
// struct type `StructName` has fields `foo` and `bar`, then
2210+
// StructName { foo(), bar: 2 }
2211+
// will not successfully parse a field `foo`, but we will not mention that,
2212+
// since the syntax error has already been reported.
2213+
}
2214+
rustc_hir::StructTailExpr::None => {
22062215
if adt_kind != AdtKind::Union
22072216
&& !remaining_fields.is_empty()
22082217
//~ non_exhaustive already reported, which will only happen for extern modules

‎tests/ui/parser/issues/issue-102806.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ fn pz(v: V3) {
1616

1717
let _ = V3 { z: 0.0, ... };
1818
//~^ ERROR expected identifier
19-
//~| ERROR missing fields `x` and `y` in initializer of `V3`
2019

2120
let V3 { z: val, ... } = v;
2221
//~^ ERROR expected field pattern

‎tests/ui/parser/issues/issue-102806.stderr‎

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ LL | let _ = V3 { z: 0.0, ... };
3131
| while parsing this struct
3232

3333
error: expected field pattern, found `...`
34-
--> $DIR/issue-102806.rs:21:22
34+
--> $DIR/issue-102806.rs:20:22
3535
|
3636
LL | let V3 { z: val, ... } = v;
3737
| ^^^
@@ -42,12 +42,5 @@ LL - let V3 { z: val, ... } = v;
4242
LL + let V3 { z: val, .. } = v;
4343
|
4444

45-
error[E0063]: missing fields `x` and `y` in initializer of `V3`
46-
--> $DIR/issue-102806.rs:17:13
47-
|
48-
LL | let _ = V3 { z: 0.0, ... };
49-
| ^^ missing `x` and `y`
50-
51-
error: aborting due to 5 previous errors
45+
error: aborting due to 4 previous errors
5246

53-
For more information about this error, try `rustc --explain E0063`.

‎tests/ui/parser/issues/issue-52496.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,5 @@ fn main() {
77
let bar = 1.5f32;
88
let _ = Foo { bar.into(), bat: -1, . };
99
//~^ ERROR expected one of
10-
//~| ERROR missing fields `bar` and `baz` in initializer of `Foo`
1110
//~| ERROR expected identifier, found `.`
1211
}

‎tests/ui/parser/issues/issue-52496.stderr‎

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,6 @@ error[E0063]: missing field `bat` in initializer of `Foo`
3737
LL | let _ = Foo { bar: .5, baz: 42 };
3838
| ^^^ missing `bat`
3939

40-
error[E0063]: missing fields `bar` and `baz` in initializer of `Foo`
41-
--> $DIR/issue-52496.rs:8:13
42-
|
43-
LL | let _ = Foo { bar.into(), bat: -1, . };
44-
| ^^^ missing `bar` and `baz`
45-
46-
error: aborting due to 5 previous errors
40+
error: aborting due to 4 previous errors
4741

4842
For more information about this error, try `rustc --explain E0063`.

‎tests/ui/parser/removed-syntax/removed-syntax-with-2.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ fn main() {
77
let a = S { foo: (), bar: () };
88
let b = S { foo: (), with a };
99
//~^ ERROR expected one of `,`, `:`, or `}`, found `a`
10-
//~| ERROR missing field `bar` in initializer of `S`
1110
}

‎tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr‎

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,5 @@ LL | let b = S { foo: (), with a };
77
| | while parsing this struct field
88
| while parsing this struct
99

10-
error[E0063]: missing field `bar` in initializer of `S`
11-
--> $DIR/removed-syntax-with-2.rs:8:13
12-
|
13-
LL | let b = S { foo: (), with a };
14-
| ^ missing `bar`
15-
16-
error: aborting due to 2 previous errors
10+
error: aborting due to 1 previous error
1711

18-
For more information about this error, try `rustc --explain E0063`.

‎tests/ui/parser/struct-field-numeric-shorthand.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@ fn main() {
55
//~^ ERROR expected identifier, found `0`
66
//~| ERROR expected identifier, found `1`
77
//~| ERROR expected identifier, found `2`
8-
//~| ERROR missing fields `0`, `1` and `2` in initializer of `Rgb`
98
}

‎tests/ui/parser/struct-field-numeric-shorthand.stderr‎

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,5 @@ LL | let _ = Rgb { 0, 1, 2 };
2222
| |
2323
| while parsing this struct
2424

25-
error[E0063]: missing fields `0`, `1` and `2` in initializer of `Rgb`
26-
--> $DIR/struct-field-numeric-shorthand.rs:4:13
27-
|
28-
LL | let _ = Rgb { 0, 1, 2 };
29-
| ^^^ missing `0`, `1` and `2`
30-
31-
error: aborting due to 4 previous errors
25+
error: aborting due to 3 previous errors
3226

33-
For more information about this error, try `rustc --explain E0063`.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Check that a syntax error inside a struct literal does not also report missing fields,
2+
// because the field might be present but hidden by the syntax error.
3+
//
4+
// The stderr for this test should contain ONLY one syntax error per struct literal,
5+
// and not any errors about missing fields.
6+
7+
struct Foo { a: isize, b: isize }
8+
9+
fn make_a() -> isize { 1234 }
10+
11+
fn expr_wrong_separator() {
12+
let f = Foo { a: make_a(); b: 2 }; //~ ERROR found `;`
13+
}
14+
15+
fn expr_missing_separator() {
16+
let f = Foo { a: make_a() b: 2 }; //~ ERROR found `b`
17+
}
18+
19+
fn expr_rest_trailing_comma() {
20+
let f = Foo { a: make_a(), ..todo!(), }; //~ ERROR cannot use a comma
21+
}
22+
23+
fn expr_missing_field_name() {
24+
let f = Foo { make_a(), b: 2, }; //~ ERROR found `(`
25+
}
26+
27+
fn pat_wrong_separator(Foo { a; b }: Foo) { //~ ERROR expected `,`
28+
let _ = (a, b);
29+
}
30+
31+
fn pat_missing_separator(Foo { a b }: Foo) { //~ ERROR expected `,`
32+
let _ = (a, b);
33+
}
34+
35+
fn pat_rest_trailing_comma(Foo { a, .., }: Foo) { //~ ERROR expected `}`, found `,`
36+
}
37+
38+
fn main() {}

0 commit comments

Comments
 (0)