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