@@ -794,69 +794,75 @@ impl<'a> InferenceTable<'a> {
794
794
ty : & Ty ,
795
795
num_args : usize ,
796
796
) -> Option < ( FnTrait , Vec < Ty > , Ty ) > {
797
- let krate = self . trait_env . krate ;
798
- let fn_once_trait = FnTrait :: FnOnce . get_id ( self . db , krate) ?;
799
- let trait_data = self . db . trait_data ( fn_once_trait) ;
800
- let output_assoc_type =
801
- trait_data. associated_type_by_name ( & Name :: new_symbol_root ( sym:: Output . clone ( ) ) ) ?;
802
-
803
- let mut arg_tys = Vec :: with_capacity ( num_args) ;
804
- let arg_ty = TyBuilder :: tuple ( num_args)
805
- . fill ( |it| {
806
- let arg = match it {
807
- ParamKind :: Type => self . new_type_var ( ) ,
808
- ParamKind :: Lifetime => unreachable ! ( "Tuple with lifetime parameter" ) ,
809
- ParamKind :: Const ( _) => unreachable ! ( "Tuple with const parameter" ) ,
810
- } ;
811
- arg_tys. push ( arg. clone ( ) ) ;
812
- arg. cast ( Interner )
813
- } )
814
- . build ( ) ;
815
-
816
- let b = TyBuilder :: trait_ref ( self . db , fn_once_trait) ;
817
- if b. remaining ( ) != 2 {
818
- return None ;
819
- }
820
- let mut trait_ref = b. push ( ty. clone ( ) ) . push ( arg_ty) . build ( ) ;
797
+ for ( fn_trait_name, output_assoc_name, subtraits) in [
798
+ ( FnTrait :: FnOnce , sym:: Output . clone ( ) , & [ FnTrait :: Fn , FnTrait :: FnMut ] [ ..] ) ,
799
+ ( FnTrait :: AsyncFnMut , sym:: CallRefFuture . clone ( ) , & [ FnTrait :: AsyncFn ] ) ,
800
+ ( FnTrait :: AsyncFnOnce , sym:: CallOnceFuture . clone ( ) , & [ ] ) ,
801
+ ] {
802
+ let krate = self . trait_env . krate ;
803
+ let fn_trait = fn_trait_name. get_id ( self . db , krate) ?;
804
+ let trait_data = self . db . trait_data ( fn_trait) ;
805
+ let output_assoc_type =
806
+ trait_data. associated_type_by_name ( & Name :: new_symbol_root ( output_assoc_name) ) ?;
807
+
808
+ let mut arg_tys = Vec :: with_capacity ( num_args) ;
809
+ let arg_ty = TyBuilder :: tuple ( num_args)
810
+ . fill ( |it| {
811
+ let arg = match it {
812
+ ParamKind :: Type => self . new_type_var ( ) ,
813
+ ParamKind :: Lifetime => unreachable ! ( "Tuple with lifetime parameter" ) ,
814
+ ParamKind :: Const ( _) => unreachable ! ( "Tuple with const parameter" ) ,
815
+ } ;
816
+ arg_tys. push ( arg. clone ( ) ) ;
817
+ arg. cast ( Interner )
818
+ } )
819
+ . build ( ) ;
820
+
821
+ let b = TyBuilder :: trait_ref ( self . db , fn_trait) ;
822
+ if b. remaining ( ) != 2 {
823
+ return None ;
824
+ }
825
+ let mut trait_ref = b. push ( ty. clone ( ) ) . push ( arg_ty) . build ( ) ;
821
826
822
- let projection = {
823
- TyBuilder :: assoc_type_projection (
827
+ let projection = TyBuilder :: assoc_type_projection (
824
828
self . db ,
825
829
output_assoc_type,
826
830
Some ( trait_ref. substitution . clone ( ) ) ,
827
831
)
828
- . build ( )
829
- } ;
832
+ . fill_with_unknown ( )
833
+ . build ( ) ;
830
834
831
- let trait_env = self . trait_env . env . clone ( ) ;
832
- let obligation = InEnvironment {
833
- goal : trait_ref. clone ( ) . cast ( Interner ) ,
834
- environment : trait_env. clone ( ) ,
835
- } ;
836
- let canonical = self . canonicalize ( obligation. clone ( ) ) ;
837
- if self . db . trait_solve ( krate, self . trait_env . block , canonical. cast ( Interner ) ) . is_some ( ) {
838
- self . register_obligation ( obligation. goal ) ;
839
- let return_ty = self . normalize_projection_ty ( projection) ;
840
- for fn_x in [ FnTrait :: Fn , FnTrait :: FnMut , FnTrait :: FnOnce ] {
841
- let fn_x_trait = fn_x. get_id ( self . db , krate) ?;
842
- trait_ref. trait_id = to_chalk_trait_id ( fn_x_trait) ;
843
- let obligation: chalk_ir:: InEnvironment < chalk_ir:: Goal < Interner > > = InEnvironment {
844
- goal : trait_ref. clone ( ) . cast ( Interner ) ,
845
- environment : trait_env. clone ( ) ,
846
- } ;
847
- let canonical = self . canonicalize ( obligation. clone ( ) ) ;
848
- if self
849
- . db
850
- . trait_solve ( krate, self . trait_env . block , canonical. cast ( Interner ) )
851
- . is_some ( )
852
- {
853
- return Some ( ( fn_x, arg_tys, return_ty) ) ;
835
+ let trait_env = self . trait_env . env . clone ( ) ;
836
+ let obligation = InEnvironment {
837
+ goal : trait_ref. clone ( ) . cast ( Interner ) ,
838
+ environment : trait_env. clone ( ) ,
839
+ } ;
840
+ let canonical = self . canonicalize ( obligation. clone ( ) ) ;
841
+ if self . db . trait_solve ( krate, self . trait_env . block , canonical. cast ( Interner ) ) . is_some ( )
842
+ {
843
+ self . register_obligation ( obligation. goal ) ;
844
+ let return_ty = self . normalize_projection_ty ( projection) ;
845
+ for & fn_x in subtraits {
846
+ let fn_x_trait = fn_x. get_id ( self . db , krate) ?;
847
+ trait_ref. trait_id = to_chalk_trait_id ( fn_x_trait) ;
848
+ let obligation: chalk_ir:: InEnvironment < chalk_ir:: Goal < Interner > > =
849
+ InEnvironment {
850
+ goal : trait_ref. clone ( ) . cast ( Interner ) ,
851
+ environment : trait_env. clone ( ) ,
852
+ } ;
853
+ let canonical = self . canonicalize ( obligation. clone ( ) ) ;
854
+ if self
855
+ . db
856
+ . trait_solve ( krate, self . trait_env . block , canonical. cast ( Interner ) )
857
+ . is_some ( )
858
+ {
859
+ return Some ( ( fn_x, arg_tys, return_ty) ) ;
860
+ }
854
861
}
862
+ return Some ( ( fn_trait_name, arg_tys, return_ty) ) ;
855
863
}
856
- unreachable ! ( "It should at least implement FnOnce at this point" ) ;
857
- } else {
858
- None
859
864
}
865
+ None
860
866
}
861
867
862
868
pub ( super ) fn insert_type_vars < T > ( & mut self , ty : T ) -> T
0 commit comments