@@ -604,6 +604,11 @@ fn find_continuable(
604604 }
605605}
606606
607+ enum ImplTraitReplacingMode {
608+ ReturnPosition ( FxHashSet < Ty > ) ,
609+ TypeAlias ,
610+ }
611+
607612impl < ' a > InferenceContext < ' a > {
608613 fn new (
609614 db : & ' a dyn HirDatabase ,
@@ -825,13 +830,19 @@ impl<'a> InferenceContext<'a> {
825830 self . write_binding_ty ( self_param, ty) ;
826831 }
827832 }
828- let mut params_and_ret_tys = Vec :: new ( ) ;
833+ let mut tait_candidates = FxHashSet :: default ( ) ;
829834 for ( ty, pat) in param_tys. zip ( & * self . body . params ) {
830835 let ty = self . insert_type_vars ( ty) ;
831836 let ty = self . normalize_associated_types_in ( ty) ;
832837
833838 self . infer_top_pat ( * pat, & ty) ;
834- params_and_ret_tys. push ( ty) ;
839+ if ty
840+ . data ( Interner )
841+ . flags
842+ . intersects ( TypeFlags :: HAS_TY_OPAQUE . union ( TypeFlags :: HAS_TY_INFER ) )
843+ {
844+ tait_candidates. insert ( ty) ;
845+ }
835846 }
836847 let return_ty = & * data. ret_type ;
837848
@@ -844,7 +855,12 @@ impl<'a> InferenceContext<'a> {
844855 let return_ty = if let Some ( rpits) = self . db . return_type_impl_traits ( func) {
845856 // RPIT opaque types use substitution of their parent function.
846857 let fn_placeholders = TyBuilder :: placeholder_subst ( self . db , func) ;
847- let result = self . insert_inference_vars_for_impl_trait ( return_ty, fn_placeholders) ;
858+ let mut mode = ImplTraitReplacingMode :: ReturnPosition ( FxHashSet :: default ( ) ) ;
859+ let result =
860+ self . insert_inference_vars_for_impl_trait ( return_ty, fn_placeholders, & mut mode) ;
861+ if let ImplTraitReplacingMode :: ReturnPosition ( taits) = mode {
862+ tait_candidates. extend ( taits) ;
863+ }
848864 let rpits = rpits. skip_binders ( ) ;
849865 for ( id, _) in rpits. impl_traits . iter ( ) {
850866 if let Entry :: Vacant ( e) = self . result . type_of_rpit . entry ( id) {
@@ -863,11 +879,23 @@ impl<'a> InferenceContext<'a> {
863879 // Functions might be defining usage sites of TAITs.
864880 // To define an TAITs, that TAIT must appear in the function's signatures.
865881 // So, it suffices to check for params and return types.
866- params_and_ret_tys. push ( self . return_ty . clone ( ) ) ;
867- self . make_tait_coercion_table ( params_and_ret_tys. iter ( ) ) ;
882+ if self
883+ . return_ty
884+ . data ( Interner )
885+ . flags
886+ . intersects ( TypeFlags :: HAS_TY_OPAQUE . union ( TypeFlags :: HAS_TY_INFER ) )
887+ {
888+ tait_candidates. insert ( self . return_ty . clone ( ) ) ;
889+ }
890+ self . make_tait_coercion_table ( tait_candidates. iter ( ) ) ;
868891 }
869892
870- fn insert_inference_vars_for_impl_trait < T > ( & mut self , t : T , placeholders : Substitution ) -> T
893+ fn insert_inference_vars_for_impl_trait < T > (
894+ & mut self ,
895+ t : T ,
896+ placeholders : Substitution ,
897+ mode : & mut ImplTraitReplacingMode ,
898+ ) -> T
871899 where
872900 T : crate :: HasInterner < Interner = Interner > + crate :: TypeFoldable < Interner > ,
873901 {
@@ -880,10 +908,31 @@ impl<'a> InferenceContext<'a> {
880908 } ;
881909 let ( impl_traits, idx) =
882910 match self . db . lookup_intern_impl_trait_id ( opaque_ty_id. into ( ) ) {
911+ // We don't replace opaque types from other kind with inference vars
912+ // because `insert_inference_vars_for_impl_traits` for each kinds
913+ // and unreplaced opaque types of other kind are resolved while
914+ // inferencing because of `tait_coercion_table`.
915+ // Moreover, calling `insert_inference_vars_for_impl_traits` with same
916+ // `placeholders` for other kind may cause trouble because
917+ // the substs for the bounds of each impl traits do not match
883918 ImplTraitId :: ReturnTypeImplTrait ( def, idx) => {
919+ if matches ! ( mode, ImplTraitReplacingMode :: TypeAlias ) {
920+ // RPITs don't have `tait_coercion_table`, so use inserted inference
921+ // vars for them.
922+ if let Some ( ty) = self . result . type_of_rpit . get ( idx) {
923+ return ty. clone ( ) ;
924+ }
925+ return ty;
926+ }
884927 ( self . db . return_type_impl_traits ( def) , idx)
885928 }
886929 ImplTraitId :: TypeAliasImplTrait ( def, idx) => {
930+ if let ImplTraitReplacingMode :: ReturnPosition ( taits) = mode {
931+ // Gather TAITs while replacing RPITs because TAITs inside RPITs
932+ // may not visited while replacing TAITs
933+ taits. insert ( ty. clone ( ) ) ;
934+ return ty;
935+ }
887936 ( self . db . type_alias_impl_traits ( def) , idx)
888937 }
889938 _ => unreachable ! ( ) ,
@@ -892,16 +941,20 @@ impl<'a> InferenceContext<'a> {
892941 return ty;
893942 } ;
894943 let bounds = ( * impl_traits)
895- . map_ref ( |rpits| rpits . impl_traits [ idx] . bounds . map_ref ( |it| it. iter ( ) ) ) ;
944+ . map_ref ( |its| its . impl_traits [ idx] . bounds . map_ref ( |it| it. iter ( ) ) ) ;
896945 let var = self . table . new_type_var ( ) ;
897946 let var_subst = Substitution :: from1 ( Interner , var. clone ( ) ) ;
898947 for bound in bounds {
899- let predicate = bound. map ( |it| it. cloned ( ) ) . substitute ( Interner , & placeholders) ;
948+ let predicate = bound. map ( |it| it. cloned ( ) ) ;
949+ let predicate = predicate. substitute ( Interner , & placeholders) ;
900950 let ( var_predicate, binders) =
901951 predicate. substitute ( Interner , & var_subst) . into_value_and_skipped_binders ( ) ;
902952 always ! ( binders. is_empty( Interner ) ) ; // quantified where clauses not yet handled
903- let var_predicate = self
904- . insert_inference_vars_for_impl_trait ( var_predicate, placeholders. clone ( ) ) ;
953+ let var_predicate = self . insert_inference_vars_for_impl_trait (
954+ var_predicate,
955+ placeholders. clone ( ) ,
956+ mode,
957+ ) ;
905958 self . push_obligation ( var_predicate. cast ( Interner ) ) ;
906959 }
907960 self . result . type_of_rpit . insert ( idx, var. clone ( ) ) ;
@@ -1038,7 +1091,11 @@ impl<'a> InferenceContext<'a> {
10381091 self . db . lookup_intern_impl_trait_id ( id. into ( ) )
10391092 {
10401093 let subst = TyBuilder :: placeholder_subst ( self . db , alias_id) ;
1041- let ty = self . insert_inference_vars_for_impl_trait ( ty, subst) ;
1094+ let ty = self . insert_inference_vars_for_impl_trait (
1095+ ty,
1096+ subst,
1097+ & mut ImplTraitReplacingMode :: TypeAlias ,
1098+ ) ;
10421099 Some ( ( id, ty) )
10431100 } else {
10441101 None
0 commit comments