@@ -2450,99 +2450,170 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
2450
2450
) -> Progress < ' tcx > {
2451
2451
let tcx = selcx. tcx ( ) ;
2452
2452
let self_ty = selcx. infcx . shallow_resolve ( obligation. predicate . self_ty ( ) ) ;
2453
- let ty:: CoroutineClosure ( def_id, args) = * self_ty. kind ( ) else {
2454
- unreachable ! (
2455
- "expected coroutine-closure self type for coroutine-closure candidate, found {self_ty}"
2456
- )
2457
- } ;
2458
- let args = args. as_coroutine_closure ( ) ;
2459
- let kind_ty = args. kind_ty ( ) ;
2460
- let sig = args. coroutine_closure_sig ( ) . skip_binder ( ) ;
2461
2453
2462
2454
let goal_kind =
2463
2455
tcx. async_fn_trait_kind_from_def_id ( obligation. predicate . trait_def_id ( tcx) ) . unwrap ( ) ;
2464
2456
let env_region = match goal_kind {
2465
2457
ty:: ClosureKind :: Fn | ty:: ClosureKind :: FnMut => obligation. predicate . args . region_at ( 2 ) ,
2466
2458
ty:: ClosureKind :: FnOnce => tcx. lifetimes . re_static ,
2467
2459
} ;
2468
-
2469
2460
let item_name = tcx. item_name ( obligation. predicate . def_id ) ;
2470
- let term = match item_name {
2471
- sym:: CallOnceFuture | sym:: CallMutFuture | sym:: CallFuture => {
2472
- if let Some ( closure_kind) = kind_ty. to_opt_closure_kind ( ) {
2473
- if !closure_kind. extends ( goal_kind) {
2474
- bug ! ( "we should not be confirming if the closure kind is not met" ) ;
2461
+
2462
+ let poly_cache_entry = match * self_ty. kind ( ) {
2463
+ ty:: CoroutineClosure ( def_id, args) => {
2464
+ let args = args. as_coroutine_closure ( ) ;
2465
+ let kind_ty = args. kind_ty ( ) ;
2466
+ let sig = args. coroutine_closure_sig ( ) . skip_binder ( ) ;
2467
+
2468
+ let term = match item_name {
2469
+ sym:: CallOnceFuture | sym:: CallMutFuture | sym:: CallFuture => {
2470
+ if let Some ( closure_kind) = kind_ty. to_opt_closure_kind ( ) {
2471
+ if !closure_kind. extends ( goal_kind) {
2472
+ bug ! ( "we should not be confirming if the closure kind is not met" ) ;
2473
+ }
2474
+ sig. to_coroutine_given_kind_and_upvars (
2475
+ tcx,
2476
+ args. parent_args ( ) ,
2477
+ tcx. coroutine_for_closure ( def_id) ,
2478
+ goal_kind,
2479
+ env_region,
2480
+ args. tupled_upvars_ty ( ) ,
2481
+ args. coroutine_captures_by_ref_ty ( ) ,
2482
+ )
2483
+ } else {
2484
+ let async_fn_kind_trait_def_id =
2485
+ tcx. require_lang_item ( LangItem :: AsyncFnKindHelper , None ) ;
2486
+ let upvars_projection_def_id = tcx
2487
+ . associated_items ( async_fn_kind_trait_def_id)
2488
+ . filter_by_name_unhygienic ( sym:: Upvars )
2489
+ . next ( )
2490
+ . unwrap ( )
2491
+ . def_id ;
2492
+ // When we don't know the closure kind (and therefore also the closure's upvars,
2493
+ // which are computed at the same time), we must delay the computation of the
2494
+ // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
2495
+ // goal functions similarly to the old `ClosureKind` predicate, and ensures that
2496
+ // the goal kind <= the closure kind. As a projection `AsyncFnKindHelper::Upvars`
2497
+ // will project to the right upvars for the generator, appending the inputs and
2498
+ // coroutine upvars respecting the closure kind.
2499
+ // N.B. No need to register a `AsyncFnKindHelper` goal here, it's already in `nested`.
2500
+ let tupled_upvars_ty = Ty :: new_projection (
2501
+ tcx,
2502
+ upvars_projection_def_id,
2503
+ [
2504
+ ty:: GenericArg :: from ( kind_ty) ,
2505
+ Ty :: from_closure_kind ( tcx, goal_kind) . into ( ) ,
2506
+ env_region. into ( ) ,
2507
+ sig. tupled_inputs_ty . into ( ) ,
2508
+ args. tupled_upvars_ty ( ) . into ( ) ,
2509
+ args. coroutine_captures_by_ref_ty ( ) . into ( ) ,
2510
+ ] ,
2511
+ ) ;
2512
+ sig. to_coroutine (
2513
+ tcx,
2514
+ args. parent_args ( ) ,
2515
+ Ty :: from_closure_kind ( tcx, goal_kind) ,
2516
+ tcx. coroutine_for_closure ( def_id) ,
2517
+ tupled_upvars_ty,
2518
+ )
2519
+ }
2475
2520
}
2476
- sig. to_coroutine_given_kind_and_upvars (
2521
+ sym:: Output => sig. return_ty ,
2522
+ name => bug ! ( "no such associated type: {name}" ) ,
2523
+ } ;
2524
+ let projection_ty = match item_name {
2525
+ sym:: CallOnceFuture | sym:: Output => ty:: AliasTy :: new (
2477
2526
tcx,
2478
- args. parent_args ( ) ,
2479
- tcx. coroutine_for_closure ( def_id) ,
2480
- goal_kind,
2481
- env_region,
2482
- args. tupled_upvars_ty ( ) ,
2483
- args. coroutine_captures_by_ref_ty ( ) ,
2484
- )
2485
- } else {
2486
- let async_fn_kind_trait_def_id =
2487
- tcx. require_lang_item ( LangItem :: AsyncFnKindHelper , None ) ;
2488
- let upvars_projection_def_id = tcx
2489
- . associated_items ( async_fn_kind_trait_def_id)
2490
- . filter_by_name_unhygienic ( sym:: Upvars )
2491
- . next ( )
2492
- . unwrap ( )
2493
- . def_id ;
2494
- // When we don't know the closure kind (and therefore also the closure's upvars,
2495
- // which are computed at the same time), we must delay the computation of the
2496
- // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
2497
- // goal functions similarly to the old `ClosureKind` predicate, and ensures that
2498
- // the goal kind <= the closure kind. As a projection `AsyncFnKindHelper::Upvars`
2499
- // will project to the right upvars for the generator, appending the inputs and
2500
- // coroutine upvars respecting the closure kind.
2501
- // N.B. No need to register a `AsyncFnKindHelper` goal here, it's already in `nested`.
2502
- let tupled_upvars_ty = Ty :: new_projection (
2527
+ obligation. predicate . def_id ,
2528
+ [ self_ty, sig. tupled_inputs_ty ] ,
2529
+ ) ,
2530
+ sym:: CallMutFuture | sym:: CallFuture => ty:: AliasTy :: new (
2503
2531
tcx,
2504
- upvars_projection_def_id,
2532
+ obligation. predicate . def_id ,
2533
+ [ ty:: GenericArg :: from ( self_ty) , sig. tupled_inputs_ty . into ( ) , env_region. into ( ) ] ,
2534
+ ) ,
2535
+ name => bug ! ( "no such associated type: {name}" ) ,
2536
+ } ;
2537
+
2538
+ args. coroutine_closure_sig ( )
2539
+ . rebind ( ty:: ProjectionPredicate { projection_ty, term : term. into ( ) } )
2540
+ }
2541
+ ty:: FnDef ( ..) | ty:: FnPtr ( ..) => {
2542
+ let bound_sig = self_ty. fn_sig ( tcx) ;
2543
+ let sig = bound_sig. skip_binder ( ) ;
2544
+
2545
+ let term = match item_name {
2546
+ sym:: CallOnceFuture | sym:: CallMutFuture | sym:: CallFuture => sig. output ( ) ,
2547
+ sym:: Output => {
2548
+ let future_trait_def_id = tcx. require_lang_item ( LangItem :: Future , None ) ;
2549
+ let future_output_def_id = tcx
2550
+ . associated_items ( future_trait_def_id)
2551
+ . filter_by_name_unhygienic ( sym:: Output )
2552
+ . next ( )
2553
+ . unwrap ( )
2554
+ . def_id ;
2555
+ Ty :: new_projection ( tcx, future_output_def_id, [ sig. output ( ) ] )
2556
+ }
2557
+ name => bug ! ( "no such associated type: {name}" ) ,
2558
+ } ;
2559
+ let projection_ty = match item_name {
2560
+ sym:: CallOnceFuture | sym:: Output => ty:: AliasTy :: new (
2561
+ tcx,
2562
+ obligation. predicate . def_id ,
2563
+ [ self_ty, Ty :: new_tup ( tcx, sig. inputs ( ) ) ] ,
2564
+ ) ,
2565
+ sym:: CallMutFuture | sym:: CallFuture => ty:: AliasTy :: new (
2566
+ tcx,
2567
+ obligation. predicate . def_id ,
2505
2568
[
2506
- ty:: GenericArg :: from ( kind_ty ) ,
2507
- Ty :: from_closure_kind ( tcx, goal_kind ) . into ( ) ,
2569
+ ty:: GenericArg :: from ( self_ty ) ,
2570
+ Ty :: new_tup ( tcx, sig . inputs ( ) ) . into ( ) ,
2508
2571
env_region. into ( ) ,
2509
- sig. tupled_inputs_ty . into ( ) ,
2510
- args. tupled_upvars_ty ( ) . into ( ) ,
2511
- args. coroutine_captures_by_ref_ty ( ) . into ( ) ,
2512
2572
] ,
2513
- ) ;
2514
- sig. to_coroutine (
2515
- tcx,
2516
- args. parent_args ( ) ,
2517
- Ty :: from_closure_kind ( tcx, goal_kind) ,
2518
- tcx. coroutine_for_closure ( def_id) ,
2519
- tupled_upvars_ty,
2520
- )
2521
- }
2573
+ ) ,
2574
+ name => bug ! ( "no such associated type: {name}" ) ,
2575
+ } ;
2576
+
2577
+ bound_sig. rebind ( ty:: ProjectionPredicate { projection_ty, term : term. into ( ) } )
2522
2578
}
2523
- sym:: Output => sig. return_ty ,
2524
- name => bug ! ( "no such associated type: {name}" ) ,
2525
- } ;
2526
- let projection_ty = match item_name {
2527
- sym:: CallOnceFuture | sym:: Output => {
2528
- ty:: AliasTy :: new ( tcx, obligation. predicate . def_id , [ self_ty, sig. tupled_inputs_ty ] )
2579
+ ty:: Closure ( _, args) => {
2580
+ let args = args. as_closure ( ) ;
2581
+ let bound_sig = args. sig ( ) ;
2582
+ let sig = bound_sig. skip_binder ( ) ;
2583
+
2584
+ let term = match item_name {
2585
+ sym:: CallOnceFuture | sym:: CallMutFuture | sym:: CallFuture => sig. output ( ) ,
2586
+ sym:: Output => {
2587
+ let future_trait_def_id = tcx. require_lang_item ( LangItem :: Future , None ) ;
2588
+ let future_output_def_id = tcx
2589
+ . associated_items ( future_trait_def_id)
2590
+ . filter_by_name_unhygienic ( sym:: Output )
2591
+ . next ( )
2592
+ . unwrap ( )
2593
+ . def_id ;
2594
+ Ty :: new_projection ( tcx, future_output_def_id, [ sig. output ( ) ] )
2595
+ }
2596
+ name => bug ! ( "no such associated type: {name}" ) ,
2597
+ } ;
2598
+ let projection_ty = match item_name {
2599
+ sym:: CallOnceFuture | sym:: Output => {
2600
+ ty:: AliasTy :: new ( tcx, obligation. predicate . def_id , [ self_ty, sig. inputs ( ) [ 0 ] ] )
2601
+ }
2602
+ sym:: CallMutFuture | sym:: CallFuture => ty:: AliasTy :: new (
2603
+ tcx,
2604
+ obligation. predicate . def_id ,
2605
+ [ ty:: GenericArg :: from ( self_ty) , sig. inputs ( ) [ 0 ] . into ( ) , env_region. into ( ) ] ,
2606
+ ) ,
2607
+ name => bug ! ( "no such associated type: {name}" ) ,
2608
+ } ;
2609
+
2610
+ bound_sig. rebind ( ty:: ProjectionPredicate { projection_ty, term : term. into ( ) } )
2529
2611
}
2530
- sym:: CallMutFuture | sym:: CallFuture => ty:: AliasTy :: new (
2531
- tcx,
2532
- obligation. predicate . def_id ,
2533
- [ ty:: GenericArg :: from ( self_ty) , sig. tupled_inputs_ty . into ( ) , env_region. into ( ) ] ,
2534
- ) ,
2535
- name => bug ! ( "no such associated type: {name}" ) ,
2612
+ _ => bug ! ( "expected callable type for AsyncFn candidate" ) ,
2536
2613
} ;
2537
2614
2538
- confirm_param_env_candidate (
2539
- selcx,
2540
- obligation,
2541
- args. coroutine_closure_sig ( )
2542
- . rebind ( ty:: ProjectionPredicate { projection_ty, term : term. into ( ) } ) ,
2543
- true ,
2544
- )
2545
- . with_addl_obligations ( nested)
2615
+ confirm_param_env_candidate ( selcx, obligation, poly_cache_entry, true )
2616
+ . with_addl_obligations ( nested)
2546
2617
}
2547
2618
2548
2619
fn confirm_async_fn_kind_helper_candidate < ' cx , ' tcx > (
0 commit comments