summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-03-22 19:31:24 +0100
committerGitHub <noreply@github.com>2019-03-22 19:31:24 +0100
commit5a0e4510a805aa7feb93f7a34000be7d5d9a6249 (patch)
treedf4aff066dccc48f8c83eb25920296a15a8c491e /src/libsyntax
parentadbfcea58f89dee842519d4ef0cbaefe09fac3a5 (diff)
parent757eb679927e2c85457f567487e887eb080eb7cb (diff)
downloadrust-5a0e4510a805aa7feb93f7a34000be7d5d9a6249.tar.gz
rust-5a0e4510a805aa7feb93f7a34000be7d5d9a6249.zip
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.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs8
-rw-r--r--src/libsyntax/config.rs2
-rw-r--r--src/libsyntax/mut_visit.rs2
-rw-r--r--src/libsyntax/parse/parser.rs30
4 files changed, 26 insertions, 16 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 1a0da73880c..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<Spanned<FieldPat>>, bool),
+    Struct(Path, Vec<Spanned<FieldPat>>, /* recovered */ bool),
 
     /// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
@@ -2133,7 +2133,7 @@ pub enum VariantData {
     /// Struct variant.
     ///
     /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
-    Struct(Vec<StructField>, NodeId),
+    Struct(Vec<StructField>, 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<T: MutVisitor>(pred: &mut WherePredicate, vis:
 
 pub fn noop_visit_variant_data<T: MutVisitor>(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 7a4a687f90e..648ee771ddb 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -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,