diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 553ffda814fe9..b2b578f1ed44a 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1399,6 +1399,37 @@ impl<'a> Parser<'a> { Ok(a_var) } + fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> { + if let Err(mut err) = self.expect(&token::Colon) { + let sm = self.sess.source_map(); + let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start()); + let semi_typo = self.token.kind == token::Semi + && self.look_ahead(1, |t| { + t.is_path_start() + // We check that we are in a situation like `foo; bar` to avoid bad suggestions + // when there's no type and `;` was used instead of a comma. + && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) { + (Ok(l), Ok(r)) => l.line == r.line, + _ => true, + } + }); + if eq_typo || semi_typo { + self.bump(); + // Gracefully handle small typos. + err.span_suggestion_short( + self.prev_token.span, + "field names and their types are separated with `:`", + ":".to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + } else { + return Err(err); + } + } + Ok(()) + } + /// Parses a structure field. fn parse_name_and_ty( &mut self, @@ -1408,8 +1439,21 @@ impl<'a> Parser<'a> { attrs: Vec, ) -> PResult<'a, FieldDef> { let name = self.parse_field_ident(adt_ty, lo)?; - self.expect(&token::Colon)?; + self.expect_field_ty_separator()?; let ty = self.parse_ty()?; + if self.token.kind == token::Eq { + self.bump(); + let const_expr = self.parse_anon_const_expr()?; + let sp = ty.span.shrink_to_hi().to(const_expr.value.span); + self.struct_span_err(sp, "default values on `struct` fields aren't supported") + .span_suggestion( + sp, + "remove this unsupported default value", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + } Ok(FieldDef { span: lo.to(self.prev_token.span), ident: Some(name), diff --git a/src/test/ui/parser/struct-default-values-and-missing-field-separator.fixed b/src/test/ui/parser/struct-default-values-and-missing-field-separator.fixed new file mode 100644 index 0000000000000..28191b82621fd --- /dev/null +++ b/src/test/ui/parser/struct-default-values-and-missing-field-separator.fixed @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +enum E { + A, +} + +struct S { + field1: i32, //~ ERROR default values on `struct` fields aren't supported + field2: E, //~ ERROR default values on `struct` fields aren't supported + field3: i32, //~ ERROR default values on `struct` fields aren't supported + field4: i32, //~ ERROR default values on `struct` fields aren't supported + field5: E, //~ ERROR default values on `struct` fields aren't supported + field6: E, //~ ERROR default values on `struct` fields aren't supported +} + +struct S1 { + field1: i32, //~ ERROR expected `,`, or `}`, found `field2` + field2: E, //~ ERROR expected `,`, or `}`, found `field3` + field3: i32, //~ ERROR default values on `struct` fields aren't supported + field4: i32, //~ ERROR default values on `struct` fields aren't supported + field5: E, //~ ERROR default values on `struct` fields aren't supported + field6: E, //~ ERROR default values on `struct` fields aren't supported +} + +struct S2 { + field1 : i32, //~ ERROR expected `:`, found `=` + field2: E, //~ ERROR expected `:`, found `;` +} + +const fn foo(_: i32) -> E { + E::A +} + +fn main() {} diff --git a/src/test/ui/parser/struct-default-values-and-missing-field-separator.rs b/src/test/ui/parser/struct-default-values-and-missing-field-separator.rs new file mode 100644 index 0000000000000..924cb08a990a5 --- /dev/null +++ b/src/test/ui/parser/struct-default-values-and-missing-field-separator.rs @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +enum E { + A, +} + +struct S { + field1: i32 = 42, //~ ERROR default values on `struct` fields aren't supported + field2: E = E::A, //~ ERROR default values on `struct` fields aren't supported + field3: i32 = 1 + 2, //~ ERROR default values on `struct` fields aren't supported + field4: i32 = { 1 + 2 }, //~ ERROR default values on `struct` fields aren't supported + field5: E = foo(42), //~ ERROR default values on `struct` fields aren't supported + field6: E = { foo(42) }, //~ ERROR default values on `struct` fields aren't supported +} + +struct S1 { + field1: i32 //~ ERROR expected `,`, or `}`, found `field2` + field2: E //~ ERROR expected `,`, or `}`, found `field3` + field3: i32 = 1 + 2, //~ ERROR default values on `struct` fields aren't supported + field4: i32 = { 1 + 2 }, //~ ERROR default values on `struct` fields aren't supported + field5: E = foo(42), //~ ERROR default values on `struct` fields aren't supported + field6: E = { foo(42) }, //~ ERROR default values on `struct` fields aren't supported +} + +struct S2 { + field1 = i32, //~ ERROR expected `:`, found `=` + field2; E, //~ ERROR expected `:`, found `;` +} + +const fn foo(_: i32) -> E { + E::A +} + +fn main() {} diff --git a/src/test/ui/parser/struct-default-values-and-missing-field-separator.stderr b/src/test/ui/parser/struct-default-values-and-missing-field-separator.stderr new file mode 100644 index 0000000000000..7f16ebcfc3ace --- /dev/null +++ b/src/test/ui/parser/struct-default-values-and-missing-field-separator.stderr @@ -0,0 +1,92 @@ +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:9:16 + | +LL | field1: i32 = 42, + | ^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:10:14 + | +LL | field2: E = E::A, + | ^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:11:16 + | +LL | field3: i32 = 1 + 2, + | ^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:12:16 + | +LL | field4: i32 = { 1 + 2 }, + | ^^^^^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:13:14 + | +LL | field5: E = foo(42), + | ^^^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:14:14 + | +LL | field6: E = { foo(42) }, + | ^^^^^^^^^^^^^^ help: remove this unsupported default value + +error: expected `,`, or `}`, found `field2` + --> $DIR/struct-default-values-and-missing-field-separator.rs:18:16 + | +LL | field1: i32 + | ^ help: try adding a comma: `,` + +error: expected `,`, or `}`, found `field3` + --> $DIR/struct-default-values-and-missing-field-separator.rs:19:14 + | +LL | field2: E + | ^ help: try adding a comma: `,` + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:20:16 + | +LL | field3: i32 = 1 + 2, + | ^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:21:16 + | +LL | field4: i32 = { 1 + 2 }, + | ^^^^^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:22:14 + | +LL | field5: E = foo(42), + | ^^^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:23:14 + | +LL | field6: E = { foo(42) }, + | ^^^^^^^^^^^^^^ help: remove this unsupported default value + +error: expected `:`, found `=` + --> $DIR/struct-default-values-and-missing-field-separator.rs:27:12 + | +LL | field1 = i32, + | ^ + | | + | expected `:` + | help: field names and their types are separated with `:` + +error: expected `:`, found `;` + --> $DIR/struct-default-values-and-missing-field-separator.rs:28:11 + | +LL | field2; E, + | ^ + | | + | expected `:` + | help: field names and their types are separated with `:` + +error: aborting due to 14 previous errors +