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.
This commit is contained in:
Esteban Küber 2019-03-17 20:09:53 -07:00
parent 7cf074a1e6
commit 6007e6f649
15 changed files with 108 additions and 57 deletions

View file

@ -6829,14 +6829,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);
@ -6864,9 +6866,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!(
@ -6898,12 +6902,14 @@ 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>, 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 {
@ -6922,7 +6928,7 @@ impl<'a> Parser<'a> {
return Err(err);
}
Ok(fields)
Ok((fields, recovered))
}
fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
@ -7684,12 +7690,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,