about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-02-13 18:23:28 +0100
committerLukas Wirth <lukastw97@gmail.com>2024-02-13 18:23:33 +0100
commitccccc299c850a250e28fd3469e75e1ec24e9c672 (patch)
tree8e2ed7ae0d628f833b9bc5d6802238de18a30600
parent925705e0c920836fefe617c4caf9e8aa4b2bfaf0 (diff)
downloadrust-ccccc299c850a250e28fd3469e75e1ec24e9c672.tar.gz
rust-ccccc299c850a250e28fd3469e75e1ec24e9c672.zip
fix: Recover from `=` in record constructor field assignment
-rw-r--r--crates/parser/src/grammar/expressions.rs29
-rw-r--r--crates/parser/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast36
-rw-r--r--crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rast41
-rw-r--r--crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rs3
4 files changed, 82 insertions, 27 deletions
diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs
index f40c515fa07..052300f6d5a 100644
--- a/crates/parser/src/grammar/expressions.rs
+++ b/crates/parser/src/grammar/expressions.rs
@@ -678,27 +678,38 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
         attributes::outer_attrs(p);
 
         match p.current() {
-            IDENT | INT_NUMBER => {
+            IDENT | INT_NUMBER if p.nth_at(1, T![::]) => {
                 // test_err record_literal_missing_ellipsis_recovery
                 // fn main() {
                 //     S { S::default() }
                 // }
-                if p.nth_at(1, T![::]) {
-                    m.abandon(p);
-                    p.expect(T![..]);
-                    expr(p);
-                } else {
+                m.abandon(p);
+                p.expect(T![..]);
+                expr(p);
+            }
+            IDENT | INT_NUMBER => {
+                if p.nth_at(1, T![..]) {
                     // test_err record_literal_before_ellipsis_recovery
                     // fn main() {
                     //     S { field ..S::default() }
                     // }
-                    if p.nth_at(1, T![:]) || p.nth_at(1, T![..]) {
+                    name_ref_or_index(p);
+                    p.error("expected colon");
+                } else {
+                    // test_err record_literal_field_eq_recovery
+                    // fn main() {
+                    //     S { field = foo }
+                    // }
+                    if p.nth_at(1, T![:]) {
+                        name_ref_or_index(p);
+                        p.bump(T![:]);
+                    } else if p.nth_at(1, T![=]) {
                         name_ref_or_index(p);
-                        p.expect(T![:]);
+                        p.err_and_bump("expected colon");
                     }
                     expr(p);
-                    m.complete(p, RECORD_EXPR_FIELD);
                 }
+                m.complete(p, RECORD_EXPR_FIELD);
             }
             T![.] if p.at(T![..]) => {
                 m.abandon(p);
diff --git a/crates/parser/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast b/crates/parser/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast
index f511960040d..c59ea2604b9 100644
--- a/crates/parser/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast
+++ b/crates/parser/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast
@@ -24,26 +24,26 @@ SOURCE_FILE
             RECORD_EXPR_FIELD
               NAME_REF
                 IDENT "field"
-              WHITESPACE " "
-              RANGE_EXPR
-                DOT2 ".."
-                CALL_EXPR
-                  PATH_EXPR
-                    PATH
-                      PATH
-                        PATH_SEGMENT
-                          NAME_REF
-                            IDENT "S"
-                      COLON2 "::"
-                      PATH_SEGMENT
-                        NAME_REF
-                          IDENT "default"
-                  ARG_LIST
-                    L_PAREN "("
-                    R_PAREN ")"
+            WHITESPACE " "
+            DOT2 ".."
+            CALL_EXPR
+              PATH_EXPR
+                PATH
+                  PATH
+                    PATH_SEGMENT
+                      NAME_REF
+                        IDENT "S"
+                  COLON2 "::"
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "default"
+              ARG_LIST
+                L_PAREN "("
+                R_PAREN ")"
             WHITESPACE " "
             R_CURLY "}"
         WHITESPACE "\n"
         R_CURLY "}"
   WHITESPACE "\n"
-error 25: expected COLON
+error 25: expected colon
+error 25: expected COMMA
diff --git a/crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rast b/crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rast
new file mode 100644
index 00000000000..4ba6f9117f9
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rast
@@ -0,0 +1,41 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "main"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE "\n    "
+        RECORD_EXPR
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "S"
+          WHITESPACE " "
+          RECORD_EXPR_FIELD_LIST
+            L_CURLY "{"
+            WHITESPACE " "
+            RECORD_EXPR_FIELD
+              NAME_REF
+                IDENT "field"
+              WHITESPACE " "
+              ERROR
+                EQ "="
+              WHITESPACE " "
+              PATH_EXPR
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "foo"
+            WHITESPACE " "
+            R_CURLY "}"
+        WHITESPACE "\n"
+        R_CURLY "}"
+  WHITESPACE "\n"
+error 26: expected colon
diff --git a/crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rs b/crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rs
new file mode 100644
index 00000000000..1eb1aa9b926
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rs
@@ -0,0 +1,3 @@
+fn main() {
+    S { field = foo }
+}