@@ -305,15 +305,14 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
305
305
return Err ( NoSolution ) ;
306
306
}
307
307
308
- sig . to_coroutine_given_kind_and_upvars (
308
+ coroutine_closure_to_certain_coroutine (
309
309
tcx,
310
- args. parent_args ( ) ,
311
- tcx. coroutine_for_closure ( def_id) ,
312
310
goal_kind,
313
311
// No captures by ref, so this doesn't matter.
314
312
tcx. lifetimes . re_static ,
315
- args. tupled_upvars_ty ( ) ,
316
- args. coroutine_captures_by_ref_ty ( ) ,
313
+ def_id,
314
+ args,
315
+ sig,
317
316
)
318
317
} else {
319
318
// Closure kind is not yet determined, so we return ambiguity unless
@@ -322,33 +321,13 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
322
321
return Ok ( None ) ;
323
322
}
324
323
325
- let async_fn_kind_trait_def_id =
326
- tcx. require_lang_item ( LangItem :: AsyncFnKindHelper , None ) ;
327
- let upvars_projection_def_id = tcx
328
- . associated_items ( async_fn_kind_trait_def_id)
329
- . filter_by_name_unhygienic ( sym:: Upvars )
330
- . next ( )
331
- . unwrap ( )
332
- . def_id ;
333
- let tupled_upvars_ty = Ty :: new_projection (
334
- tcx,
335
- upvars_projection_def_id,
336
- [
337
- ty:: GenericArg :: from ( kind_ty) ,
338
- Ty :: from_closure_kind ( tcx, goal_kind) . into ( ) ,
339
- // No captures by ref, so this doesn't matter.
340
- tcx. lifetimes . re_static . into ( ) ,
341
- sig. tupled_inputs_ty . into ( ) ,
342
- args. tupled_upvars_ty ( ) . into ( ) ,
343
- args. coroutine_captures_by_ref_ty ( ) . into ( ) ,
344
- ] ,
345
- ) ;
346
- sig. to_coroutine (
324
+ coroutine_closure_to_ambiguous_coroutine (
347
325
tcx,
348
- args. parent_args ( ) ,
349
- Ty :: from_closure_kind ( tcx, goal_kind) ,
350
- tcx. coroutine_for_closure ( def_id) ,
351
- tupled_upvars_ty,
326
+ goal_kind, // No captures by ref, so this doesn't matter.
327
+ tcx. lifetimes . re_static ,
328
+ def_id,
329
+ args,
330
+ sig,
352
331
)
353
332
} ;
354
333
@@ -385,6 +364,19 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
385
364
}
386
365
}
387
366
367
+ /// Relevant types for an async callable, including its inputs, output,
368
+ /// and the return type you get from awaiting the output.
369
+ #[ derive( Copy , Clone , Debug , TypeVisitable , TypeFoldable ) ]
370
+ pub ( in crate :: solve) struct AsyncCallableRelevantTypes < ' tcx > {
371
+ pub tupled_inputs_ty : Ty < ' tcx > ,
372
+ /// Type returned by calling the closure
373
+ /// i.e. `f()`.
374
+ pub output_coroutine_ty : Ty < ' tcx > ,
375
+ /// Type returned by `await`ing the output
376
+ /// i.e. `f().await`.
377
+ pub coroutine_return_ty : Ty < ' tcx > ,
378
+ }
379
+
388
380
// Returns a binder of the tupled inputs types, output type, and coroutine type
389
381
// from a builtin coroutine-closure type. If we don't yet know the closure kind of
390
382
// the coroutine-closure, emit an additional trait predicate for `AsyncFnKindHelper`
@@ -395,8 +387,10 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
395
387
self_ty : Ty < ' tcx > ,
396
388
goal_kind : ty:: ClosureKind ,
397
389
env_region : ty:: Region < ' tcx > ,
398
- ) -> Result < ( ty:: Binder < ' tcx , ( Ty < ' tcx > , Ty < ' tcx > , Ty < ' tcx > ) > , Vec < ty:: Predicate < ' tcx > > ) , NoSolution >
399
- {
390
+ ) -> Result <
391
+ ( ty:: Binder < ' tcx , AsyncCallableRelevantTypes < ' tcx > > , Vec < ty:: Predicate < ' tcx > > ) ,
392
+ NoSolution ,
393
+ > {
400
394
match * self_ty. kind ( ) {
401
395
ty:: CoroutineClosure ( def_id, args) => {
402
396
let args = args. as_coroutine_closure ( ) ;
@@ -407,24 +401,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
407
401
if !closure_kind. extends ( goal_kind) {
408
402
return Err ( NoSolution ) ;
409
403
}
410
- sig. to_coroutine_given_kind_and_upvars (
411
- tcx,
412
- args. parent_args ( ) ,
413
- tcx. coroutine_for_closure ( def_id) ,
414
- goal_kind,
415
- env_region,
416
- args. tupled_upvars_ty ( ) ,
417
- args. coroutine_captures_by_ref_ty ( ) ,
404
+
405
+ coroutine_closure_to_certain_coroutine (
406
+ tcx, goal_kind, env_region, def_id, args, sig,
418
407
)
419
408
} else {
420
- let async_fn_kind_trait_def_id =
421
- tcx. require_lang_item ( LangItem :: AsyncFnKindHelper , None ) ;
422
- let upvars_projection_def_id = tcx
423
- . associated_items ( async_fn_kind_trait_def_id)
424
- . filter_by_name_unhygienic ( sym:: Upvars )
425
- . next ( )
426
- . unwrap ( )
427
- . def_id ;
428
409
// When we don't know the closure kind (and therefore also the closure's upvars,
429
410
// which are computed at the same time), we must delay the computation of the
430
411
// generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
@@ -435,38 +416,23 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
435
416
nested. push (
436
417
ty:: TraitRef :: new (
437
418
tcx,
438
- async_fn_kind_trait_def_id ,
419
+ tcx . require_lang_item ( LangItem :: AsyncFnKindHelper , None ) ,
439
420
[ kind_ty, Ty :: from_closure_kind ( tcx, goal_kind) ] ,
440
421
)
441
422
. to_predicate ( tcx) ,
442
423
) ;
443
- let tupled_upvars_ty = Ty :: new_projection (
444
- tcx,
445
- upvars_projection_def_id,
446
- [
447
- ty:: GenericArg :: from ( kind_ty) ,
448
- Ty :: from_closure_kind ( tcx, goal_kind) . into ( ) ,
449
- env_region. into ( ) ,
450
- sig. tupled_inputs_ty . into ( ) ,
451
- args. tupled_upvars_ty ( ) . into ( ) ,
452
- args. coroutine_captures_by_ref_ty ( ) . into ( ) ,
453
- ] ,
454
- ) ;
455
- sig. to_coroutine (
456
- tcx,
457
- args. parent_args ( ) ,
458
- Ty :: from_closure_kind ( tcx, goal_kind) ,
459
- tcx. coroutine_for_closure ( def_id) ,
460
- tupled_upvars_ty,
424
+
425
+ coroutine_closure_to_ambiguous_coroutine (
426
+ tcx, goal_kind, env_region, def_id, args, sig,
461
427
)
462
428
} ;
463
429
464
430
Ok ( (
465
- args. coroutine_closure_sig ( ) . rebind ( (
466
- sig. tupled_inputs_ty ,
467
- sig . return_ty ,
468
- coroutine_ty ,
469
- ) ) ,
431
+ args. coroutine_closure_sig ( ) . rebind ( AsyncCallableRelevantTypes {
432
+ tupled_inputs_ty : sig. tupled_inputs_ty ,
433
+ output_coroutine_ty : coroutine_ty ,
434
+ coroutine_return_ty : sig . return_ty ,
435
+ } ) ,
470
436
nested,
471
437
) )
472
438
}
@@ -490,7 +456,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
490
456
. def_id ;
491
457
let future_output_ty = Ty :: new_projection ( tcx, future_output_def_id, [ sig. output ( ) ] ) ;
492
458
Ok ( (
493
- bound_sig. rebind ( ( Ty :: new_tup ( tcx, sig. inputs ( ) ) , sig. output ( ) , future_output_ty) ) ,
459
+ bound_sig. rebind ( AsyncCallableRelevantTypes {
460
+ tupled_inputs_ty : Ty :: new_tup ( tcx, sig. inputs ( ) ) ,
461
+ output_coroutine_ty : sig. output ( ) ,
462
+ coroutine_return_ty : future_output_ty,
463
+ } ) ,
494
464
nested,
495
465
) )
496
466
}
@@ -541,7 +511,14 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
541
511
. unwrap ( )
542
512
. def_id ;
543
513
let future_output_ty = Ty :: new_projection ( tcx, future_output_def_id, [ sig. output ( ) ] ) ;
544
- Ok ( ( bound_sig. rebind ( ( sig. inputs ( ) [ 0 ] , sig. output ( ) , future_output_ty) ) , nested) )
514
+ Ok ( (
515
+ bound_sig. rebind ( AsyncCallableRelevantTypes {
516
+ tupled_inputs_ty : sig. inputs ( ) [ 0 ] ,
517
+ output_coroutine_ty : sig. output ( ) ,
518
+ coroutine_return_ty : future_output_ty,
519
+ } ) ,
520
+ nested,
521
+ ) )
545
522
}
546
523
547
524
ty:: Bool
@@ -574,6 +551,68 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
574
551
}
575
552
}
576
553
554
+ /// Given a coroutine-closure, project to its returned coroutine when we are *certain*
555
+ /// that the closure's kind is compatible with the goal.
556
+ fn coroutine_closure_to_certain_coroutine < ' tcx > (
557
+ tcx : TyCtxt < ' tcx > ,
558
+ goal_kind : ty:: ClosureKind ,
559
+ goal_region : ty:: Region < ' tcx > ,
560
+ def_id : DefId ,
561
+ args : ty:: CoroutineClosureArgs < ' tcx > ,
562
+ sig : ty:: CoroutineClosureSignature < ' tcx > ,
563
+ ) -> Ty < ' tcx > {
564
+ sig. to_coroutine_given_kind_and_upvars (
565
+ tcx,
566
+ args. parent_args ( ) ,
567
+ tcx. coroutine_for_closure ( def_id) ,
568
+ goal_kind,
569
+ goal_region,
570
+ args. tupled_upvars_ty ( ) ,
571
+ args. coroutine_captures_by_ref_ty ( ) ,
572
+ )
573
+ }
574
+
575
+ /// Given a coroutine-closure, project to its returned coroutine when we are *not certain*
576
+ /// that the closure's kind is compatible with the goal, and therefore also don't know
577
+ /// yet what the closure's upvars are.
578
+ ///
579
+ /// Note that we do not also push a `AsyncFnKindHelper` goal here.
580
+ fn coroutine_closure_to_ambiguous_coroutine < ' tcx > (
581
+ tcx : TyCtxt < ' tcx > ,
582
+ goal_kind : ty:: ClosureKind ,
583
+ goal_region : ty:: Region < ' tcx > ,
584
+ def_id : DefId ,
585
+ args : ty:: CoroutineClosureArgs < ' tcx > ,
586
+ sig : ty:: CoroutineClosureSignature < ' tcx > ,
587
+ ) -> Ty < ' tcx > {
588
+ let async_fn_kind_trait_def_id = tcx. require_lang_item ( LangItem :: AsyncFnKindHelper , None ) ;
589
+ let upvars_projection_def_id = tcx
590
+ . associated_items ( async_fn_kind_trait_def_id)
591
+ . filter_by_name_unhygienic ( sym:: Upvars )
592
+ . next ( )
593
+ . unwrap ( )
594
+ . def_id ;
595
+ let tupled_upvars_ty = Ty :: new_projection (
596
+ tcx,
597
+ upvars_projection_def_id,
598
+ [
599
+ ty:: GenericArg :: from ( args. kind_ty ( ) ) ,
600
+ Ty :: from_closure_kind ( tcx, goal_kind) . into ( ) ,
601
+ goal_region. into ( ) ,
602
+ sig. tupled_inputs_ty . into ( ) ,
603
+ args. tupled_upvars_ty ( ) . into ( ) ,
604
+ args. coroutine_captures_by_ref_ty ( ) . into ( ) ,
605
+ ] ,
606
+ ) ;
607
+ sig. to_coroutine (
608
+ tcx,
609
+ args. parent_args ( ) ,
610
+ Ty :: from_closure_kind ( tcx, goal_kind) ,
611
+ tcx. coroutine_for_closure ( def_id) ,
612
+ tupled_upvars_ty,
613
+ )
614
+ }
615
+
577
616
/// Assemble a list of predicates that would be present on a theoretical
578
617
/// user impl for an object type. These predicates must be checked any time
579
618
/// we assemble a built-in object candidate for an object type, since they
0 commit comments