about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-07-04 18:10:20 +0000
committerbors <bors@rust-lang.org>2023-07-04 18:10:20 +0000
commite95644e279592ea36061633779a2648afeb9536f (patch)
tree80c4c19683f11dd86edb99a3d0cf7e1fdd11864c
parente219999a1799596cd2412f234e736a0f198b943d (diff)
parent49b039f1d1591757e7fbd77243c23154691c38a9 (diff)
downloadrust-e95644e279592ea36061633779a2648afeb9536f.tar.gz
rust-e95644e279592ea36061633779a2648afeb9536f.zip
Auto merge of #15212 - lowr:patch/recover-from-incomplete-assoc-ty, r=HKalbasi
Recover from missing associated items and generic const defaults

Fixes #15129
-rw-r--r--crates/parser/src/grammar/generic_args.rs19
-rw-r--r--crates/parser/src/grammar/generic_params.rs3
-rw-r--r--crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rast48
-rw-r--r--crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rs1
-rw-r--r--crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast44
-rw-r--r--crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rs1
6 files changed, 113 insertions, 3 deletions
diff --git a/crates/parser/src/grammar/generic_args.rs b/crates/parser/src/grammar/generic_args.rs
index e589b69934d..211af98e6ef 100644
--- a/crates/parser/src/grammar/generic_args.rs
+++ b/crates/parser/src/grammar/generic_args.rs
@@ -32,6 +32,9 @@ const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
 ])
 .union(types::TYPE_FIRST);
 
+// Despite its name, it can also be used for generic param list.
+const GENERIC_ARG_RECOVERY_SET: TokenSet = TokenSet::new(&[T![>], T![,]]);
+
 // test generic_arg
 // type T = S<i32>;
 fn generic_arg(p: &mut Parser<'_>) -> bool {
@@ -55,6 +58,15 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
                         // test assoc_type_eq
                         // type T = StreamingIterator<Item<'a> = &'a T>;
                         types::type_(p);
+                    } else if p.at_ts(GENERIC_ARG_RECOVERY_SET) {
+                        // Although `const_arg()` recovers as expected, we want to
+                        // handle those here to give the following message because
+                        // we don't know whether this associated item is a type or
+                        // const at this point.
+
+                        // test_err recover_from_missing_assoc_item_binding
+                        // fn f() -> impl Iterator<Item = , Item = > {}
+                        p.error("missing associated item binding");
                     } else {
                         // test assoc_const_eq
                         // fn foo<F: Foo<N=3>>() {}
@@ -141,12 +153,17 @@ pub(super) fn const_arg_expr(p: &mut Parser<'_>) {
             expressions::literal(p);
             lm.complete(p, PREFIX_EXPR);
         }
-        _ => {
+        _ if paths::is_use_path_start(p) => {
             // This shouldn't be hit by `const_arg`
             let lm = p.start();
             paths::use_path(p);
             lm.complete(p, PATH_EXPR);
         }
+        _ => {
+            // test_err recover_from_missing_const_default
+            // struct A<const N: i32 = , const M: i32 =>;
+            p.err_recover("expected a generic const argument", GENERIC_ARG_RECOVERY_SET);
+        }
     }
 }
 
diff --git a/crates/parser/src/grammar/generic_params.rs b/crates/parser/src/grammar/generic_params.rs
index 7fcf938babd..8ed1c84c4c6 100644
--- a/crates/parser/src/grammar/generic_params.rs
+++ b/crates/parser/src/grammar/generic_params.rs
@@ -79,10 +79,9 @@ fn const_param(p: &mut Parser<'_>, m: Marker) {
         p.error("missing type for const parameter");
     }
 
-    if p.at(T![=]) {
+    if p.eat(T![=]) {
         // test const_param_default_literal
         // struct A<const N: i32 = -1>;
-        p.bump(T![=]);
 
         // test const_param_default_expression
         // struct A<const N: i32 = { 1 }>;
diff --git a/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rast b/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rast
new file mode 100644
index 00000000000..fc59db84e77
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rast
@@ -0,0 +1,48 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "f"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    RET_TYPE
+      THIN_ARROW "->"
+      WHITESPACE " "
+      IMPL_TRAIT_TYPE
+        IMPL_KW "impl"
+        WHITESPACE " "
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            PATH_TYPE
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "Iterator"
+                  GENERIC_ARG_LIST
+                    L_ANGLE "<"
+                    ASSOC_TYPE_ARG
+                      NAME_REF
+                        IDENT "Item"
+                      WHITESPACE " "
+                      EQ "="
+                    WHITESPACE " "
+                    COMMA ","
+                    WHITESPACE " "
+                    ASSOC_TYPE_ARG
+                      NAME_REF
+                        IDENT "Item"
+                      WHITESPACE " "
+                      EQ "="
+                    WHITESPACE " "
+                    R_ANGLE ">"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        R_CURLY "}"
+  WHITESPACE "\n"
+error 30: missing associated item binding
+error 39: missing associated item binding
diff --git a/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rs b/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rs
new file mode 100644
index 00000000000..e484e433a09
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rs
@@ -0,0 +1 @@
+fn f() -> impl Iterator<Item = , Item = > {}
diff --git a/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast b/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast
new file mode 100644
index 00000000000..809ad1b8d5b
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast
@@ -0,0 +1,44 @@
+SOURCE_FILE
+  STRUCT
+    STRUCT_KW "struct"
+    WHITESPACE " "
+    NAME
+      IDENT "A"
+    GENERIC_PARAM_LIST
+      L_ANGLE "<"
+      CONST_PARAM
+        CONST_KW "const"
+        WHITESPACE " "
+        NAME
+          IDENT "N"
+        COLON ":"
+        WHITESPACE " "
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "i32"
+        WHITESPACE " "
+        EQ "="
+      WHITESPACE " "
+      COMMA ","
+      WHITESPACE " "
+      CONST_PARAM
+        CONST_KW "const"
+        WHITESPACE " "
+        NAME
+          IDENT "M"
+        COLON ":"
+        WHITESPACE " "
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "i32"
+        WHITESPACE " "
+        EQ "="
+      R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 23: expected a generic const argument
+error 40: expected a generic const argument
diff --git a/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rs b/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rs
new file mode 100644
index 00000000000..5bab13da92b
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rs
@@ -0,0 +1 @@
+struct A<const N: i32 = , const M: i32 =>;