@@ -570,6 +570,10 @@ impl CallableSig {
570
570
}
571
571
}
572
572
573
+ pub fn abi ( & self ) -> FnAbi {
574
+ self . abi
575
+ }
576
+
573
577
pub fn params ( & self ) -> & [ Ty ] {
574
578
& self . params_and_return [ 0 ..self . params_and_return . len ( ) - 1 ]
575
579
}
@@ -892,20 +896,16 @@ where
892
896
Canonical { value, binders : chalk_ir:: CanonicalVarKinds :: from_iter ( Interner , kinds) }
893
897
}
894
898
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 > ,
898
902
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 ;
905
905
let fn_once_trait = FnTrait :: FnOnce . get_id ( db, krate) ?;
906
906
let output_assoc_type = db. trait_data ( fn_once_trait) . associated_type_by_name ( & name ! [ Output ] ) ?;
907
907
908
- let mut table = InferenceTable :: new ( db, env ) ;
908
+ let mut table = InferenceTable :: new ( db, trait_env . clone ( ) ) ;
909
909
let b = TyBuilder :: trait_ref ( db, fn_once_trait) ;
910
910
if b. remaining ( ) != 2 {
911
911
return None ;
@@ -915,23 +915,56 @@ pub fn callable_sig_from_fnonce(
915
915
// - Self: FnOnce<?args_ty>
916
916
// - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
917
917
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 ( ) ;
919
919
let projection = TyBuilder :: assoc_type_projection (
920
920
db,
921
921
output_assoc_type,
922
922
Some ( trait_ref. substitution . clone ( ) ) ,
923
923
)
924
924
. 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) ;
930
925
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
+ }
935
968
}
936
969
937
970
struct PlaceholderCollector < ' db > {
0 commit comments