diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2023-11-06 23:24:42 +0000 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2023-11-29 18:47:31 +0000 |
| commit | db39068ad7060bf2375535e50aeb3e42d9f939bd (patch) | |
| tree | bd84df8a60528c0ce47ee63b40cf6c0ecf5f81f7 | |
| parent | 1994abed74b3f39297f49a9caed1513eb12b21b3 (diff) | |
| download | rust-db39068ad7060bf2375535e50aeb3e42d9f939bd.tar.gz rust-db39068ad7060bf2375535e50aeb3e42d9f939bd.zip | |
Change enum parse recovery
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 43 | ||||
| -rw-r--r-- | tests/ui/parser/issues/issue-68890.stderr | 10 | ||||
| -rw-r--r-- | tests/ui/parser/recover/recover-enum2.stderr | 12 |
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 |
