diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 5f55a565f560..bfbe93176a25 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -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 diff --git a/tests/ui/parser/issues/issue-102806.rs b/tests/ui/parser/issues/issue-102806.rs index 5ee8c5c1e3de..804e727272d4 100644 --- a/tests/ui/parser/issues/issue-102806.rs +++ b/tests/ui/parser/issues/issue-102806.rs @@ -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 diff --git a/tests/ui/parser/issues/issue-102806.stderr b/tests/ui/parser/issues/issue-102806.stderr index cd447c6dec0d..d4c899ed5811 100644 --- a/tests/ui/parser/issues/issue-102806.stderr +++ b/tests/ui/parser/issues/issue-102806.stderr @@ -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`. diff --git a/tests/ui/parser/issues/issue-52496.rs b/tests/ui/parser/issues/issue-52496.rs index 05461f8b8c41..3e88a92aae9b 100644 --- a/tests/ui/parser/issues/issue-52496.rs +++ b/tests/ui/parser/issues/issue-52496.rs @@ -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 `.` } diff --git a/tests/ui/parser/issues/issue-52496.stderr b/tests/ui/parser/issues/issue-52496.stderr index a97effb4e0cd..da22f5ce1356 100644 --- a/tests/ui/parser/issues/issue-52496.stderr +++ b/tests/ui/parser/issues/issue-52496.stderr @@ -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`. diff --git a/tests/ui/parser/removed-syntax/removed-syntax-with-2.rs b/tests/ui/parser/removed-syntax/removed-syntax-with-2.rs index 451057c66a12..119afdcc75e3 100644 --- a/tests/ui/parser/removed-syntax/removed-syntax-with-2.rs +++ b/tests/ui/parser/removed-syntax/removed-syntax-with-2.rs @@ -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` } diff --git a/tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr b/tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr index e75c5bcd6431..7768aeccfad9 100644 --- a/tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr +++ b/tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr @@ -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`. diff --git a/tests/ui/parser/struct-field-numeric-shorthand.rs b/tests/ui/parser/struct-field-numeric-shorthand.rs index 645abd9c7192..aa342eb02a91 100644 --- a/tests/ui/parser/struct-field-numeric-shorthand.rs +++ b/tests/ui/parser/struct-field-numeric-shorthand.rs @@ -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` } diff --git a/tests/ui/parser/struct-field-numeric-shorthand.stderr b/tests/ui/parser/struct-field-numeric-shorthand.stderr index bfb8a931b640..9878cfbbdceb 100644 --- a/tests/ui/parser/struct-field-numeric-shorthand.stderr +++ b/tests/ui/parser/struct-field-numeric-shorthand.stderr @@ -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`. diff --git a/tests/ui/structs/syntax-error-not-missing-field.rs b/tests/ui/structs/syntax-error-not-missing-field.rs new file mode 100644 index 000000000000..f1080d3908cf --- /dev/null +++ b/tests/ui/structs/syntax-error-not-missing-field.rs @@ -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() {} diff --git a/tests/ui/structs/syntax-error-not-missing-field.stderr b/tests/ui/structs/syntax-error-not-missing-field.stderr new file mode 100644 index 000000000000..d781a41300f3 --- /dev/null +++ b/tests/ui/structs/syntax-error-not-missing-field.stderr @@ -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 + diff --git a/tests/ui/suggestions/struct-initializer-comma.fixed b/tests/ui/suggestions/struct-initializer-comma.fixed index 556bfbca58df..9bd9434a3b59 100644 --- a/tests/ui/suggestions/struct-initializer-comma.fixed +++ b/tests/ui/suggestions/struct-initializer-comma.fixed @@ -7,7 +7,6 @@ pub struct Foo { fn main() { let _ = Foo { - //~^ ERROR missing field first: true, second: 25 //~^ ERROR expected one of diff --git a/tests/ui/suggestions/struct-initializer-comma.rs b/tests/ui/suggestions/struct-initializer-comma.rs index 7b93bf187b87..4b225df08df0 100644 --- a/tests/ui/suggestions/struct-initializer-comma.rs +++ b/tests/ui/suggestions/struct-initializer-comma.rs @@ -7,7 +7,6 @@ pub struct Foo { fn main() { let _ = Foo { - //~^ ERROR missing field first: true second: 25 //~^ ERROR expected one of diff --git a/tests/ui/suggestions/struct-initializer-comma.stderr b/tests/ui/suggestions/struct-initializer-comma.stderr index 5eff43f32cda..5fdc95a30cc4 100644 --- a/tests/ui/suggestions/struct-initializer-comma.stderr +++ b/tests/ui/suggestions/struct-initializer-comma.stderr @@ -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`.