Rollup merge of #59266 - estebank:struct-parse-recovery, r=petrochenkov
Do not complain about non-existing fields after parse recovery When failing to parse struct-like enum variants, the ADT gets recorded as having no fields. Record that we have actually recovered during parsing of this variant to avoid complaing about non-existing fields when actually using it. Fix #57361.
This commit is contained in:
@@ -6837,14 +6837,16 @@ impl<'a> Parser<'a> {
|
||||
VariantData::Unit(ast::DUMMY_NODE_ID)
|
||||
} else {
|
||||
// If we see: `struct Foo<T> where T: Copy { ... }`
|
||||
VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
|
||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
||||
VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
|
||||
}
|
||||
// No `where` so: `struct Foo<T>;`
|
||||
} else if self.eat(&token::Semi) {
|
||||
VariantData::Unit(ast::DUMMY_NODE_ID)
|
||||
// Record-style struct definition
|
||||
} else if self.token == token::OpenDelim(token::Brace) {
|
||||
VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
|
||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
||||
VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
|
||||
// Tuple-style struct definition with optional where-clause.
|
||||
} else if self.token == token::OpenDelim(token::Paren) {
|
||||
let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID);
|
||||
@@ -6872,9 +6874,11 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let vdata = if self.token.is_keyword(keywords::Where) {
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
|
||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
||||
VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
|
||||
} else if self.token == token::OpenDelim(token::Brace) {
|
||||
VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
|
||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
||||
VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
|
||||
} else {
|
||||
let token_str = self.this_token_descr();
|
||||
let mut err = self.fatal(&format!(
|
||||
@@ -6906,12 +6910,16 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_record_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
|
||||
fn parse_record_struct_body(
|
||||
&mut self,
|
||||
) -> PResult<'a, (Vec<StructField>, /* recovered */ bool)> {
|
||||
let mut fields = Vec::new();
|
||||
let mut recovered = false;
|
||||
if self.eat(&token::OpenDelim(token::Brace)) {
|
||||
while self.token != token::CloseDelim(token::Brace) {
|
||||
let field = self.parse_struct_decl_field().map_err(|e| {
|
||||
self.recover_stmt();
|
||||
recovered = true;
|
||||
e
|
||||
});
|
||||
match field {
|
||||
@@ -6930,7 +6938,7 @@ impl<'a> Parser<'a> {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
Ok(fields)
|
||||
Ok((fields, recovered))
|
||||
}
|
||||
|
||||
fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
|
||||
@@ -7693,12 +7701,14 @@ impl<'a> Parser<'a> {
|
||||
if self.check(&token::OpenDelim(token::Brace)) {
|
||||
// Parse a struct variant.
|
||||
all_nullary = false;
|
||||
struct_def = VariantData::Struct(self.parse_record_struct_body()?,
|
||||
ast::DUMMY_NODE_ID);
|
||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
||||
struct_def = VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered);
|
||||
} else if self.check(&token::OpenDelim(token::Paren)) {
|
||||
all_nullary = false;
|
||||
struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?,
|
||||
ast::DUMMY_NODE_ID);
|
||||
struct_def = VariantData::Tuple(
|
||||
self.parse_tuple_struct_body()?,
|
||||
ast::DUMMY_NODE_ID,
|
||||
);
|
||||
} else if self.eat(&token::Eq) {
|
||||
disr_expr = Some(AnonConst {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
|
||||
Reference in New Issue
Block a user