@@ -794,69 +794,75 @@ impl<'a> InferenceTable<'a> {
794794 ty : & Ty ,
795795 num_args : usize ,
796796 ) -> 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 ( ) ;
821826
822- let projection = {
823- TyBuilder :: assoc_type_projection (
827+ let projection = TyBuilder :: assoc_type_projection (
824828 self . db ,
825829 output_assoc_type,
826830 Some ( trait_ref. substitution . clone ( ) ) ,
827831 )
828- . build ( )
829- } ;
832+ . fill_with_unknown ( )
833+ . build ( ) ;
830834
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+ }
854861 }
862+ return Some ( ( fn_trait_name, arg_tys, return_ty) ) ;
855863 }
856- unreachable ! ( "It should at least implement FnOnce at this point" ) ;
857- } else {
858- None
859864 }
865+ None
860866 }
861867
862868 pub ( super ) fn insert_type_vars < T > ( & mut self , ty : T ) -> T
0 commit comments