@@ -604,6 +604,11 @@ fn find_continuable(
604
604
}
605
605
}
606
606
607
+ enum ImplTraitReplacingMode {
608
+ ReturnPosition ( FxHashSet < Ty > ) ,
609
+ TypeAlias ,
610
+ }
611
+
607
612
impl < ' a > InferenceContext < ' a > {
608
613
fn new (
609
614
db : & ' a dyn HirDatabase ,
@@ -825,13 +830,19 @@ impl<'a> InferenceContext<'a> {
825
830
self . write_binding_ty ( self_param, ty) ;
826
831
}
827
832
}
828
- let mut params_and_ret_tys = Vec :: new ( ) ;
833
+ let mut tait_candidates = FxHashSet :: default ( ) ;
829
834
for ( ty, pat) in param_tys. zip ( & * self . body . params ) {
830
835
let ty = self . insert_type_vars ( ty) ;
831
836
let ty = self . normalize_associated_types_in ( ty) ;
832
837
833
838
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
+ }
835
846
}
836
847
let return_ty = & * data. ret_type ;
837
848
@@ -844,7 +855,12 @@ impl<'a> InferenceContext<'a> {
844
855
let return_ty = if let Some ( rpits) = self . db . return_type_impl_traits ( func) {
845
856
// RPIT opaque types use substitution of their parent function.
846
857
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
+ }
848
864
let rpits = rpits. skip_binders ( ) ;
849
865
for ( id, _) in rpits. impl_traits . iter ( ) {
850
866
if let Entry :: Vacant ( e) = self . result . type_of_rpit . entry ( id) {
@@ -863,11 +879,23 @@ impl<'a> InferenceContext<'a> {
863
879
// Functions might be defining usage sites of TAITs.
864
880
// To define an TAITs, that TAIT must appear in the function's signatures.
865
881
// 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 ( ) ) ;
868
891
}
869
892
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
871
899
where
872
900
T : crate :: HasInterner < Interner = Interner > + crate :: TypeFoldable < Interner > ,
873
901
{
@@ -880,10 +908,31 @@ impl<'a> InferenceContext<'a> {
880
908
} ;
881
909
let ( impl_traits, idx) =
882
910
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
883
918
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
+ }
884
927
( self . db . return_type_impl_traits ( def) , idx)
885
928
}
886
929
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
+ }
887
936
( self . db . type_alias_impl_traits ( def) , idx)
888
937
}
889
938
_ => unreachable ! ( ) ,
@@ -892,16 +941,20 @@ impl<'a> InferenceContext<'a> {
892
941
return ty;
893
942
} ;
894
943
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 ( ) ) ) ;
896
945
let var = self . table . new_type_var ( ) ;
897
946
let var_subst = Substitution :: from1 ( Interner , var. clone ( ) ) ;
898
947
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) ;
900
950
let ( var_predicate, binders) =
901
951
predicate. substitute ( Interner , & var_subst) . into_value_and_skipped_binders ( ) ;
902
952
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
+ ) ;
905
958
self . push_obligation ( var_predicate. cast ( Interner ) ) ;
906
959
}
907
960
self . result . type_of_rpit . insert ( idx, var. clone ( ) ) ;
@@ -1038,7 +1091,11 @@ impl<'a> InferenceContext<'a> {
1038
1091
self . db . lookup_intern_impl_trait_id ( id. into ( ) )
1039
1092
{
1040
1093
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
+ ) ;
1042
1099
Some ( ( id, ty) )
1043
1100
} else {
1044
1101
None
0 commit comments