Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #20934 from Veykril/veykril/push-qtzmsqkzntpo
fix: Improve error recovery when parsing malformed function return types
Lukas Wirth 6 months ago
parent d08d54f · parent 47c5af2 · commit 769ebaf
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs6
-rw-r--r--crates/parser/src/grammar/items.rs8
-rw-r--r--crates/parser/test_data/generated/runner.rs8
-rw-r--r--crates/parser/test_data/parser/inline/err/closure_ret_recovery.rast52
-rw-r--r--crates/parser/test_data/parser/inline/err/closure_ret_recovery.rs1
-rw-r--r--crates/parser/test_data/parser/inline/err/fn_ret_recovery.rast112
-rw-r--r--crates/parser/test_data/parser/inline/err/fn_ret_recovery.rs2
7 files changed, 189 insertions, 0 deletions
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index ed8a91c39c..cde62e0323 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -588,6 +588,12 @@ fn closure_expr(p: &mut Parser<'_>) -> CompletedMarker {
}
params::param_list_closure(p);
if opt_ret_type(p) {
+ // test_err closure_ret_recovery
+ // fn foo() { || -> A> { let x = 1; } }
+ while p.at(T![>]) {
+ // recover from unbalanced return type brackets
+ p.err_and_bump("expected a curly brace");
+ }
// test lambda_ret_block
// fn main() { || -> i32 { 92 }(); }
block_expr(p);
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index 8e551b0b96..c609f9383e 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -424,6 +424,14 @@ fn fn_(p: &mut Parser<'_>, m: Marker) {
// fn bar() -> () {}
opt_ret_type(p);
+ // test_err fn_ret_recovery
+ // fn foo() -> A>]) { let x = 1; }
+ // fn foo() -> A>]) where T: Copy { let x = 1; }
+ while p.at(T![')']) | p.at(T![']']) | p.at(T![>]) {
+ // recover from unbalanced return type brackets
+ p.err_and_bump("expected a curly brace");
+ }
+
// test function_where_clause
// fn foo<T>() where T: Copy {}
generic_params::opt_where_clause(p);
diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs
index 9bdbe56330..c56eb5090c 100644
--- a/crates/parser/test_data/generated/runner.rs
+++ b/crates/parser/test_data/generated/runner.rs
@@ -749,6 +749,10 @@ mod err {
#[test]
fn bad_asm_expr() { run_and_expect_errors("test_data/parser/inline/err/bad_asm_expr.rs"); }
#[test]
+ fn closure_ret_recovery() {
+ run_and_expect_errors("test_data/parser/inline/err/closure_ret_recovery.rs");
+ }
+ #[test]
fn comma_after_default_values_syntax() {
run_and_expect_errors("test_data/parser/inline/err/comma_after_default_values_syntax.rs");
}
@@ -773,6 +777,10 @@ mod err {
run_and_expect_errors("test_data/parser/inline/err/fn_pointer_type_missing_fn.rs");
}
#[test]
+ fn fn_ret_recovery() {
+ run_and_expect_errors("test_data/parser/inline/err/fn_ret_recovery.rs");
+ }
+ #[test]
fn gen_fn() {
run_and_expect_errors_with_edition(
"test_data/parser/inline/err/gen_fn.rs",
diff --git a/crates/parser/test_data/parser/inline/err/closure_ret_recovery.rast b/crates/parser/test_data/parser/inline/err/closure_ret_recovery.rast
new file mode 100644
index 0000000000..f6266510bb
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/closure_ret_recovery.rast
@@ -0,0 +1,52 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "foo"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ CLOSURE_EXPR
+ PARAM_LIST
+ PIPE "|"
+ PIPE "|"
+ WHITESPACE " "
+ RET_TYPE
+ THIN_ARROW "->"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "A"
+ ERROR
+ R_ANGLE ">"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ LET_STMT
+ LET_KW "let"
+ WHITESPACE " "
+ IDENT_PAT
+ NAME
+ IDENT "x"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "1"
+ SEMICOLON ";"
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE "\n"
+error 18: expected a curly brace
diff --git a/crates/parser/test_data/parser/inline/err/closure_ret_recovery.rs b/crates/parser/test_data/parser/inline/err/closure_ret_recovery.rs
new file mode 100644
index 0000000000..7a758ec076
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/closure_ret_recovery.rs
@@ -0,0 +1 @@
+fn foo() { || -> A> { let x = 1; } }
diff --git a/crates/parser/test_data/parser/inline/err/fn_ret_recovery.rast b/crates/parser/test_data/parser/inline/err/fn_ret_recovery.rast
new file mode 100644
index 0000000000..0323df8bf0
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/fn_ret_recovery.rast
@@ -0,0 +1,112 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "foo"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ RET_TYPE
+ THIN_ARROW "->"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "A"
+ ERROR
+ R_ANGLE ">"
+ ERROR
+ R_BRACK "]"
+ ERROR
+ R_PAREN ")"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ LET_STMT
+ LET_KW "let"
+ WHITESPACE " "
+ IDENT_PAT
+ NAME
+ IDENT "x"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "1"
+ SEMICOLON ";"
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE "\n"
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "foo"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ RET_TYPE
+ THIN_ARROW "->"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "A"
+ ERROR
+ R_ANGLE ">"
+ ERROR
+ R_BRACK "]"
+ ERROR
+ R_PAREN ")"
+ WHITESPACE " "
+ WHERE_CLAUSE
+ WHERE_KW "where"
+ WHITESPACE " "
+ WHERE_PRED
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "T"
+ COLON ":"
+ WHITESPACE " "
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Copy"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ LET_STMT
+ LET_KW "let"
+ WHITESPACE " "
+ IDENT_PAT
+ NAME
+ IDENT "x"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "1"
+ SEMICOLON ";"
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE "\n"
+error 13: expected a curly brace
+error 14: expected a curly brace
+error 15: expected a curly brace
+error 45: expected a curly brace
+error 46: expected a curly brace
+error 47: expected a curly brace
diff --git a/crates/parser/test_data/parser/inline/err/fn_ret_recovery.rs b/crates/parser/test_data/parser/inline/err/fn_ret_recovery.rs
new file mode 100644
index 0000000000..73e3d84d74
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/fn_ret_recovery.rs
@@ -0,0 +1,2 @@
+fn foo() -> A>]) { let x = 1; }
+fn foo() -> A>]) where T: Copy { let x = 1; }