@@ -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,75 @@ 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
+ // Construct a "normal" `FnOnce` signature for coroutine-closure. This is
2397
+ // basically duplicated with the `AsyncFnOnce::CallOnce` confirmation, but
2398
+ // I didn't see a good way to unify those.
2399
+ ty:: CoroutineClosure ( def_id, args) => {
2400
+ let args = args. as_coroutine_closure ( ) ;
2401
+ let kind_ty = args. kind_ty ( ) ;
2402
+ args. coroutine_closure_sig ( ) . map_bound ( |sig| {
2403
+ // If we know the kind and upvars, use that directly.
2404
+ // Otherwise, defer to `AsyncFnKindHelper::Upvars` to delay
2405
+ // the projection, like the `AsyncFn*` traits do.
2406
+ let output_ty = if let Some ( _) = kind_ty. to_opt_closure_kind ( ) {
2407
+ sig. to_coroutine_given_kind_and_upvars (
2408
+ tcx,
2409
+ args. parent_args ( ) ,
2410
+ tcx. coroutine_for_closure ( def_id) ,
2411
+ ty:: ClosureKind :: FnOnce ,
2412
+ tcx. lifetimes . re_static ,
2413
+ args. tupled_upvars_ty ( ) ,
2414
+ args. coroutine_captures_by_ref_ty ( ) ,
2415
+ )
2416
+ } else {
2417
+ let async_fn_kind_trait_def_id =
2418
+ tcx. require_lang_item ( LangItem :: AsyncFnKindHelper , None ) ;
2419
+ let upvars_projection_def_id = tcx
2420
+ . associated_items ( async_fn_kind_trait_def_id)
2421
+ . filter_by_name_unhygienic ( sym:: Upvars )
2422
+ . next ( )
2423
+ . unwrap ( )
2424
+ . def_id ;
2425
+ let tupled_upvars_ty = Ty :: new_projection (
2426
+ tcx,
2427
+ upvars_projection_def_id,
2428
+ [
2429
+ ty:: GenericArg :: from ( kind_ty) ,
2430
+ Ty :: from_closure_kind ( tcx, ty:: ClosureKind :: FnOnce ) . into ( ) ,
2431
+ tcx. lifetimes . re_static . into ( ) ,
2432
+ sig. tupled_inputs_ty . into ( ) ,
2433
+ args. tupled_upvars_ty ( ) . into ( ) ,
2434
+ args. coroutine_captures_by_ref_ty ( ) . into ( ) ,
2435
+ ] ,
2436
+ ) ;
2437
+ sig. to_coroutine (
2438
+ tcx,
2439
+ args. parent_args ( ) ,
2440
+ Ty :: from_closure_kind ( tcx, ty:: ClosureKind :: FnOnce ) ,
2441
+ tcx. coroutine_for_closure ( def_id) ,
2442
+ tupled_upvars_ty,
2443
+ )
2444
+ } ;
2445
+ tcx. mk_fn_sig (
2446
+ [ sig. tupled_inputs_ty ] ,
2447
+ output_ty,
2448
+ sig. c_variadic ,
2449
+ sig. unsafety ,
2450
+ sig. abi ,
2451
+ )
2452
+ } )
2453
+ }
2454
+
2455
+ _ => {
2456
+ unreachable ! ( "expected closure self type for closure candidate, found {self_ty}" ) ;
2457
+ }
2392
2458
} ;
2393
- let closure_sig = args . as_closure ( ) . sig ( ) ;
2459
+
2394
2460
let Normalized { value : closure_sig, obligations } = normalize_with_depth (
2395
2461
selcx,
2396
2462
obligation. param_env ,
0 commit comments