Rollup merge of #142798 - camsteffen:recover-semi, r=compiler-errors

Don't fail to parse a struct if a semicolon is used to separate fields

The first commit is a small refactor.
This commit is contained in:
Guillaume Gomez 2025-06-22 17:35:35 +02:00 committed by GitHub
commit 194e58c75c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 30 additions and 39 deletions

View File

@ -1781,7 +1781,7 @@ impl<'a> Parser<'a> {
let mut recovered = Recovered::No;
if self.eat(exp!(OpenBrace)) {
while self.token != token::CloseBrace {
match self.parse_field_def(adt_ty) {
match self.parse_field_def(adt_ty, ident_span) {
Ok(field) => {
fields.push(field);
}
@ -1894,7 +1894,7 @@ impl<'a> Parser<'a> {
}
/// Parses an element of a struct declaration.
fn parse_field_def(&mut self, adt_ty: &str) -> PResult<'a, FieldDef> {
fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
self.recover_vcs_conflict_marker();
let attrs = self.parse_outer_attributes()?;
self.recover_vcs_conflict_marker();
@ -1902,7 +1902,7 @@ impl<'a> Parser<'a> {
let lo = this.token.span;
let vis = this.parse_visibility(FollowedByType::No)?;
let safety = this.parse_unsafe_field();
this.parse_single_struct_field(adt_ty, lo, vis, safety, attrs)
this.parse_single_struct_field(adt_ty, lo, vis, safety, attrs, ident_span)
.map(|field| (field, Trailing::No, UsePreAttrPos::No))
})
}
@ -1915,28 +1915,27 @@ impl<'a> Parser<'a> {
vis: Visibility,
safety: Safety,
attrs: AttrVec,
ident_span: Span,
) -> PResult<'a, FieldDef> {
let mut seen_comma: bool = false;
let a_var = self.parse_name_and_ty(adt_ty, lo, vis, safety, attrs)?;
if self.token == token::Comma {
seen_comma = true;
}
if self.eat(exp!(Semi)) {
let sp = self.prev_token.span;
let mut err =
self.dcx().struct_span_err(sp, format!("{adt_ty} fields are separated by `,`"));
err.span_suggestion_short(
sp,
"replace `;` with `,`",
",",
Applicability::MachineApplicable,
);
return Err(err);
}
match self.token.kind {
token::Comma => {
self.bump();
}
token::Semi => {
self.bump();
let sp = self.prev_token.span;
let mut err =
self.dcx().struct_span_err(sp, format!("{adt_ty} fields are separated by `,`"));
err.span_suggestion_short(
sp,
"replace `;` with `,`",
",",
Applicability::MachineApplicable,
);
err.span_label(ident_span, format!("while parsing this {adt_ty}"));
err.emit();
}
token::CloseBrace => {}
token::DocComment(..) => {
let previous_span = self.prev_token.span;
@ -1945,19 +1944,11 @@ impl<'a> Parser<'a> {
missing_comma: None,
};
self.bump(); // consume the doc comment
let comma_after_doc_seen = self.eat(exp!(Comma));
// `seen_comma` is always false, because we are inside doc block
// condition is here to make code more readable
if !seen_comma && comma_after_doc_seen {
seen_comma = true;
}
if comma_after_doc_seen || self.token == token::CloseBrace {
if self.eat(exp!(Comma)) || self.token == token::CloseBrace {
self.dcx().emit_err(err);
} else {
if !seen_comma {
let sp = previous_span.shrink_to_hi();
err.missing_comma = Some(sp);
}
let sp = previous_span.shrink_to_hi();
err.missing_comma = Some(sp);
return Err(self.dcx().create_err(err));
}
}

View File

@ -3,7 +3,7 @@ struct Foo {
//~^ ERROR struct fields are separated by `,`
}
union Bar { //~ ERROR
union Bar {
foo: i32;
//~^ ERROR union fields are separated by `,`
}
@ -13,4 +13,6 @@ enum Baz {
//~^ ERROR struct fields are separated by `,`
}
fn main() {}
fn main() {
let _ = Foo { foo: "" }; //~ ERROR mismatched types
}

View File

@ -22,14 +22,12 @@ LL | Qux { foo: i32; }
| |
| while parsing this struct
error: unions cannot have zero fields
--> $DIR/recover-field-semi.rs:6:1
error[E0308]: mismatched types
--> $DIR/recover-field-semi.rs:17:24
|
LL | / union Bar {
LL | | foo: i32;
LL | |
LL | | }
| |_^
LL | let _ = Foo { foo: "" };
| ^^ expected `i32`, found `&str`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`.