about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-07-17 19:41:42 +0000
committerGitHub <noreply@github.com>2021-07-17 19:41:42 +0000
commit398ae3e67ffedda98fbb7be668349fbbb7cdb8a4 (patch)
tree5c76918016fbc426279275f9705478b8ce3a5830
parent610ecc9a7e8b7b464af575321b7f5d5261342afd (diff)
parent15f11dce4ab52ef41e7ffb2e5c1328f918962344 (diff)
downloadrust-398ae3e67ffedda98fbb7be668349fbbb7cdb8a4.tar.gz
rust-398ae3e67ffedda98fbb7be668349fbbb7cdb8a4.zip
Merge #9622
9622: feat: improve parser error recovery for function parameters r=matklad a=matklad

bors r+
🤖

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
-rw-r--r--crates/ide_completion/src/completions/fn_param.rs14
-rw-r--r--crates/parser/src/grammar/items/consts.rs7
-rw-r--r--crates/parser/src/grammar/params.rs14
-rw-r--r--crates/parser/src/grammar/type_params.rs6
-rw-r--r--crates/parser/src/grammar/types.rs3
-rw-r--r--crates/syntax/test_data/parser/err/0018_incomplete_fn.rast3
-rw-r--r--crates/syntax/test_data/parser/err/0021_incomplete_param.rast3
-rw-r--r--crates/syntax/test_data/parser/err/0045_item_modifiers.rast24
-rw-r--r--crates/syntax/test_data/parser/inline/err/0015_missing_fn_param_type.rast52
-rw-r--r--crates/syntax/test_data/parser/inline/err/0015_missing_fn_param_type.rs1
10 files changed, 106 insertions, 21 deletions
diff --git a/crates/ide_completion/src/completions/fn_param.rs b/crates/ide_completion/src/completions/fn_param.rs
index 7805da24abd..d299f2e2634 100644
--- a/crates/ide_completion/src/completions/fn_param.rs
+++ b/crates/ide_completion/src/completions/fn_param.rs
@@ -102,6 +102,20 @@ fn baz(file$0) {}
     }
 
     #[test]
