Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #20886 from A4-Tacks/parse-missing-method-name
Improve parsing of missing name in MethodCallExpr
Lukas Wirth 6 months ago
parent 9d8fa5d · parent 891391a · commit cb09f24
-rw-r--r--crates/parser/src/grammar/expressions.rs23
-rw-r--r--crates/parser/test_data/generated/runner.rs4
-rw-r--r--crates/parser/test_data/parser/inline/err/postfix_dot_expr_ambiguity.rast29
-rw-r--r--crates/parser/test_data/parser/inline/err/postfix_dot_expr_ambiguity.rs4
4 files changed, 55 insertions, 5 deletions
diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs
index 41fd72d8d5..76d26c1ecd 100644
--- a/crates/parser/src/grammar/expressions.rs
+++ b/crates/parser/src/grammar/expressions.rs
@@ -430,6 +430,11 @@ fn postfix_expr(
// }
T!['('] if allow_calls => call_expr(p, lhs),
T!['['] if allow_calls => index_expr(p, lhs),
+ // test_err postfix_dot_expr_ambiguity
+ // fn foo() {
+ // x.
+ // ()
+ // }
T![.] => match postfix_dot_expr::<false>(p, lhs) {
Ok(it) => it,
Err(it) => {
@@ -458,6 +463,7 @@ fn postfix_dot_expr<const FLOAT_RECOVERY: bool>(
if PATH_NAME_REF_KINDS.contains(p.nth(nth1))
&& (p.nth(nth2) == T!['('] || p.nth_at(nth2, T![::]))
+ || p.nth(nth1) == T!['(']
{
return Ok(method_call_expr::<FLOAT_RECOVERY>(p, lhs));
}
@@ -526,19 +532,26 @@ fn method_call_expr<const FLOAT_RECOVERY: bool>(
lhs: CompletedMarker,
) -> CompletedMarker {
if FLOAT_RECOVERY {
- assert!(p.at_ts(PATH_NAME_REF_KINDS) && (p.nth(1) == T!['('] || p.nth_at(1, T![::])));
+ assert!(
+ p.at_ts(PATH_NAME_REF_KINDS) && (p.nth(1) == T!['('] || p.nth_at(1, T![::]))
+ || p.current() == T!['(']
+ );
} else {
+ assert!(p.at(T![.]));
assert!(
- p.at(T![.])
- && PATH_NAME_REF_KINDS.contains(p.nth(1))
- && (p.nth(2) == T!['('] || p.nth_at(2, T![::]))
+ PATH_NAME_REF_KINDS.contains(p.nth(1)) && (p.nth(2) == T!['('] || p.nth_at(2, T![::]))
+ || p.nth(1) == T!['(']
);
}
let m = lhs.precede(p);
if !FLOAT_RECOVERY {
p.bump(T![.]);
}
- name_ref_mod_path(p);
+ if p.at_ts(PATH_NAME_REF_KINDS) {
+ name_ref_mod_path(p);
+ } else {
+ p.error("expected method name, field name or number");
+ }
generic_args::opt_generic_arg_list_expr(p);
if p.at(T!['(']) {
arg_list(p);
diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs
index cd6d433d0e..9bdbe56330 100644
--- a/crates/parser/test_data/generated/runner.rs
+++ b/crates/parser/test_data/generated/runner.rs
@@ -844,6 +844,10 @@ mod err {
run_and_expect_errors("test_data/parser/inline/err/pointer_type_no_mutability.rs");
}
#[test]
+ fn postfix_dot_expr_ambiguity() {
+ run_and_expect_errors("test_data/parser/inline/err/postfix_dot_expr_ambiguity.rs");
+ }
+ #[test]
fn precise_capturing_invalid() {
run_and_expect_errors("test_data/parser/inline/err/precise_capturing_invalid.rs");
}
diff --git a/crates/parser/test_data/parser/inline/err/postfix_dot_expr_ambiguity.rast b/crates/parser/test_data/parser/inline/err/postfix_dot_expr_ambiguity.rast
new file mode 100644
index 0000000000..4ee318de25
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/postfix_dot_expr_ambiguity.rast
@@ -0,0 +1,29 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "foo"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ METHOD_CALL_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "x"
+ DOT "."
+ WHITESPACE "\n "
+ ARG_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE "\n"
+ R_CURLY "}"
+ WHITESPACE "\n"
+error 17: expected method name, field name or number
diff --git a/crates/parser/test_data/parser/inline/err/postfix_dot_expr_ambiguity.rs b/crates/parser/test_data/parser/inline/err/postfix_dot_expr_ambiguity.rs
new file mode 100644
index 0000000000..c1aed30342
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/postfix_dot_expr_ambiguity.rs
@@ -0,0 +1,4 @@
+fn foo() {
+ x.
+ ()
+}