Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #19933 from Veykril/push-uyxorpyvnzsl
Better parser recovery for macro calls in type bound position
Lukas Wirth 11 months ago
parent ba4b9f6 · parent 5d30017 · commit d5665e5
-rw-r--r--crates/parser/src/grammar/generic_params.rs11
-rw-r--r--crates/parser/src/grammar/paths.rs2
-rw-r--r--crates/parser/src/grammar/types.rs14
-rw-r--r--crates/parser/test_data/generated/runner.rs4
-rw-r--r--crates/parser/test_data/parser/inline/err/type_bounds_macro_call_recovery.rast112
-rw-r--r--crates/parser/test_data/parser/inline/err/type_bounds_macro_call_recovery.rs1
6 files changed, 134 insertions, 10 deletions
diff --git a/crates/parser/src/grammar/generic_params.rs b/crates/parser/src/grammar/generic_params.rs
index 9d4fdbfaf2..ea5a3bc859 100644
--- a/crates/parser/src/grammar/generic_params.rs
+++ b/crates/parser/src/grammar/generic_params.rs
@@ -201,6 +201,17 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
}
if paths::is_use_path_start(p) {
types::path_type_bounds(p, false);
+ // test_err type_bounds_macro_call_recovery
+ // fn foo<T: T![], T: T!, T: T!{}>() -> Box<T! + T!{}> {}
+ if p.at(T![!]) {
+ let m = p.start();
+ p.bump(T![!]);
+ p.error("unexpected `!` in type path, macro calls are not allowed here");
+ if p.at_ts(TokenSet::new(&[T!['{'], T!['['], T!['(']])) {
+ items::token_tree(p);
+ }
+ m.complete(p, ERROR);
+ }
} else {
m.abandon(p);
return false;
diff --git a/crates/parser/src/grammar/paths.rs b/crates/parser/src/grammar/paths.rs
index e628bcc056..dfe7cb57d2 100644
--- a/crates/parser/src/grammar/paths.rs
+++ b/crates/parser/src/grammar/paths.rs
@@ -98,7 +98,7 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
types::type_(p);
if p.eat(T![as]) {
if is_use_path_start(p) {
- types::path_type(p);
+ types::path_type_bounds(p, true);
} else {
p.error("expected a trait");
}
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 9d31e435cf..908440b5d0 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -330,15 +330,6 @@ fn bare_dyn_trait_type(p: &mut Parser<'_>) {
m.complete(p, DYN_TRAIT_TYPE);
}
-// test path_type
-// type A = Foo;
-// type B = ::Foo;
-// type C = self::Foo;
-// type D = super::Foo;
-pub(super) fn path_type(p: &mut Parser<'_>) {
- path_type_bounds(p, true);
-}
-
// test macro_call_type
// type A = foo!();
// type B = crate::foo!();
@@ -365,6 +356,11 @@ fn path_or_macro_type(p: &mut Parser<'_>, allow_bounds: bool) {
}
}
+// test path_type
+// type A = Foo;
+// type B = ::Foo;
+// type C = self::Foo;
+// type D = super::Foo;
pub(super) fn path_type_bounds(p: &mut Parser<'_>, allow_bounds: bool) {
assert!(paths::is_path_start(p));
let m = p.start();
diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs
index 537f6df05b..6ec4192830 100644
--- a/crates/parser/test_data/generated/runner.rs
+++ b/crates/parser/test_data/generated/runner.rs
@@ -876,6 +876,10 @@ mod err {
run_and_expect_errors("test_data/parser/inline/err/tuple_pat_leading_comma.rs");
}
#[test]
+ fn type_bounds_macro_call_recovery() {
+ run_and_expect_errors("test_data/parser/inline/err/type_bounds_macro_call_recovery.rs");
+ }
+ #[test]
fn type_in_array_recover() {
run_and_expect_errors("test_data/parser/inline/err/type_in_array_recover.rs");
}
diff --git a/crates/parser/test_data/parser/inline/err/type_bounds_macro_call_recovery.rast b/crates/parser/test_data/parser/inline/err/type_bounds_macro_call_recovery.rast
new file mode 100644
index 0000000000..4722beb619
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/type_bounds_macro_call_recovery.rast
@@ -0,0 +1,112 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "foo"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ TYPE_PARAM
+ NAME
+ IDENT "T"
+ COLON ":"
+ WHITESPACE " "
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "T"
+ ERROR
+ BANG "!"
+ TOKEN_TREE
+ L_BRACK "["
+ R_BRACK "]"
+ COMMA ","
+ WHITESPACE " "
+ TYPE_PARAM
+ NAME
+ IDENT "T"
+ COLON ":"
+ WHITESPACE " "
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "T"
+ ERROR
+ BANG "!"
+ COMMA ","
+ WHITESPACE " "
+ TYPE_PARAM
+ NAME
+ IDENT "T"
+ COLON ":"
+ WHITESPACE " "
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "T"
+ ERROR
+ BANG "!"
+ TOKEN_TREE
+ L_CURLY "{"
+ R_CURLY "}"
+ R_ANGLE ">"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ RET_TYPE
+ THIN_ARROW "->"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Box"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ TYPE_ARG
+ DYN_TRAIT_TYPE
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ MACRO_TYPE
+ MACRO_CALL
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "T"
+ BANG "!"
+ WHITESPACE " "
+ PLUS "+"
+ WHITESPACE " "
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "T"
+ ERROR
+ BANG "!"
+ TOKEN_TREE
+ L_CURLY "{"
+ R_CURLY "}"
+ R_ANGLE ">"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ R_CURLY "}"
+ WHITESPACE "\n"
+error 12: unexpected `!` in type path, macro calls are not allowed here
+error 21: unexpected `!` in type path, macro calls are not allowed here
+error 28: unexpected `!` in type path, macro calls are not allowed here
+error 43: expected `{`, `[`, `(`
+error 48: unexpected `!` in type path, macro calls are not allowed here
diff --git a/crates/parser/test_data/parser/inline/err/type_bounds_macro_call_recovery.rs b/crates/parser/test_data/parser/inline/err/type_bounds_macro_call_recovery.rs
new file mode 100644
index 0000000000..517404fdb0
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/type_bounds_macro_call_recovery.rs
@@ -0,0 +1 @@
+fn foo<T: T![], T: T!, T: T!{}>() -> Box<T! + T!{}> {}