@@ -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,13 @@ 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
+ tait_candidates . insert ( ty) ;
835
840
}
836
841
let return_ty = & * data. ret_type ;
837
842
@@ -844,7 +849,12 @@ impl<'a> InferenceContext<'a> {
844
849
let return_ty = if let Some ( rpits) = self . db . return_type_impl_traits ( func) {
845
850
// RPIT opaque types use substitution of their parent function.
846
851
let fn_placeholders = TyBuilder :: placeholder_subst ( self . db , func) ;
847
- let result = self . insert_inference_vars_for_impl_trait ( return_ty, fn_placeholders) ;
852
+ let mut mode = ImplTraitReplacingMode :: ReturnPosition ( FxHashSet :: default ( ) ) ;
853
+ let result =
854
+ self . insert_inference_vars_for_impl_trait ( return_ty, fn_placeholders, & mut mode) ;
855
+ if let ImplTraitReplacingMode :: ReturnPosition ( taits) = mode {
856
+ tait_candidates. extend ( taits) ;
857
+ }
848
858
let rpits = rpits. skip_binders ( ) ;
849
859
for ( id, _) in rpits. impl_traits . iter ( ) {
850
860
if let Entry :: Vacant ( e) = self . result . type_of_rpit . entry ( id) {
@@ -863,11 +873,16 @@ impl<'a> InferenceContext<'a> {
863
873
// Functions might be defining usage sites of TAITs.
864
874
// To define an TAITs, that TAIT must appear in the function's signatures.
865
875
// 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 ( ) ) ;
876
+ tait_candidates . insert ( self . return_ty . clone ( ) ) ;
877
+ self . make_tait_coercion_table ( tait_candidates . iter ( ) ) ;
868
878
}
869
879
870
- fn insert_inference_vars_for_impl_trait < T > ( & mut self , t : T , placeholders : Substitution ) -> T
880
+ fn insert_inference_vars_for_impl_trait < T > (
881
+ & mut self ,
882
+ t : T ,
883
+ placeholders : Substitution ,
884
+ mode : & mut ImplTraitReplacingMode ,
885
+ ) -> T
871
886
where
872
887
T : crate :: HasInterner < Interner = Interner > + crate :: TypeFoldable < Interner > ,
873
888
{
@@ -880,10 +895,31 @@ impl<'a> InferenceContext<'a> {
880
895
} ;
881
896
let ( impl_traits, idx) =
882
897
match self . db . lookup_intern_impl_trait_id ( opaque_ty_id. into ( ) ) {
898
+ // We don't replace opaque types from other kind with inference vars
899
+ // because `insert_inference_vars_for_impl_traits` for each kinds
900
+ // and unreplaced opaque types of other kind are resolved while
901
+ // inferencing because of `tait_coercion_table`.
902
+ // Moreover, calling `insert_inference_vars_for_impl_traits` with same
903
+ // `placeholders` for other kind may cause trouble because
904
+ // the substs for the bounds of each impl traits do not match
883
905
ImplTraitId :: ReturnTypeImplTrait ( def, idx) => {
906
+ if matches ! ( mode, ImplTraitReplacingMode :: TypeAlias ) {
907
+ // RPITs don't have `tait_coercion_table`, so use inserted inference
908
+ // vars for them.
909
+ if let Some ( ty) = self . result . type_of_rpit . get ( idx) {
910
+ return ty. clone ( ) ;
911
+ }
912
+ return ty;
913
+ }
884
914
( self . db . return_type_impl_traits ( def) , idx)
885
915
}
886
916
ImplTraitId :: TypeAliasImplTrait ( def, idx) => {
917
+ if let ImplTraitReplacingMode :: ReturnPosition ( taits) = mode {
918
+ // Gather TAITs while replacing RPITs because TAITs inside RPITs
919
+ // may not visited while replacing TAITs
920
+ taits. insert ( ty. clone ( ) ) ;
921
+ return ty;
922
+ }
887
923
( self . db . type_alias_impl_traits ( def) , idx)
888
924
}
889
925
_ => unreachable ! ( ) ,
@@ -892,16 +928,20 @@ impl<'a> InferenceContext<'a> {
892
928
return ty;
893
929
} ;
894
930
let bounds = ( * impl_traits)
895
- . map_ref ( |rpits| rpits . impl_traits [ idx] . bounds . map_ref ( |it| it. iter ( ) ) ) ;
931
+ . map_ref ( |its| its . impl_traits [ idx] . bounds . map_ref ( |it| it. iter ( ) ) ) ;
896
932
let var = self . table . new_type_var ( ) ;
897
933
let var_subst = Substitution :: from1 ( Interner , var. clone ( ) ) ;
898
934
for bound in bounds {
899
- let predicate = bound. map ( |it| it. cloned ( ) ) . substitute ( Interner , & placeholders) ;
935
+ let predicate = bound. map ( |it| it. cloned ( ) ) ;
936
+ let predicate = predicate. substitute ( Interner , & placeholders) ;
900
937
let ( var_predicate, binders) =
901
938
predicate. substitute ( Interner , & var_subst) . into_value_and_skipped_binders ( ) ;
902
939
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 ( ) ) ;
940
+ let var_predicate = self . insert_inference_vars_for_impl_trait (
941
+ var_predicate,
942
+ placeholders. clone ( ) ,
943
+ mode,
944
+ ) ;
905
945
self . push_obligation ( var_predicate. cast ( Interner ) ) ;
906
946
}
907
947
self . result . type_of_rpit . insert ( idx, var. clone ( ) ) ;
@@ -1038,7 +1078,11 @@ impl<'a> InferenceContext<'a> {
1038
1078
self . db . lookup_intern_impl_trait_id ( id. into ( ) )
1039
1079
{
1040
1080
let subst = TyBuilder :: placeholder_subst ( self . db , alias_id) ;
1041
- let ty = self . insert_inference_vars_for_impl_trait ( ty, subst) ;
1081
+ let ty = self . insert_inference_vars_for_impl_trait (
1082
+ ty,
1083
+ subst,
1084
+ & mut ImplTraitReplacingMode :: TypeAlias ,
1085
+ ) ;
1042
1086
Some ( ( id, ty) )
1043
1087
} else {
1044
1088
None
0 commit comments