Skip to content

Commit db39068

Browse files
committed
Change enum parse recovery
1 parent 1994abe commit db39068

File tree

3 files changed

+44
-21
lines changed

3 files changed

+44
-21
lines changed

compiler/rustc_parse/src/parser/item.rs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,8 +1415,8 @@ impl<'a> Parser<'a> {
14151415
self.bump();
14161416
(thin_vec![], false)
14171417
} else {
1418-
self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err(
1419-
|mut err| {
1418+
self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant(id.span))
1419+
.map_err(|mut err| {
14201420
err.span_label(id.span, "while parsing this enum");
14211421
if self.token == token::Colon {
14221422
let snapshot = self.create_snapshot_for_diagnostic();
@@ -1436,17 +1436,17 @@ impl<'a> Parser<'a> {
14361436
}
14371437
self.restore_snapshot(snapshot);
14381438
}
1439-
self.recover_stmt();
1439+
self.eat_to_tokens(&[&token::CloseDelim(Delimiter::Brace)]);
1440+
self.bump(); // }
14401441
err
1441-
},
1442-
)?
1442+
})?
14431443
};
14441444

14451445
let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
14461446
Ok((id, ItemKind::Enum(enum_definition, generics)))
14471447
}
14481448

1449-
fn parse_enum_variant(&mut self) -> PResult<'a, Option<Variant>> {
1449+
fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
14501450
self.recover_diff_marker();
14511451
let variant_attrs = self.parse_outer_attributes()?;
14521452
self.recover_diff_marker();
@@ -1476,10 +1476,37 @@ impl<'a> Parser<'a> {
14761476
let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) {
14771477
// Parse a struct variant.
14781478
let (fields, recovered) =
1479-
this.parse_record_struct_body("struct", ident.span, false)?;
1479+
match this.parse_record_struct_body("struct", ident.span, false) {
1480+
Ok((fields, recovered)) => (fields, recovered),
1481+
Err(mut err) => {
1482+
if this.token == token::Colon {
1483+
// We handle `enum` to `struct` suggestion in the caller.
1484+
return Err(err);
1485+
}
1486+
this.eat_to_tokens(&[&token::CloseDelim(Delimiter::Brace)]);
1487+
this.bump(); // }
1488+
err.span_label(span, "while parsing this enum");
1489+
err.emit();
1490+
(thin_vec![], true)
1491+
}
1492+
};
14801493
VariantData::Struct(fields, recovered)
14811494
} else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) {
1482-
VariantData::Tuple(this.parse_tuple_struct_body()?, DUMMY_NODE_ID)
1495+
let body = match this.parse_tuple_struct_body() {
1496+
Ok(body) => body,
1497+
Err(mut err) => {
1498+
if this.token == token::Colon {
1499+
// We handle `enum` to `struct` suggestion in the caller.
1500+
return Err(err);
1501+
}
1502+
this.eat_to_tokens(&[&token::CloseDelim(Delimiter::Parenthesis)]);
1503+
this.bump(); // )
1504+
err.span_label(span, "while parsing this enum");
1505+
err.emit();
1506+
thin_vec![]
1507+
}
1508+
};
1509+
VariantData::Tuple(body, DUMMY_NODE_ID)
14831510
} else {
14841511
VariantData::Unit(DUMMY_NODE_ID)
14851512
};

tests/ui/parser/issues/issue-68890.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,14 @@ LL | enum e{A((?'a a+?+l))}
1111
| - ^ expected one of `)`, `+`, or `,`
1212
| |
1313
| while parsing this enum
14+
15+
error: expected item, found `)`
16+
--> $DIR/issue-68890.rs:1:21
17+
|
18+
LL | enum e{A((?'a a+?+l))}
19+
| ^ expected item
1420
|
15-
= help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
21+
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
1622

17-
error: aborting due to 2 previous errors
23+
error: aborting due to 3 previous errors
1824

tests/ui/parser/recover/recover-enum2.stderr

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,6 @@ LL | enum Test4 {
1313
| ----- while parsing this enum
1414
LL | Nope(i32 {})
1515
| ^ expected one of 7 possible tokens
16-
|
17-
= help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
18-
19-
error: expected item, found `}`
20-
--> $DIR/recover-enum2.rs:28:1
21-
|
22-
LL | }
23-
| ^ expected item
24-
|
25-
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
2616

27-
error: aborting due to 3 previous errors
17+
error: aborting due to 2 previous errors
2818

0 commit comments

Comments
 (0)