@@ -32,6 +32,9 @@ const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
32
32
] )
33
33
. union ( types:: TYPE_FIRST ) ;
34
34
35
+ // Despite its name, it can also be used for generic param list.
36
+ const GENERIC_ARG_RECOVERY_SET : TokenSet = TokenSet :: new ( & [ T ! [ >] , T ! [ , ] ] ) ;
37
+
35
38
// test generic_arg
36
39
// type T = S<i32>;
37
40
fn generic_arg ( p : & mut Parser < ' _ > ) -> bool {
@@ -55,6 +58,15 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
55
58
// test assoc_type_eq
56
59
// type T = StreamingIterator<Item<'a> = &'a T>;
57
60
types:: type_ ( p) ;
61
+ } else if p. at_ts ( GENERIC_ARG_RECOVERY_SET ) {
62
+ // Although `const_arg()` recovers as expected, we want to
63
+ // handle those here to give the following message because
64
+ // we don't know whether this associated item is a type or
65
+ // const at this point.
66
+
67
+ // test_err recover_from_missing_assoc_item_binding
68
+ // fn f() -> impl Iterator<Item = , Item = > {}
69
+ p. error ( "missing associated item binding" ) ;
58
70
} else {
59
71
// test assoc_const_eq
60
72
// fn foo<F: Foo<N=3>>() {}
@@ -141,12 +153,17 @@ pub(super) fn const_arg_expr(p: &mut Parser<'_>) {
141
153
expressions:: literal ( p) ;
142
154
lm. complete ( p, PREFIX_EXPR ) ;
143
155
}
144
- _ => {
156
+ _ if paths :: is_use_path_start ( p ) => {
145
157
// This shouldn't be hit by `const_arg`
146
158
let lm = p. start ( ) ;
147
159
paths:: use_path ( p) ;
148
160
lm. complete ( p, PATH_EXPR ) ;
149
161
}
162
+ _ => {
163
+ // test_err recover_from_missing_const_default
164
+ // struct A<const N: i32 = , const M: i32 =>;
165
+ p. err_recover ( "expected a generic const argument" , GENERIC_ARG_RECOVERY_SET ) ;
166
+ }
150
167
}
151
168
}
152
169
0 commit comments