From 6007e6f649feac9a0cb39270444033f8dbfa9259 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Sun, 17 Mar 2019 20:09:53 -0700 Subject: 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. --- src/libsyntax/ast.rs | 6 +++--- src/libsyntax/config.rs | 2 +- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/parse/parser.rs | 28 ++++++++++++++++++---------- 4 files changed, 23 insertions(+), 15 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1a0da73880c..5da00ef8ebe 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2133,7 +2133,7 @@ pub enum VariantData { /// Struct variant. /// /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`. - Struct(Vec, NodeId), + Struct(Vec, NodeId, bool), /// Tuple variant. /// /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`. @@ -2147,13 +2147,13 @@ pub enum VariantData { impl VariantData { pub fn fields(&self) -> &[StructField] { match *self { - VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => fields, + VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields, _ => &[], } } pub fn id(&self) -> NodeId { match *self { - VariantData::Struct(_, id) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id, + VariantData::Struct(_, id, _) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id, } } pub fn is_struct(&self) -> bool { diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index c300ffc2d61..7159c949513 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -225,7 +225,7 @@ impl<'a> StripUnconfigured<'a> { fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) { match vdata { - ast::VariantData::Struct(fields, _id) | + ast::VariantData::Struct(fields, _id, _) | ast::VariantData::Tuple(fields, _id) => fields.flat_map_in_place(|field| self.configure(field)), ast::VariantData::Unit(_id) => {} diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 462346df7d7..5bb1d8a4b94 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -765,7 +765,7 @@ pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: pub fn noop_visit_variant_data(vdata: &mut VariantData, vis: &mut T) { match vdata { - VariantData::Struct(fields, id) | + VariantData::Struct(fields, id, _) | VariantData::Tuple(fields, id) => { visit_vec(fields, |field| vis.visit_struct_field(field)); vis.visit_id(id); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index aa70c54a1ef..360a101a64f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6829,14 +6829,16 @@ impl<'a> Parser<'a> { VariantData::Unit(ast::DUMMY_NODE_ID) } else { // If we see: `struct Foo 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;` } 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> { + fn parse_record_struct_body(&mut self) -> PResult<'a, (Vec, 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> { @@ -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, -- cgit 1.4.1-3-g733a5 From 757eb679927e2c85457f567487e887eb080eb7cb Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Tue, 19 Mar 2019 13:17:25 -0700 Subject: review comments --- src/librustc/hir/mod.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/parse/parser.rs | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 785d7745b29..51d91cc562f 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2173,7 +2173,7 @@ impl StructField { /// Id of the whole struct lives in `Item`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum VariantData { - Struct(HirVec, HirId, bool), + Struct(HirVec, HirId, /* recovered */ bool), Tuple(HirVec, HirId), Unit(HirId), } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 5da00ef8ebe..2cbd2dfeb25 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -620,7 +620,7 @@ pub enum PatKind { /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// The `bool` is `true` in the presence of a `..`. - Struct(Path, Vec>, bool), + Struct(Path, Vec>, /* recovered */ bool), /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). /// If the `..` pattern fragment is present, then `Option` denotes its position. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 360a101a64f..361ecce5bc4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6902,7 +6902,9 @@ impl<'a> Parser<'a> { } } - fn parse_record_struct_body(&mut self) -> PResult<'a, (Vec, bool)> { + fn parse_record_struct_body( + &mut self, + ) -> PResult<'a, (Vec, /* recovered */ bool)> { let mut fields = Vec::new(); let mut recovered = false; if self.eat(&token::OpenDelim(token::Brace)) { -- cgit 1.4.1-3-g733a5