Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #15212 - lowr:patch/recover-from-incomplete-assoc-ty, r=HKalbasi
Recover from missing associated items and generic const defaults Fixes #15129
bors 2023-07-05
parent e219999 · parent 49b039f · commit e95644e
-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 e589b69934..211af98e6e 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 7fcf938bab..8ed1c84c4c 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 0000000000..fc59db84e7
--- /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 0000000000..e484e433a0
--- /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 0000000000..809ad1b8d5
--- /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 0000000000..5bab13da92
--- /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 =>;