about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2023-11-06 23:24:42 +0000
committerEsteban Küber <esteban@kuber.com.ar>2023-11-29 18:47:31 +0000
commitdb39068ad7060bf2375535e50aeb3e42d9f939bd (patch)
treebd84df8a60528c0ce47ee63b40cf6c0ecf5f81f7
parent1994abed74b3f39297f49a9caed1513eb12b21b3 (diff)
downloadrust-db39068ad7060bf2375535e50aeb3e42d9f939bd.tar.gz
rust-db39068ad7060bf2375535e50aeb3e42d9f939bd.zip
Change enum parse recovery
-rw-r--r--compiler/rustc_parse/src/parser/item.rs43
-rw-r--r--tests/ui/parser/issues/issue-68890.stderr10
-rw-r--r--tests/ui/parser/recover/recover-enum2.stderr12
3 files changed, 44 insertions, 21 deletions
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 23886b1208b..5e73472c842 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1415,8 +1415,8 @@ impl<'a> Parser<'a> {
             self.bump();
             (thin_vec![], false)
         } else {
-            self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err(
-                |mut err| {
+            self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant(id.span))
+                .map_err(|mut err| {
                     err.span_label(id.span, "while parsing this enum");
                     if self.token == token::Colon {
                         let snapshot = self.create_snapshot_for_diagnostic();
@@ -1436,17 +1436,17 @@ impl<'a> Parser<'a> {
                         }
                         self.restore_snapshot(snapshot);
                     }
-                    self.recover_stmt();
+                    self.eat_to_tokens(&[&token::CloseDelim(Delimiter::Brace)]);
+                    self.bump(); // }
                     err
-                },
-            )?
+                })?
         };
 
         let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
         Ok((id, ItemKind::Enum(enum_definition, generics)))
     }
 
-    fn parse_enum_variant(&mut self) -> PResult<'a, Option<Variant>> {
+    fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
         self.recover_diff_marker();
         let variant_attrs = self.parse_outer_attributes()?;
         self.recover_diff_marker();
@@ -1476,10 +1476,37 @@ impl<'a> Parser<'a> {
                 let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) {
                     // Parse a struct variant.
                     let (fields, recovered) =
-                        this.parse_record_struct_body("struct", ident.span, false)?;
+                        match this.parse_record_struct_body("struct", ident.span, false) {
+                            Ok((fields, recovered)) => (fields, recovered),
+                            Err(mut err) => {
+                                if this.token == token::Colon {
+                                    // We handle `enum` to `struct` suggestion in the caller.
+                                    return Err(err);
+                                }
+                                this.eat_to_tokens(&[&token::CloseDelim(Delimiter::Brace)]);
+                                this.bump(); // }
+                                err.span_label(span, "while parsing this enum");
+                                err.emit();
+                                (thin_vec![], true)
+                            }
+                        };
                     VariantData::Struct(fields, recovered)
                 } else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) {
-                    VariantData::Tuple(this.parse_tuple_struct_body()?, DUMMY_NODE_ID)
+                    let body = match this.parse_tuple_struct_body() {
+                        Ok(body) => body,
+                        Err(mut err) => {
+                            if this.token == token::Colon {
+                                // We handle `enum` to `struct` suggestion in the caller.
+                                return Err(err);
+                            }
+                            this.eat_to_tokens(&[&token::CloseDelim(Delimiter::Parenthesis)]);
+                            this.bump(); // )
+                            err.span_label(span, "while parsing this enum");
+                            err.emit();
+                            thin_vec![]
+                        }
+                    };
+                    VariantData::Tuple(body, DUMMY_NODE_ID)
                 } else {
                     VariantData::Unit(DUMMY_NODE_ID)
                 };
diff --git a/tests/ui/parser/issues/issue-68890.stderr b/tests/ui/parser/issues/issue-68890.stderr
index 72332e85f18..914c90565f5 100644
--- a/tests/ui/parser/issues/issue-68890.stderr
+++ b/tests/ui/parser/issues/issue-68890.stderr
@@ -11,8 +11,14 @@ LL | enum e{A((?'a a+?+l))}
    |      -        ^ expected one of `)`, `+`, or `,`
    |      |
    |      while parsing this enum
+
+error: expected item, found `)`
+  --> $DIR/issue-68890.rs:1:21
+   |
+LL | enum e{A((?'a a+?+l))}
+   |                     ^ expected item
    |
-   = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
+   = note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/parser/recover/recover-enum2.stderr b/tests/ui/parser/recover/recover-enum2.stderr
index cecb26218eb..71c2804c3a7 100644
--- a/tests/ui/parser/recover/recover-enum2.stderr
+++ b/tests/ui/parser/recover/recover-enum2.stderr
@@ -13,16 +13,6 @@ LL |         enum Test4 {
    |              ----- while parsing this enum
 LL |             Nope(i32 {})
    |                      ^ expected one of 7 possible tokens
-   |
-   = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
-
-error: expected item, found `}`
-  --> $DIR/recover-enum2.rs:28:1
-   |
-LL | }
-   | ^ expected item
-   |
-   = note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors