@@ -305,15 +305,14 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
305305 return Err ( NoSolution ) ;
306306 }
307307
308- sig . to_coroutine_given_kind_and_upvars (
308+ coroutine_closure_to_certain_coroutine (
309309 tcx,
310- args. parent_args ( ) ,
311- tcx. coroutine_for_closure ( def_id) ,
312310 goal_kind,
313311 // No captures by ref, so this doesn't matter.
314312 tcx. lifetimes . re_static ,
315- args. tupled_upvars_ty ( ) ,
316- args. coroutine_captures_by_ref_ty ( ) ,
313+ def_id,
314+ args,
315+ sig,
317316 )
318317 } else {
319318 // 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>(
322321 return Ok ( None ) ;
323322 }
324323
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 (
347325 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,
352331 )
353332 } ;
354333
@@ -385,6 +364,19 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
385364 }
386365}
387366
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+
388380// Returns a binder of the tupled inputs types, output type, and coroutine type
389381// from a builtin coroutine-closure type. If we don't yet know the closure kind of
390382// 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
395387 self_ty : Ty < ' tcx > ,
396388 goal_kind : ty:: ClosureKind ,
397389 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+ > {
400394 match * self_ty. kind ( ) {
401395 ty:: CoroutineClosure ( def_id, args) => {
402396 let args = args. as_coroutine_closure ( ) ;
@@ -407,24 +401,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
407401 if !closure_kind. extends ( goal_kind) {
408402 return Err ( NoSolution ) ;
409403 }
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,
418407 )
419408 } 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 ;
428409 // When we don't know the closure kind (and therefore also the closure's upvars,
429410 // which are computed at the same time), we must delay the computation of the
430411 // 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
435416 nested. push (
436417 ty:: TraitRef :: new (
437418 tcx,
438- async_fn_kind_trait_def_id ,
419+ tcx . require_lang_item ( LangItem :: AsyncFnKindHelper , None ) ,
439420 [ kind_ty, Ty :: from_closure_kind ( tcx, goal_kind) ] ,
440421 )
441422 . to_predicate ( tcx) ,
442423 ) ;
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,
461427 )
462428 } ;
463429
464430 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+ } ) ,
470436 nested,
471437 ) )
472438 }
@@ -490,7 +456,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
490456 . def_id ;
491457 let future_output_ty = Ty :: new_projection ( tcx, future_output_def_id, [ sig. output ( ) ] ) ;
492458 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+ } ) ,
494464 nested,
495465 ) )
496466 }
@@ -541,7 +511,14 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
541511 . unwrap ( )
542512 . def_id ;
543513 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+ ) )
545522 }
546523
547524 ty:: Bool
@@ -574,6 +551,68 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
574551 }
575552}
576553
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+
577616/// Assemble a list of predicates that would be present on a theoretical
578617/// user impl for an object type. These predicates must be checked any time
579618/// we assemble a built-in object candidate for an object type, since they
0 commit comments