about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-01-21 15:28:51 -0800
committerEsteban Küber <esteban@kuber.com.ar>2019-01-21 15:47:23 -0800
commit4745b86202f0e96b4c0d0de05220a5ac4b5308ef (patch)
tree1c7f7912efac2e75ae727afc4000956438962697 /src/libsyntax/parse/parser.rs
parentdefa61f3fb2612358b57c206c5e16da2751e6deb (diff)
downloadrust-4745b86202f0e96b4c0d0de05220a5ac4b5308ef.tar.gz
rust-4745b86202f0e96b4c0d0de05220a5ac4b5308ef.zip
Accept more invalid code that is close to correct fields
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs22
1 files changed, 20 insertions, 2 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a2d3595b472..745f2c7dc19 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2695,6 +2695,21 @@ impl<'a> Parser<'a> {
                 break;
             }
 
+            let mut recovery_field = None;
+            if let token::Ident(ident, _) = self.token {
+                if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
+                    // Use in case of error after field-looking code: `S { foo: () with a }`
+                    let mut ident = ident.clone();
+                    ident.span = self.span;
+                    recovery_field = Some(ast::Field {
+                        ident,
+                        span: self.span,
+                        expr: self.mk_expr(self.span, ExprKind::Err, ThinVec::new()),
+                        is_shorthand: false,
+                        attrs: ThinVec::new(),
+                    });
+                }
+            }
             let mut parsed_field = None;
             match self.parse_field() {
                 Ok(f) => parsed_field = Some(f),
@@ -2716,11 +2731,14 @@ impl<'a> Parser<'a> {
 
             match self.expect_one_of(&[token::Comma],
                                      &[token::CloseDelim(token::Brace)]) {
-                Ok(()) => if let Some(f) = parsed_field {
-                    // only include the field if there's no parse error
+                Ok(()) => if let Some(f) = parsed_field.or(recovery_field) {
+                    // only include the field if there's no parse error for the field name
                     fields.push(f);
                 }
                 Err(mut e) => {
+                    if let Some(f) = recovery_field {
+                        fields.push(f);
+                    }
                     e.span_label(struct_sp, "while parsing this struct");
                     e.emit();
                     self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);