+    fn test_param_completion_first_param() {
+        check(
+            r#"
+fn foo(file_id: FileId) {}
+fn bar(file_id: FileId) {}
+fn baz(file$0 id: u32) {}
+"#,
+            expect![[r#"
+                bn file_id: FileId
+            "#]],
+        );
+    }
+
+    #[test]
     fn test_param_completion_nth_param() {
         check(
             r#"
diff --git a/crates/parser/src/grammar/items/consts.rs b/crates/parser/src/grammar/items/consts.rs
index ed3bee4a468..1b317dd84a9 100644
--- a/crates/parser/src/grammar/items/consts.rs
+++ b/crates/parser/src/grammar/items/consts.rs
@@ -21,8 +21,11 @@ fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
 
     // test_err static_underscore
     // static _: i32 = 5;
-
-    types::ascription(p);
+    if p.at(T![:]) {
+        types::ascription(p);
+    } else {
+        p.error("missing type for `const` or `static`")
+    }
     if p.eat(T![=]) {
         expressions::expr(p);
     }
diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs
index 5a78675fb4f..8f028c61941 100644
--- a/crates/parser/src/grammar/params.rs
+++ b/crates/parser/src/grammar/params.rs
@@ -106,7 +106,13 @@ fn param(p: &mut Parser, m: Marker, flavor: Flavor) -> Variadic {
             if variadic_param(p) {
                 res = Variadic(true)
             } else {
-                types::ascription(p);
+                if p.at(T![:]) {
+                    types::ascription(p)
+                } else {
+                    // test_err missing_fn_param_type
+                    // fn f(x y: i32, z, t: i32) {}
+                    p.error("missing type for function parameter")
+                }
             }
         }
         // test value_parameters_no_patterns
@@ -126,7 +132,11 @@ fn param(p: &mut Parser, m: Marker, flavor: Flavor) -> Variadic {
                 if variadic_param(p) {
                     res = Variadic(true)
                 } else {
-                    types::ascription(p);
+                    if p.at(T![:]) {
+                        types::ascription(p)
+                    } else {
+                        p.error("missing type for function parameter")
+                    }
                 }
             } else {
                 types::type_(p);
diff --git a/crates/parser/src/grammar/type_params.rs b/crates/parser/src/grammar/type_params.rs
index 49d6fa6d0b6..a7a0109fd1b 100644
--- a/crates/parser/src/grammar/type_params.rs
+++ b/crates/parser/src/grammar/type_params.rs
@@ -67,7 +67,11 @@ fn const_param(p: &mut Parser, m: Marker) {
     assert!(p.at(T![const]));
     p.bump(T![const]);
     name(p);
-    types::ascription(p);
+    if p.at(T![:]) {
+        types::ascription(p);
+    } else {
+        p.error("missing type for const parameter");
+    }
 
     // test const_param_defaults
     // struct A<const N: i32 = -1>;
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 72476c19070..e0b3c1bf0cb 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -55,7 +55,8 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
 }
 
 pub(super) fn ascription(p: &mut Parser) {
-    p.expect(T![:]);
+    assert!(p.at(T![:]));
+    p.bump(T![:]);
     type_(p)
 }
 
diff --git a/crates/syntax/test_data/parser/err/0018_incomplete_fn.rast b/crates/syntax/test_data/parser/err/0018_incomplete_fn.rast
index 060f47dc440..5b180ce3375 100644
--- a/crates/syntax/test_data/parser/err/0018_incomplete_fn.rast
+++ b/crates/syntax/test_data/parser/err/0018_incomplete_fn.rast
@@ -127,7 +127,6 @@ SOURCE_FILE@0..183
       R_CURLY@181..182 "}"
   WHITESPACE@182..183 "\n"
 error 34..34: expected pattern
-error 34..34: expected COLON
-error 34..34: expected type
+error 34..34: missing type for function parameter
 error 180..180: expected function arguments
 error 180..180: expected a block
diff --git a/crates/syntax/test_data/parser/err/0021_incomplete_param.rast b/crates/syntax/test_data/parser/err/0021_incomplete_param.rast
index b3284553770..901490fa2fe 100644
--- a/crates/syntax/test_data/parser/err/0021_incomplete_param.rast
+++ b/crates/syntax/test_data/parser/err/0021_incomplete_param.rast
@@ -30,5 +30,4 @@ SOURCE_FILE@0..22
       WHITESPACE@19..20 "\n"
       R_CURLY@20..21 "}"
   WHITESPACE@21..22 "\n"
-error 16..16: expected COLON
-error 16..16: expected type
+error 16..16: missing type for function parameter
diff --git a/crates/syntax/test_data/parser/err/0045_item_modifiers.rast b/crates/syntax/test_data/parser/err/0045_item_modifiers.rast
index a6e6552a99e..e9dad0b7a03 100644
--- a/crates/syntax/test_data/parser/err/0045_item_modifiers.rast
+++ b/crates/syntax/test_data/parser/err/0045_item_modifiers.rast
@@ -17,22 +17,22 @@ SOURCE_FILE@0..50
       L_CURLY@22..23 "{"
       R_CURLY@23..24 "}"
   WHITESPACE@24..25 "\n"
-  CONST@25..46
+  CONST@25..40
     UNSAFE_KW@25..31 "unsafe"
     WHITESPACE@31..32 " "
     CONST_KW@32..37 "const"
     WHITESPACE@37..38 " "
     ERROR@38..40
       FN_KW@38..40 "fn"
-    WHITESPACE@40..41 " "
-    PATH_TYPE@41..46
-      PATH@41..46
-        PATH_SEGMENT@41..46
-          NAME_REF@41..44
-            IDENT@41..44 "bar"
-          PARAM_LIST@44..46
-            L_PAREN@44..45 "("
-            R_PAREN@45..46 ")"
+  WHITESPACE@40..41 " "
+  MACRO_CALL@41..46
+    PATH@41..44
+      PATH_SEGMENT@41..44
+        NAME_REF@41..44
+          IDENT@41..44 "bar"
+    TOKEN_TREE@44..46
+      L_PAREN@44..45 "("
+      R_PAREN@45..46 ")"
   WHITESPACE@46..47 " "
   ERROR@47..49
     L_CURLY@47..48 "{"
@@ -40,6 +40,8 @@ SOURCE_FILE@0..50
   WHITESPACE@49..50 "\n"
 error 6..6: expected existential, fn, trait or impl
 error 38..38: expected a name
-error 40..40: expected COLON
+error 40..40: missing type for `const` or `static`
+error 40..40: expected SEMICOLON
+error 44..44: expected BANG
 error 46..46: expected SEMICOLON
 error 47..47: expected an item
diff --git a/crates/syntax/test_data/parser/inline/err/0015_missing_fn_param_type.rast b/crates/syntax/test_data/parser/inline/err/0015_missing_fn_param_type.rast
new file mode 100644
index 00000000000..99391c266ab
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0015_missing_fn_param_type.rast
@@ -0,0 +1,52 @@
+SOURCE_FILE@0..29
+  FN@0..28
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    PARAM_LIST@4..25
+      L_PAREN@4..5 "("
+      PARAM@5..6
+        IDENT_PAT@5..6
+          NAME@5..6
+            IDENT@5..6 "x"
+      WHITESPACE@6..7 " "
+      PARAM@7..13
+        IDENT_PAT@7..8
+          NAME@7..8
+            IDENT@7..8 "y"
+        COLON@8..9 ":"
+        WHITESPACE@9..10 " "
+        PATH_TYPE@10..13
+          PATH@10..13
+            PATH_SEGMENT@10..13
+              NAME_REF@10..13
+                IDENT@10..13 "i32"
+      COMMA@13..14 ","
+      WHITESPACE@14..15 " "
+      PARAM@15..16
+        IDENT_PAT@15..16
+          NAME@15..16
+            IDENT@15..16 "z"
+      COMMA@16..17 ","
+      WHITESPACE@17..18 " "
+      PARAM@18..24
+        IDENT_PAT@18..19
+          NAME@18..19
+            IDENT@18..19 "t"
+        COLON@19..20 ":"
+        WHITESPACE@20..21 " "
+        PATH_TYPE@21..24
+          PATH@21..24
+            PATH_SEGMENT@21..24
+              NAME_REF@21..24
+                IDENT@21..24 "i32"
+      R_PAREN@24..25 ")"
+    WHITESPACE@25..26 " "
+    BLOCK_EXPR@26..28
+      L_CURLY@26..27 "{"
+      R_CURLY@27..28 "}"
+  WHITESPACE@28..29 "\n"
+error 6..6: missing type for function parameter
+error 6..6: expected COMMA
+error 16..16: missing type for function parameter
diff --git a/crates/syntax/test_data/parser/inline/err/0015_missing_fn_param_type.rs b/crates/syntax/test_data/parser/inline/err/0015_missing_fn_param_type.rs
new file mode 100644
index 00000000000..4a95b908435
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0015_missing_fn_param_type.rs
@@ -0,0 +1 @@
+fn f(x y: i32, z, t: i32) {}