From 645332f87d55eede076b3f8c898a99b7a0d0312b Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 5 Jul 2024 00:52:34 +0800 Subject: [PATCH] try recover from struct parse error --- compiler/rustc_parse/src/parser/item.rs | 11 ++++- .../struct-parser-recovery-issue-126344.rs | 42 +++++++++++++++++++ ...struct-parser-recovery-issue-126344.stderr | 41 ++++++++++++++++++ 3 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 tests/ui/pattern/struct-parser-recovery-issue-126344.rs create mode 100644 tests/ui/pattern/struct-parser-recovery-issue-126344.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index abb6b51cebd68..dc0acf02eb37c 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1753,11 +1753,18 @@ impl<'a> Parser<'a> { fields.push(field); } Err(mut err) => { - self.consume_block(Delimiter::Brace, ConsumeClosingDelim::No); err.span_label(ident_span, format!("while parsing this {adt_ty}")); let guar = err.emit(); recovered = Recovered::Yes(guar); - break; + if self.look_ahead(1, |next_token| next_token == &token::Comma) { + self.bump(); + self.eat(&TokenKind::Comma); + } else if self.prev_token.kind == token::Semi { + // we already suggested `;` -> `,`, here we try to recover and continue parse next field + } else { + self.consume_block(Delimiter::Brace, ConsumeClosingDelim::No); + break; + } } } } diff --git a/tests/ui/pattern/struct-parser-recovery-issue-126344.rs b/tests/ui/pattern/struct-parser-recovery-issue-126344.rs new file mode 100644 index 0000000000000..b6e06abbfff22 --- /dev/null +++ b/tests/ui/pattern/struct-parser-recovery-issue-126344.rs @@ -0,0 +1,42 @@ +struct Wrong { + x: i32; //~ ERROR struct fields are separated by `,` + y: i32, + z: i32, + h: i32, +} + +fn oops(w: &Wrong) { + w.x; //~ ERROR no field `x` on type `&Wrong` +} + +fn foo(w: &Wrong) { + w.y; +} + +fn haha(w: &Wrong) { + w.z; +} + +struct WrongWithType { + x: 1, //~ ERROR expected type, found `1` + y: i32, + z: i32, + h: i32, +} + +fn oops_type(w: &WrongWithType) { + w.x; //~ ERROR no field `x` on type `&WrongWithType` +} + +fn foo_type(w: &WrongWithType) { + w.y; +} + +fn haha_type(w: &WrongWithType) { + w.z; +} + +fn main() { + let v = Wrong { x: 1, y: 2, z: 3, h: 4 }; + let x = WrongWithType { x: 1, y: 2, z: 3, h: 4 }; +} diff --git a/tests/ui/pattern/struct-parser-recovery-issue-126344.stderr b/tests/ui/pattern/struct-parser-recovery-issue-126344.stderr new file mode 100644 index 0000000000000..001a601fd369d --- /dev/null +++ b/tests/ui/pattern/struct-parser-recovery-issue-126344.stderr @@ -0,0 +1,41 @@ +error: struct fields are separated by `,` + --> $DIR/struct-parser-recovery-issue-126344.rs:2:11 + | +LL | struct Wrong { + | ----- while parsing this struct +LL | x: i32; + | ^ help: replace `;` with `,` + +error: expected type, found `1` + --> $DIR/struct-parser-recovery-issue-126344.rs:21:8 + | +LL | struct WrongWithType { + | ------------- while parsing this struct +LL | x: 1, + | ^ expected type + +error[E0609]: no field `x` on type `&Wrong` + --> $DIR/struct-parser-recovery-issue-126344.rs:9:7 + | +LL | w.x; + | ^ unknown field + | +help: a field with a similar name exists + | +LL | w.y; + | ~ + +error[E0609]: no field `x` on type `&WrongWithType` + --> $DIR/struct-parser-recovery-issue-126344.rs:28:7 + | +LL | w.x; + | ^ unknown field + | +help: a field with a similar name exists + | +LL | w.y; + | ~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0609`.