@@ -5,45 +5,40 @@ use std::{iter, ops::ControlFlow, sync::Arc};
5
5
6
6
use hir_expand:: name:: Name ;
7
7
use intern:: sym;
8
- use rustc_hash:: FxHashMap ;
9
8
use span:: Edition ;
10
9
use tracing:: debug;
11
10
12
11
use chalk_ir:: {
13
12
Binders , CanonicalVarKinds ,
14
13
cast:: { Cast , Caster } ,
15
- fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable , shift:: Shift } ,
14
+ fold:: shift:: Shift ,
16
15
} ;
17
16
use chalk_solve:: rust_ir:: { self , AssociatedTyDatumBound , OpaqueTyDatumBound , WellKnownTrait } ;
18
17
19
18
use base_db:: Crate ;
20
19
use hir_def:: {
21
- AssocItemId , BlockId , CallableDefId , FunctionId , GenericDefId , HasModule , ItemContainerId ,
22
- Lookup , TypeAliasId , VariantId ,
20
+ AssocItemId , BlockId , CallableDefId , GenericDefId , HasModule , ItemContainerId , Lookup ,
21
+ TypeAliasId , VariantId ,
23
22
data:: { TraitFlags , adt:: StructFlags } ,
24
- generics:: { GenericParams , TypeOrConstParamData } ,
25
23
hir:: Movability ,
26
24
lang_item:: { LangItem , LangItemTarget } ,
27
25
} ;
28
26
29
27
use crate :: {
30
- AliasEq , AliasTy , BoundVar , Const , ConstData , ConstValue , DebruijnIndex , DomainGoal , FnDefId ,
31
- Goal , GoalData , InferenceTable , Interner , Lifetime , LifetimeData , PlaceholderIndex ,
32
- ProjectionTy , ProjectionTyExt , QuantifiedWhereClause , Substitution , TraitRef , TraitRefExt , Ty ,
33
- TyBuilder , TyExt , TyKind , VariableKinds , WhereClause ,
34
- db:: {
35
- HirDatabase , InternedCoroutine , RpititImplAssocTy , RpititImplAssocTyId ,
36
- RpititTraitAssocTyId ,
37
- } ,
38
- from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
28
+ AliasEq , AliasTy , BoundVar , DebruijnIndex , FnDefId , Interner , ProjectionTy , ProjectionTyExt ,
29
+ QuantifiedWhereClause , Substitution , TraitRef , TraitRefExt , Ty , TyBuilder , TyExt , TyKind ,
30
+ VariableKinds , WhereClause ,
31
+ db:: { HirDatabase , InternedCoroutine } ,
32
+ from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
39
33
generics:: generics,
40
34
lower:: trait_fn_signature,
41
- lt_from_placeholder_idx , make_binders, make_single_type_binders,
35
+ make_binders, make_single_type_binders,
42
36
mapping:: {
43
37
AnyImplAssocType , AnyTraitAssocType , ToChalk , from_assoc_type_value_id, from_chalk,
44
38
to_assoc_type_id_rpitit, to_assoc_type_value_id, to_assoc_type_value_id_rpitit,
45
39
} ,
46
40
method_resolution:: { ALL_FLOAT_FPS , ALL_INT_FPS , TraitImpls , TyFingerprint } ,
41
+ rpitit:: { RpititImplAssocTy , RpititImplAssocTyId , impl_method_rpitit_values} ,
47
42
to_assoc_type_id, to_chalk_trait_id,
48
43
traits:: ChalkContext ,
49
44
utils:: ClosureSubst ,
@@ -952,265 +947,6 @@ fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId)
952
947
Arc :: new ( impl_datum)
953
948
}
954
949
955
- // We return a list and not a hasmap because the number of RPITITs in a function should be small.
956
- #[ salsa:: tracked( return_ref) ]
957
- fn impl_method_rpitit_values (
958
- db : & dyn HirDatabase ,
959
- impl_id : hir_def:: ImplId ,
960
- trait_method_id : FunctionId ,
961
- ) -> Box < [ Arc < AssociatedTyValue > ] > {
962
- let impl_items = db. impl_items ( impl_id) ;
963
- let trait_method_generics = generics ( db. upcast ( ) , trait_method_id. into ( ) ) ;
964
- let impl_datum =
965
- db. impl_datum ( impl_id. loc ( db) . container . krate ( ) , hir_def:: ImplId :: to_chalk ( impl_id, db) ) ;
966
- let trait_method = db. function_data ( trait_method_id) ;
967
- let Some ( impl_method) = impl_items. items . iter ( ) . find_map ( |( name, id) | {
968
- if * name == trait_method. name {
969
- match * id {
970
- AssocItemId :: FunctionId ( it) => Some ( it) ,
971
- _ => None ,
972
- }
973
- } else {
974
- None
975
- }
976
- } ) else {
977
- // FIXME: Handle defaulted methods.
978
- return Box :: default ( ) ;
979
- } ;
980
-
981
- let impl_method_generics = generics ( db. upcast ( ) , impl_method. into ( ) ) ;
982
-
983
- // First, just so we won't ICE, check that the impl method generics match the trait method generics.
984
- if !check_method_generics_are_structurally_compatible (
985
- trait_method_generics. self_params ( ) ,
986
- impl_method_generics. self_params ( ) ,
987
- ) {
988
- return Box :: default ( ) ;
989
- }
990
-
991
- // The inference algorithm works as follows: in the trait method, we replace each RPITIT with an infer var,
992
- // then we equate the return type of the trait method with the return type of the impl method. The values
993
- // of the inference vars now represent the value of the RPITIT assoc types.
994
- let mut table = InferenceTable :: new ( db, db. trait_environment ( impl_method. into ( ) ) ) ;
995
- let impl_method_placeholder_subst = impl_method_generics. placeholder_subst ( db) ;
996
-
997
- let impl_method_ret = db
998
- . callable_item_signature ( impl_method. into ( ) )
999
- . substitute ( Interner , & impl_method_placeholder_subst)
1000
- . ret ( )
1001
- . clone ( ) ;
1002
- let impl_method_ret = table. normalize_associated_types_in ( impl_method_ret) ;
1003
-
1004
- // Create mapping from trait to impl (i.e. impl trait header + impl method identity args).
1005
- let trait_ref_placeholder_subst =
1006
- & impl_method_placeholder_subst. as_slice ( Interner ) [ impl_method_generics. len_self ( ) ..] ;
1007
- // We want to substitute the TraitRef with placeholders, but placeholders from the method, not the impl.
1008
- let impl_trait_ref = impl_datum
1009
- . binders
1010
- . as_ref ( )
1011
- . map ( |it| it. trait_ref . clone ( ) )
1012
- . substitute ( Interner , trait_ref_placeholder_subst) ;
1013
- let trait_to_impl_args = Substitution :: from_iter (
1014
- Interner ,
1015
- impl_method_placeholder_subst. as_slice ( Interner ) [ ..impl_method_generics. len_self ( ) ]
1016
- . iter ( )
1017
- . chain ( impl_trait_ref. substitution . as_slice ( Interner ) ) ,
1018
- ) ;
1019
- let trait_method_ret = db
1020
- . callable_item_signature ( trait_method_id. into ( ) )
1021
- . substitute ( Interner , & trait_to_impl_args)
1022
- . ret ( )
1023
- . clone ( ) ;
1024
- let mut rpitit_to_infer_var_folder = RpititToInferVarFolder {
1025
- db,
1026
- table : & mut table,
1027
- trait_method_id,
1028
- trait_rpitit_to_infer_var : FxHashMap :: default ( ) ,
1029
- } ;
1030
- let trait_method_ret =
1031
- trait_method_ret. fold_with ( & mut rpitit_to_infer_var_folder, DebruijnIndex :: INNERMOST ) ;
1032
- let trait_rpitit_to_infer_var = rpitit_to_infer_var_folder. trait_rpitit_to_infer_var ;
1033
- let trait_method_ret = table. normalize_associated_types_in ( trait_method_ret) ;
1034
-
1035
- table. resolve_obligations_as_possible ( ) ;
1036
- // Even if unification fails, we want to continue. We will fill the RPITITs with error types.
1037
- table. unify ( & trait_method_ret, & impl_method_ret) ;
1038
- table. resolve_obligations_as_possible ( ) ;
1039
-
1040
- return trait_rpitit_to_infer_var
1041
- . into_iter ( )
1042
- . map ( |( trait_assoc_id, infer_var) | {
1043
- let impl_rpitit = table. resolve_completely ( infer_var) ;
1044
- let impl_rpitit = impl_rpitit. fold_with (
1045
- & mut PlaceholderToBoundVarFolder {
1046
- db,
1047
- method : impl_method. into ( ) ,
1048
- method_generics : impl_method_generics. self_params ( ) ,
1049
- } ,
1050
- DebruijnIndex :: INNERMOST ,
1051
- ) ;
1052
- let trait_assoc = trait_assoc_id. loc ( db) ;
1053
- // Completely unlike the docs, Chalk requires both the impl generics and the associated type
1054
- // generics in the binder.
1055
- let impl_rpitit_binders = VariableKinds :: from_iter (
1056
- Interner ,
1057
- trait_assoc. bounds . binders . as_slice ( Interner ) [ ..trait_method_generics. len ( ) ]
1058
- . iter ( )
1059
- . cloned ( )
1060
- . chain ( variable_kinds_from_generics ( db, impl_method_generics. iter_parent_id ( ) ) ) ,
1061
- ) ;
1062
- let impl_rpitit = Binders :: new (
1063
- impl_rpitit_binders,
1064
- rust_ir:: AssociatedTyValueBound { ty : impl_rpitit } ,
1065
- ) ;
1066
- Arc :: new ( AssociatedTyValue {
1067
- associated_ty_id : to_assoc_type_id_rpitit ( trait_assoc_id) ,
1068
- impl_id : hir_def:: ImplId :: to_chalk ( impl_id, db) ,
1069
- value : impl_rpitit,
1070
- } )
1071
- } )
1072
- . collect ( ) ;
1073
-
1074
- #[ derive( chalk_derive:: FallibleTypeFolder ) ]
1075
- #[ has_interner( Interner ) ]
1076
- struct RpititToInferVarFolder < ' a , ' b > {
1077
- db : & ' a dyn HirDatabase ,
1078
- table : & ' a mut InferenceTable < ' b > ,
1079
- trait_rpitit_to_infer_var : FxHashMap < RpititTraitAssocTyId , Ty > ,
1080
- trait_method_id : FunctionId ,
1081
- }
1082
- impl TypeFolder < Interner > for RpititToInferVarFolder < ' _ , ' _ > {
1083
- fn as_dyn ( & mut self ) -> & mut dyn TypeFolder < Interner > {
1084
- self
1085
- }
1086
-
1087
- fn interner ( & self ) -> Interner {
1088
- Interner
1089
- }
1090
-
1091
- fn fold_ty ( & mut self , ty : Ty , outer_binder : DebruijnIndex ) -> Ty {
1092
- let result = match ty. kind ( Interner ) {
1093
- TyKind :: Alias ( AliasTy :: Projection ( ProjectionTy {
1094
- associated_ty_id,
1095
- substitution,
1096
- } ) )
1097
- | TyKind :: AssociatedType ( associated_ty_id, substitution) => {
1098
- if let AnyTraitAssocType :: Rpitit ( assoc_id) =
1099
- from_assoc_type_id ( self . db , * associated_ty_id)
1100
- {
1101
- let assoc = assoc_id. loc ( self . db ) ;
1102
- if assoc. synthesized_from_method == self . trait_method_id {
1103
- if let Some ( ty) = self . trait_rpitit_to_infer_var . get ( & assoc_id) {
1104
- return ty. clone ( ) ;
1105
- }
1106
-
1107
- // Replace with new infer var.
1108
- // This needs to come before we fold the bounds, because they also contain this associated type.
1109
- let var = self . table . new_type_var ( ) ;
1110
- self . trait_rpitit_to_infer_var . insert ( assoc_id, var. clone ( ) ) ;
1111
-
1112
- // Recurse into bounds, so that nested RPITITs will be handled correctly.
1113
- for bound in assoc. bounds . clone ( ) . substitute ( Interner , substitution) {
1114
- let bound = inline_bound_to_generic_predicate ( & bound, var. clone ( ) ) ;
1115
- let bound = bound. fold_with ( self , outer_binder) ;
1116
- let bound = self . table . normalize_associated_types_in ( bound) ;
1117
- self . table . register_obligation ( Goal :: new (
1118
- Interner ,
1119
- GoalData :: Quantified (
1120
- chalk_ir:: QuantifierKind :: ForAll ,
1121
- bound. map ( |bound| {
1122
- Goal :: new (
1123
- Interner ,
1124
- GoalData :: DomainGoal ( DomainGoal :: Holds ( bound) ) ,
1125
- )
1126
- } ) ,
1127
- ) ,
1128
- ) ) ;
1129
- }
1130
-
1131
- return var;
1132
- }
1133
- }
1134
- ty. clone ( )
1135
- }
1136
- _ => ty. clone ( ) ,
1137
- } ;
1138
- result. super_fold_with ( self , outer_binder)
1139
- }
1140
- }
1141
-
1142
- #[ derive( chalk_derive:: FallibleTypeFolder ) ]
1143
- #[ has_interner( Interner ) ]
1144
- struct PlaceholderToBoundVarFolder < ' a > {
1145
- db : & ' a dyn HirDatabase ,
1146
- method : GenericDefId ,
1147
- method_generics : & ' a GenericParams ,
1148
- }
1149
- impl TypeFolder < Interner > for PlaceholderToBoundVarFolder < ' _ > {
1150
- fn as_dyn ( & mut self ) -> & mut dyn TypeFolder < Interner > {
1151
- self
1152
- }
1153
-
1154
- fn interner ( & self ) -> Interner {
1155
- Interner
1156
- }
1157
-
1158
- fn fold_free_placeholder_ty (
1159
- & mut self ,
1160
- universe : PlaceholderIndex ,
1161
- _outer_binder : DebruijnIndex ,
1162
- ) -> Ty {
1163
- let placeholder = from_placeholder_idx ( self . db , universe) ;
1164
- if placeholder. parent == self . method {
1165
- BoundVar :: new (
1166
- DebruijnIndex :: INNERMOST ,
1167
- placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize
1168
- + self . method_generics . len_lifetimes ( ) ,
1169
- )
1170
- . to_ty ( Interner )
1171
- } else {
1172
- TyKind :: Placeholder ( universe) . intern ( Interner )
1173
- }
1174
- }
1175
-
1176
- fn fold_free_placeholder_const (
1177
- & mut self ,
1178
- ty : Ty ,
1179
- universe : PlaceholderIndex ,
1180
- _outer_binder : DebruijnIndex ,
1181
- ) -> Const {
1182
- let placeholder = from_placeholder_idx ( self . db , universe) ;
1183
- if placeholder. parent == self . method {
1184
- BoundVar :: new (
1185
- DebruijnIndex :: INNERMOST ,
1186
- placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize
1187
- + self . method_generics . len_lifetimes ( ) ,
1188
- )
1189
- . to_const ( Interner , ty)
1190
- } else {
1191
- Const :: new ( Interner , ConstData { ty, value : ConstValue :: Placeholder ( universe) } )
1192
- }
1193
- }
1194
-
1195
- fn fold_free_placeholder_lifetime (
1196
- & mut self ,
1197
- universe : PlaceholderIndex ,
1198
- _outer_binder : DebruijnIndex ,
1199
- ) -> Lifetime {
1200
- let placeholder = lt_from_placeholder_idx ( self . db , universe) ;
1201
- if placeholder. parent == self . method {
1202
- BoundVar :: new (
1203
- DebruijnIndex :: INNERMOST ,
1204
- placeholder. local_id . into_raw ( ) . into_u32 ( ) as usize ,
1205
- )
1206
- . to_lifetime ( Interner )
1207
- } else {
1208
- Lifetime :: new ( Interner , LifetimeData :: Placeholder ( universe) )
1209
- }
1210
- }
1211
- }
1212
- }
1213
-
1214
950
pub ( crate ) fn inline_bound_to_generic_predicate (
1215
951
bound : & Binders < rust_ir:: InlineBound < Interner > > ,
1216
952
self_ty : Ty ,
@@ -1250,29 +986,6 @@ pub(crate) fn inline_bound_to_generic_predicate(
1250
986
}
1251
987
}
1252
988
1253
- fn check_method_generics_are_structurally_compatible (
1254
- trait_method_generics : & GenericParams ,
1255
- impl_method_generics : & GenericParams ,
1256
- ) -> bool {
1257
- if trait_method_generics. len_type_or_consts ( ) != impl_method_generics. len_type_or_consts ( ) {
1258
- return false ;
1259
- }
1260
-
1261
- for ( ( _, trait_arg) , ( _, impl_arg) ) in iter:: zip (
1262
- trait_method_generics. iter_type_or_consts ( ) ,
1263
- impl_method_generics. iter_type_or_consts ( ) ,
1264
- ) {
1265
- match ( trait_arg, impl_arg) {
1266
- ( TypeOrConstParamData :: TypeParamData ( _) , TypeOrConstParamData :: TypeParamData ( _) )
1267
- | ( TypeOrConstParamData :: ConstParamData ( _) , TypeOrConstParamData :: ConstParamData ( _) ) => {
1268
- }
1269
- _ => return false ,
1270
- }
1271
- }
1272
-
1273
- true
1274
- }
1275
-
1276
989
pub ( crate ) fn associated_ty_value_query (
1277
990
db : & dyn HirDatabase ,
1278
991
krate : Crate ,
0 commit comments