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.
This commit is contained in:
Kevin Reid
2026-02-28 18:11:11 -08:00
parent d6eefce00d
commit f5d3b158b9
14 changed files with 129 additions and 49 deletions
+10 -1
View File
@@ -2202,7 +2202,16 @@ fn check_expr_struct_fields(
};
self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr.hir_id, fru_tys);
}
rustc_hir::StructTailExpr::None | rustc_hir::StructTailExpr::NoneWithError(_) => {
rustc_hir::StructTailExpr::NoneWithError(ErrorGuaranteed { .. }) => {
// If parsing the struct recovered from a syntax error, do not report missing
// fields. 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, if a
// struct type `StructName` has fields `foo` and `bar`, then
// StructName { foo(), bar: 2 }
// will not successfully parse a field `foo`, but we will not mention that,
// since the syntax error has already been reported.
}
rustc_hir::StructTailExpr::None => {
if adt_kind != AdtKind::Union
&& !remaining_fields.is_empty()
//~ non_exhaustive already reported, which will only happen for extern modules
-1
View File
@@ -16,7 +16,6 @@ fn pz(v: V3) {
let _ = V3 { z: 0.0, ... };
//~^ ERROR expected identifier
//~| ERROR missing fields `x` and `y` in initializer of `V3`
let V3 { z: val, ... } = v;
//~^ ERROR expected field pattern
+2 -9
View File
@@ -31,7 +31,7 @@ LL | let _ = V3 { z: 0.0, ... };
| while parsing this struct
error: expected field pattern, found `...`
--> $DIR/issue-102806.rs:21:22
--> $DIR/issue-102806.rs:20:22
|
LL | let V3 { z: val, ... } = v;
| ^^^
@@ -42,12 +42,5 @@ LL - let V3 { z: val, ... } = v;
LL + let V3 { z: val, .. } = v;
|
error[E0063]: missing fields `x` and `y` in initializer of `V3`
--> $DIR/issue-102806.rs:17:13
|
LL | let _ = V3 { z: 0.0, ... };
| ^^ missing `x` and `y`
error: aborting due to 4 previous errors
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0063`.
-1
View File
@@ -7,6 +7,5 @@ fn main() {
let bar = 1.5f32;
let _ = Foo { bar.into(), bat: -1, . };
//~^ ERROR expected one of
//~| ERROR missing fields `bar` and `baz` in initializer of `Foo`
//~| ERROR expected identifier, found `.`
}
+1 -7
View File
@@ -37,12 +37,6 @@ error[E0063]: missing field `bat` in initializer of `Foo`
LL | let _ = Foo { bar: .5, baz: 42 };
| ^^^ missing `bat`
error[E0063]: missing fields `bar` and `baz` in initializer of `Foo`
--> $DIR/issue-52496.rs:8:13
|
LL | let _ = Foo { bar.into(), bat: -1, . };
| ^^^ missing `bar` and `baz`
error: aborting due to 5 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0063`.
@@ -7,5 +7,4 @@ struct S {
let a = S { foo: (), bar: () };
let b = S { foo: (), with a };
//~^ ERROR expected one of `,`, `:`, or `}`, found `a`
//~| ERROR missing field `bar` in initializer of `S`
}
@@ -7,12 +7,5 @@ LL | let b = S { foo: (), with a };
| | while parsing this struct field
| while parsing this struct
error[E0063]: missing field `bar` in initializer of `S`
--> $DIR/removed-syntax-with-2.rs:8:13
|
LL | let b = S { foo: (), with a };
| ^ missing `bar`
error: aborting due to 1 previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0063`.
@@ -5,5 +5,4 @@ fn main() {
//~^ ERROR expected identifier, found `0`
//~| ERROR expected identifier, found `1`
//~| ERROR expected identifier, found `2`
//~| ERROR missing fields `0`, `1` and `2` in initializer of `Rgb`
}
@@ -22,12 +22,5 @@ LL | let _ = Rgb { 0, 1, 2 };
| |
| while parsing this struct
error[E0063]: missing fields `0`, `1` and `2` in initializer of `Rgb`
--> $DIR/struct-field-numeric-shorthand.rs:4:13
|
LL | let _ = Rgb { 0, 1, 2 };
| ^^^ missing `0`, `1` and `2`
error: aborting due to 3 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0063`.
@@ -0,0 +1,38 @@
// Check that a syntax error inside a struct literal does not also report missing fields,
// because the field might be present but hidden by the syntax error.
//
// The stderr for this test should contain ONLY one syntax error per struct literal,
// and not any errors about missing fields.
struct Foo { a: isize, b: isize }
fn make_a() -> isize { 1234 }
fn expr_wrong_separator() {
let f = Foo { a: make_a(); b: 2 }; //~ ERROR found `;`
}
fn expr_missing_separator() {
let f = Foo { a: make_a() b: 2 }; //~ ERROR found `b`
}
fn expr_rest_trailing_comma() {
let f = Foo { a: make_a(), ..todo!(), }; //~ ERROR cannot use a comma
}
fn expr_missing_field_name() {
let f = Foo { make_a(), b: 2, }; //~ ERROR found `(`
}
fn pat_wrong_separator(Foo { a; b }: Foo) { //~ ERROR expected `,`
let _ = (a, b);
}
fn pat_missing_separator(Foo { a b }: Foo) { //~ ERROR expected `,`
let _ = (a, b);
}
fn pat_rest_trailing_comma(Foo { a, .., }: Foo) { //~ ERROR expected `}`, found `,`
}
fn main() {}
@@ -0,0 +1,74 @@
error: expected one of `,`, `.`, `?`, `}`, or an operator, found `;`
--> $DIR/syntax-error-not-missing-field.rs:12:30
|
LL | let f = Foo { a: make_a(); b: 2 };
| --- ^
| | |
| | expected one of `,`, `.`, `?`, `}`, or an operator
| | help: try adding a comma: `,`
| while parsing this struct
error: expected one of `,`, `.`, `?`, `}`, or an operator, found `b`
--> $DIR/syntax-error-not-missing-field.rs:16:31
|
LL | let f = Foo { a: make_a() b: 2 };
| --- -^ expected one of `,`, `.`, `?`, `}`, or an operator
| | |
| | help: try adding a comma: `,`
| while parsing this struct
error: cannot use a comma after the base struct
--> $DIR/syntax-error-not-missing-field.rs:20:32
|
LL | let f = Foo { a: make_a(), ..todo!(), };
| ^^^^^^^^^
|
= note: the base struct must always be the last field
help: remove this comma
|
LL - let f = Foo { a: make_a(), ..todo!(), };
LL + let f = Foo { a: make_a(), ..todo!() };
|
error: expected one of `,`, `:`, or `}`, found `(`
--> $DIR/syntax-error-not-missing-field.rs:24:25
|
LL | let f = Foo { make_a(), b: 2, };
| --- ------^ expected one of `,`, `:`, or `}`
| | |
| | while parsing this struct field
| while parsing this struct
|
help: try naming a field
|
LL | let f = Foo { make_a: make_a(), b: 2, };
| +++++++
error: expected `,`
--> $DIR/syntax-error-not-missing-field.rs:27:31
|
LL | fn pat_wrong_separator(Foo { a; b }: Foo) {
| --- ^
| |
| while parsing the fields for this pattern
error: expected `,`
--> $DIR/syntax-error-not-missing-field.rs:31:34
|
LL | fn pat_missing_separator(Foo { a b }: Foo) {
| --- ^
| |
| while parsing the fields for this pattern
error: expected `}`, found `,`
--> $DIR/syntax-error-not-missing-field.rs:35:39
|
LL | fn pat_rest_trailing_comma(Foo { a, .., }: Foo) {
| --^
| | |
| | expected `}`
| | help: remove this comma
| `..` must be at the end and cannot have a trailing comma
error: aborting due to 7 previous errors
@@ -7,7 +7,6 @@ pub struct Foo {
fn main() {
let _ = Foo {
//~^ ERROR missing field
first: true,
second: 25
//~^ ERROR expected one of
@@ -7,7 +7,6 @@ pub struct Foo {
fn main() {
let _ = Foo {
//~^ ERROR missing field
first: true
second: 25
//~^ ERROR expected one of
@@ -1,9 +1,8 @@
error: expected one of `,`, `.`, `?`, `}`, or an operator, found `second`
--> $DIR/struct-initializer-comma.rs:12:9
--> $DIR/struct-initializer-comma.rs:11:9
|
LL | let _ = Foo {
| --- while parsing this struct
LL |
LL | first: true
| -
| |
@@ -12,12 +11,5 @@ LL | first: true
LL | second: 25
| ^^^^^^ unexpected token
error[E0063]: missing field `second` in initializer of `Foo`
--> $DIR/struct-initializer-comma.rs:9:13
|
LL | let _ = Foo {
| ^^^ missing `second`
error: aborting due to 1 previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0063`.