@@ -2074,7 +2074,9 @@ fn confirm_select_candidate<'cx, 'tcx>(
2074
2074
} else if lang_items. async_iterator_trait ( ) == Some ( trait_def_id) {
2075
2075
confirm_async_iterator_candidate ( selcx, obligation, data)
2076
2076
} else if selcx. tcx ( ) . fn_trait_kind_from_def_id ( trait_def_id) . is_some ( ) {
2077
- if obligation. predicate . self_ty ( ) . is_closure ( ) {
2077
+ if obligation. predicate . self_ty ( ) . is_closure ( )
2078
+ || obligation. predicate . self_ty ( ) . is_coroutine_closure ( )
2079
+ {
2078
2080
confirm_closure_candidate ( selcx, obligation, data)
2079
2081
} else {
2080
2082
confirm_fn_pointer_candidate ( selcx, obligation, data)
@@ -2386,11 +2388,71 @@ fn confirm_closure_candidate<'cx, 'tcx>(
2386
2388
obligation : & ProjectionTyObligation < ' tcx > ,
2387
2389
nested : Vec < PredicateObligation < ' tcx > > ,
2388
2390
) -> Progress < ' tcx > {
2391
+ let tcx = selcx. tcx ( ) ;
2389
2392
let self_ty = selcx. infcx . shallow_resolve ( obligation. predicate . self_ty ( ) ) ;
2390
- let ty:: Closure ( _, args) = self_ty. kind ( ) else {
2391
- unreachable ! ( "expected closure self type for closure candidate, found {self_ty}" )
2393
+ let closure_sig = match * self_ty. kind ( ) {
2394
+ ty:: Closure ( _, args) => args. as_closure ( ) . sig ( ) ,
2395
+
2396
+ // FIXME(async_closures): We can actually confirm `{coroutine-closure}: FnOnce`
2397
+ // without yet knowing the upvars. Not sure if this is beneficial, though.
2398
+ ty:: CoroutineClosure ( def_id, args) => {
2399
+ let args = args. as_coroutine_closure ( ) ;
2400
+ let kind_ty = args. kind_ty ( ) ;
2401
+ args. coroutine_closure_sig ( ) . map_bound ( |sig| {
2402
+ let output_ty = if let Some ( _) = kind_ty. to_opt_closure_kind ( ) {
2403
+ sig. to_coroutine_given_kind_and_upvars (
2404
+ tcx,
2405
+ args. parent_args ( ) ,
2406
+ tcx. coroutine_for_closure ( def_id) ,
2407
+ ty:: ClosureKind :: FnOnce ,
2408
+ tcx. lifetimes . re_static ,
2409
+ args. tupled_upvars_ty ( ) ,
2410
+ args. coroutine_captures_by_ref_ty ( ) ,
2411
+ )
2412
+ } else {
2413
+ let async_fn_kind_trait_def_id =
2414
+ tcx. require_lang_item ( LangItem :: AsyncFnKindHelper , None ) ;
2415
+ let upvars_projection_def_id = tcx
2416
+ . associated_items ( async_fn_kind_trait_def_id)
2417
+ . filter_by_name_unhygienic ( sym:: Upvars )
2418
+ . next ( )
2419
+ . unwrap ( )
2420
+ . def_id ;
2421
+ let tupled_upvars_ty = Ty :: new_projection (
2422
+ tcx,
2423
+ upvars_projection_def_id,
2424
+ [
2425
+ ty:: GenericArg :: from ( kind_ty) ,
2426
+ Ty :: from_closure_kind ( tcx, ty:: ClosureKind :: FnOnce ) . into ( ) ,
2427
+ tcx. lifetimes . re_static . into ( ) ,
2428
+ sig. tupled_inputs_ty . into ( ) ,
2429
+ args. tupled_upvars_ty ( ) . into ( ) ,
2430
+ args. coroutine_captures_by_ref_ty ( ) . into ( ) ,
2431
+ ] ,
2432
+ ) ;
2433
+ sig. to_coroutine (
2434
+ tcx,
2435
+ args. parent_args ( ) ,
2436
+ Ty :: from_closure_kind ( tcx, ty:: ClosureKind :: FnOnce ) ,
2437
+ tcx. coroutine_for_closure ( def_id) ,
2438
+ tupled_upvars_ty,
2439
+ )
2440
+ } ;
2441
+ tcx. mk_fn_sig (
2442
+ [ sig. tupled_inputs_ty ] ,
2443
+ output_ty,
2444
+ sig. c_variadic ,
2445
+ sig. unsafety ,
2446
+ sig. abi ,
2447
+ )
2448
+ } )
2449
+ }
2450
+
2451
+ _ => {
2452
+ unreachable ! ( "expected closure self type for closure candidate, found {self_ty}" ) ;
2453
+ }
2392
2454
} ;
2393
- let closure_sig = args . as_closure ( ) . sig ( ) ;
2455
+
2394
2456
let Normalized { value : closure_sig, obligations } = normalize_with_depth (
2395
2457
selcx,
2396
2458
obligation. param_env ,
0 commit comments