Change enum parse recovery

This commit is contained in:
Esteban Küber 2023-11-06 23:24:42 +00:00
parent 1994abed74
commit db39068ad7
3 changed files with 44 additions and 21 deletions

View File

@ -1415,8 +1415,8 @@ impl<'a> Parser<'a> {
self.bump(); self.bump();
(thin_vec![], false) (thin_vec![], false)
} else { } else {
self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err( self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant(id.span))
|mut err| { .map_err(|mut err| {
err.span_label(id.span, "while parsing this enum"); err.span_label(id.span, "while parsing this enum");
if self.token == token::Colon { if self.token == token::Colon {
let snapshot = self.create_snapshot_for_diagnostic(); let snapshot = self.create_snapshot_for_diagnostic();
@ -1436,17 +1436,17 @@ impl<'a> Parser<'a> {
} }
self.restore_snapshot(snapshot); self.restore_snapshot(snapshot);
} }
self.recover_stmt(); self.eat_to_tokens(&[&token::CloseDelim(Delimiter::Brace)]);
self.bump(); // }
err err
}, })?
)?
}; };
let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() }; let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
Ok((id, ItemKind::Enum(enum_definition, generics))) 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(); self.recover_diff_marker();
let variant_attrs = self.parse_outer_attributes()?; let variant_attrs = self.parse_outer_attributes()?;
self.recover_diff_marker(); self.recover_diff_marker();
@ -1476,10 +1476,37 @@ impl<'a> Parser<'a> {
let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) { let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) {
// Parse a struct variant. // Parse a struct variant.
let (fields, recovered) = 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) VariantData::Struct(fields, recovered)
} else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) { } 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 { } else {
VariantData::Unit(DUMMY_NODE_ID) VariantData::Unit(DUMMY_NODE_ID)
}; };

View File

@ -11,8 +11,14 @@ LL | enum e{A((?'a a+?+l))}
| - ^ expected one of `)`, `+`, or `,` | - ^ expected one of `)`, `+`, or `,`
| | | |
| while parsing this enum | while parsing this enum
error: expected item, found `)`
--> $DIR/issue-68890.rs:1:21
| |
= help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` LL | enum e{A((?'a a+?+l))}
| ^ 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 2 previous errors error: aborting due to 3 previous errors

View File

@ -13,16 +13,6 @@ LL | enum Test4 {
| ----- while parsing this enum | ----- while parsing this enum
LL | Nope(i32 {}) LL | Nope(i32 {})
| ^ expected one of 7 possible tokens | ^ 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 `}` error: aborting due to 2 previous errors
--> $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