@@ -458,28 +458,23 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
458458 ) )
459459 }
460460
461- ty:: FnDef ( ..) | ty:: FnPtr ( ..) => {
462- let bound_sig = self_ty. fn_sig ( cx) ;
463- let sig = bound_sig. skip_binder ( ) ;
464- let future_trait_def_id = cx. require_lang_item ( TraitSolverLangItem :: Future ) ;
465- // `FnDef` and `FnPtr` only implement `AsyncFn*` when their
466- // return type implements `Future`.
467- let nested = vec ! [
468- bound_sig
469- . rebind( ty:: TraitRef :: new( cx, future_trait_def_id, [ sig. output( ) ] ) )
470- . upcast( cx) ,
471- ] ;
472- let future_output_def_id = cx. require_lang_item ( TraitSolverLangItem :: FutureOutput ) ;
473- let future_output_ty = Ty :: new_projection ( cx, future_output_def_id, [ sig. output ( ) ] ) ;
474- Ok ( (
475- bound_sig. rebind ( AsyncCallableRelevantTypes {
476- tupled_inputs_ty : Ty :: new_tup ( cx, sig. inputs ( ) . as_slice ( ) ) ,
477- output_coroutine_ty : sig. output ( ) ,
478- coroutine_return_ty : future_output_ty,
479- } ) ,
480- nested,
481- ) )
461+ ty:: FnDef ( def_id, _) => {
462+ let sig = self_ty. fn_sig ( cx) ;
463+ if sig. skip_binder ( ) . is_fn_trait_compatible ( ) && !cx. has_target_features ( def_id) {
464+ fn_item_to_async_callable ( cx, sig)
465+ } else {
466+ Err ( NoSolution )
467+ }
468+ }
469+ ty:: FnPtr ( ..) => {
470+ let sig = self_ty. fn_sig ( cx) ;
471+ if sig. skip_binder ( ) . is_fn_trait_compatible ( ) {
472+ fn_item_to_async_callable ( cx, sig)
473+ } else {
474+ Err ( NoSolution )
475+ }
482476 }
477+
483478 ty:: Closure ( _, args) => {
484479 let args = args. as_closure ( ) ;
485480 let bound_sig = args. sig ( ) ;
@@ -563,6 +558,29 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
563558 }
564559}
565560
561+ fn fn_item_to_async_callable < I : Interner > (
562+ cx : I ,
563+ bound_sig : ty:: Binder < I , ty:: FnSig < I > > ,
564+ ) -> Result < ( ty:: Binder < I , AsyncCallableRelevantTypes < I > > , Vec < I :: Predicate > ) , NoSolution > {
565+ let sig = bound_sig. skip_binder ( ) ;
566+ let future_trait_def_id = cx. require_lang_item ( TraitSolverLangItem :: Future ) ;
567+ // `FnDef` and `FnPtr` only implement `AsyncFn*` when their
568+ // return type implements `Future`.
569+ let nested = vec ! [
570+ bound_sig. rebind( ty:: TraitRef :: new( cx, future_trait_def_id, [ sig. output( ) ] ) ) . upcast( cx) ,
571+ ] ;
572+ let future_output_def_id = cx. require_lang_item ( TraitSolverLangItem :: FutureOutput ) ;
573+ let future_output_ty = Ty :: new_projection ( cx, future_output_def_id, [ sig. output ( ) ] ) ;
574+ Ok ( (
575+ bound_sig. rebind ( AsyncCallableRelevantTypes {
576+ tupled_inputs_ty : Ty :: new_tup ( cx, sig. inputs ( ) . as_slice ( ) ) ,
577+ output_coroutine_ty : sig. output ( ) ,
578+ coroutine_return_ty : future_output_ty,
579+ } ) ,
580+ nested,
581+ ) )
582+ }
583+
566584/// Given a coroutine-closure, project to its returned coroutine when we are *certain*
567585/// that the closure's kind is compatible with the goal.
568586fn coroutine_closure_to_certain_coroutine < I : Interner > (
0 commit comments