@@ -13,7 +13,7 @@ pub(super) fn opt_generic_param_list(p: &mut Parser<'_>) {
1313
1414// test_err generic_param_list_recover
1515// fn f<T: Clone,, U:, V>() {}
16- fn generic_param_list ( p : & mut Parser < ' _ > ) {
16+ pub ( super ) fn generic_param_list ( p : & mut Parser < ' _ > ) {
1717 assert ! ( p. at( T ![ <] ) ) ;
1818 let m = p. start ( ) ;
1919 delimited (
@@ -147,7 +147,15 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
147147 let has_paren = p. eat ( T ! [ '(' ] ) ;
148148 match p. current ( ) {
149149 LIFETIME_IDENT => lifetime ( p) ,
150- T ! [ for ] => types:: for_type ( p, false ) ,
150+ // test for_binder_bound
151+ // fn foo<T: for<'a> [const] async Trait>() {}
152+ T ! [ for ] => {
153+ types:: for_binder ( p) ;
154+ if path_type_bound ( p) . is_err ( ) {
155+ m. abandon ( p) ;
156+ return false ;
157+ }
158+ }
151159 // test precise_capturing
152160 // fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T, Self> {}
153161
@@ -180,44 +188,8 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
180188 p. bump_any ( ) ;
181189 types:: for_type ( p, false )
182190 }
183- current => {
184- match current {
185- T ! [ ?] => p. bump_any ( ) ,
186- T ! [ ~] => {
187- p. bump_any ( ) ;
188- p. expect ( T ! [ const ] ) ;
189- }
190- T ! [ '[' ] => {
191- p. bump_any ( ) ;
192- p. expect ( T ! [ const ] ) ;
193- p. expect ( T ! [ ']' ] ) ;
194- }
195- // test const_trait_bound
196- // const fn foo(_: impl const Trait) {}
197- T ! [ const ] => {
198- p. bump_any ( ) ;
199- }
200- // test async_trait_bound
201- // fn async_foo(_: impl async Fn(&i32)) {}
202- T ! [ async ] => {
203- p. bump_any ( ) ;
204- }
205- _ => ( ) ,
206- }
207- if paths:: is_use_path_start ( p) {
208- types:: path_type_bounds ( p, false ) ;
209- // test_err type_bounds_macro_call_recovery
210- // fn foo<T: T![], T: T!, T: T!{}>() -> Box<T! + T!{}> {}
211- if p. at ( T ! [ !] ) {
212- let m = p. start ( ) ;
213- p. bump ( T ! [ !] ) ;
214- p. error ( "unexpected `!` in type path, macro calls are not allowed here" ) ;
215- if p. at_ts ( TokenSet :: new ( & [ T ! [ '{' ] , T ! [ '[' ] , T ! [ '(' ] ] ) ) {
216- items:: token_tree ( p) ;
217- }
218- m. complete ( p, ERROR ) ;
219- }
220- } else {
191+ _ => {
192+ if path_type_bound ( p) . is_err ( ) {
221193 m. abandon ( p) ;
222194 return false ;
223195 }
@@ -231,6 +203,43 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
231203 true
232204}
233205
206+ fn path_type_bound ( p : & mut Parser < ' _ > ) -> Result < ( ) , ( ) > {
207+ if p. eat ( T ! [ ~] ) {
208+ p. expect ( T ! [ const ] ) ;
209+ } else if p. eat ( T ! [ '[' ] ) {
210+ // test maybe_const_trait_bound
211+ // const fn foo(_: impl [const] Trait) {}
212+ p. expect ( T ! [ const ] ) ;
213+ p. expect ( T ! [ ']' ] ) ;
214+ } else {
215+ // test const_trait_bound
216+ // const fn foo(_: impl const Trait) {}
217+ p. eat ( T ! [ const ] ) ;
218+ }
219+ // test async_trait_bound
220+ // fn async_foo(_: impl async Fn(&i32)) {}
221+ p. eat ( T ! [ async ] ) ;
222+ p. eat ( T ! [ ?] ) ;
223+
224+ if paths:: is_use_path_start ( p) {
225+ types:: path_type_bounds ( p, false ) ;
226+ // test_err type_bounds_macro_call_recovery
227+ // fn foo<T: T![], T: T!, T: T!{}>() -> Box<T! + T!{}> {}
228+ if p. at ( T ! [ !] ) {
229+ let m = p. start ( ) ;
230+ p. bump ( T ! [ !] ) ;
231+ p. error ( "unexpected `!` in type path, macro calls are not allowed here" ) ;
232+ if p. at_ts ( TokenSet :: new ( & [ T ! [ '{' ] , T ! [ '[' ] , T ! [ '(' ] ] ) ) {
233+ items:: token_tree ( p) ;
234+ }
235+ m. complete ( p, ERROR ) ;
236+ }
237+ Ok ( ( ) )
238+ } else {
239+ Err ( ( ) )
240+ }
241+ }
242+
234243// test where_clause
235244// fn foo()
236245// where
0 commit comments