@@ -570,6 +570,10 @@ impl CallableSig {
570570 }
571571 }
572572
573+ pub fn abi ( & self ) -> FnAbi {
574+ self . abi
575+ }
576+
573577 pub fn params ( & self ) -> & [ Ty ] {
574578 & self . params_and_return [ 0 ..self . params_and_return . len ( ) - 1 ]
575579 }
@@ -892,20 +896,16 @@ where
892896 Canonical { value, binders : chalk_ir:: CanonicalVarKinds :: from_iter ( Interner , kinds) }
893897}
894898
895- pub fn callable_sig_from_fnonce (
896- mut self_ty : & Ty ,
897- env : Arc < TraitEnvironment > ,
899+ pub fn callable_sig_from_fn_trait (
900+ self_ty : & Ty ,
901+ trait_env : Arc < TraitEnvironment > ,
898902 db : & dyn HirDatabase ,
899- ) -> Option < CallableSig > {
900- if let Some ( ( ty, _, _) ) = self_ty. as_reference ( ) {
901- // This will happen when it implements fn or fn mut, since we add a autoborrow adjustment
902- self_ty = ty;
903- }
904- let krate = env. krate ;
903+ ) -> Option < ( FnTrait , CallableSig ) > {
904+ let krate = trait_env. krate ;
905905 let fn_once_trait = FnTrait :: FnOnce . get_id ( db, krate) ?;
906906 let output_assoc_type = db. trait_data ( fn_once_trait) . associated_type_by_name ( & name ! [ Output ] ) ?;
907907
908- let mut table = InferenceTable :: new ( db, env ) ;
908+ let mut table = InferenceTable :: new ( db, trait_env . clone ( ) ) ;
909909 let b = TyBuilder :: trait_ref ( db, fn_once_trait) ;
910910 if b. remaining ( ) != 2 {
911911 return None ;
@@ -915,23 +915,56 @@ pub fn callable_sig_from_fnonce(
915915 // - Self: FnOnce<?args_ty>
916916 // - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
917917 let args_ty = table. new_type_var ( ) ;
918- let trait_ref = b. push ( self_ty. clone ( ) ) . push ( args_ty. clone ( ) ) . build ( ) ;
918+ let mut trait_ref = b. push ( self_ty. clone ( ) ) . push ( args_ty. clone ( ) ) . build ( ) ;
919919 let projection = TyBuilder :: assoc_type_projection (
920920 db,
921921 output_assoc_type,
922922 Some ( trait_ref. substitution . clone ( ) ) ,
923923 )
924924 . build ( ) ;
925- table. register_obligation ( trait_ref. cast ( Interner ) ) ;
926- let ret_ty = table. normalize_projection_ty ( projection) ;
927-
928- let ret_ty = table. resolve_completely ( ret_ty) ;
929- let args_ty = table. resolve_completely ( args_ty) ;
930925
931- let params =
932- args_ty. as_tuple ( ) ?. iter ( Interner ) . map ( |it| it. assert_ty_ref ( Interner ) ) . cloned ( ) . collect ( ) ;
933-
934- Some ( CallableSig :: from_params_and_return ( params, ret_ty, false , Safety :: Safe , FnAbi :: RustCall ) )
926+ let block = trait_env. block ;
927+ let trait_env = trait_env. env . clone ( ) ;
928+ let obligation =
929+ InEnvironment { goal : trait_ref. clone ( ) . cast ( Interner ) , environment : trait_env. clone ( ) } ;
930+ let canonical = table. canonicalize ( obligation. clone ( ) ) ;
931+ if db. trait_solve ( krate, block, canonical. cast ( Interner ) ) . is_some ( ) {
932+ table. register_obligation ( obligation. goal ) ;
933+ let return_ty = table. normalize_projection_ty ( projection) ;
934+ for fn_x in [ FnTrait :: Fn , FnTrait :: FnMut , FnTrait :: FnOnce ] {
935+ let fn_x_trait = fn_x. get_id ( db, krate) ?;
936+ trait_ref. trait_id = to_chalk_trait_id ( fn_x_trait) ;
937+ let obligation: chalk_ir:: InEnvironment < chalk_ir:: Goal < Interner > > = InEnvironment {
938+ goal : trait_ref. clone ( ) . cast ( Interner ) ,
939+ environment : trait_env. clone ( ) ,
940+ } ;
941+ let canonical = table. canonicalize ( obligation. clone ( ) ) ;
942+ if db. trait_solve ( krate, block, canonical. cast ( Interner ) ) . is_some ( ) {
943+ let ret_ty = table. resolve_completely ( return_ty) ;
944+ let args_ty = table. resolve_completely ( args_ty) ;
945+ let params = args_ty
946+ . as_tuple ( ) ?
947+ . iter ( Interner )
948+ . map ( |it| it. assert_ty_ref ( Interner ) )
949+ . cloned ( )
950+ . collect ( ) ;
951+
952+ return Some ( (
953+ fn_x,
954+ CallableSig :: from_params_and_return (
955+ params,
956+ ret_ty,
957+ false ,
958+ Safety :: Safe ,
959+ FnAbi :: RustCall ,
960+ ) ,
961+ ) ) ;
962+ }
963+ }
964+ unreachable ! ( "It should at least implement FnOnce at this point" ) ;
965+ } else {
966+ None
967+ }
935968}
936969
937970struct PlaceholderCollector < ' db > {
0 commit comments