about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_parse/src/parser/item.rs46
-rw-r--r--src/test/ui/parser/struct-default-values-and-missing-field-separator.fixed35
-rw-r--r--src/test/ui/parser/struct-default-values-and-missing-field-separator.rs35
-rw-r--r--src/test/ui/parser/struct-default-values-and-missing-field-separator.stderr92
4 files changed, 207 insertions, 1 deletions
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 553ffda814f..b2b578f1ed4 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<Attribute>,
     ) -> 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 00000000000..28191b82621
--- /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 00000000000..924cb08a990
--- /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 00000000000..7f16ebcfc3a
--- /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
+