@@ -5,45 +5,40 @@ use std::{iter, ops::ControlFlow, sync::Arc};
55
66use hir_expand:: name:: Name ;
77use intern:: sym;
8- use rustc_hash:: FxHashMap ;
98use span:: Edition ;
109use tracing:: debug;
1110
1211use chalk_ir:: {
1312 Binders , CanonicalVarKinds ,
1413 cast:: { Cast , Caster } ,
15- fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable , shift:: Shift } ,
14+ fold:: shift:: Shift ,
1615} ;
1716use chalk_solve:: rust_ir:: { self , AssociatedTyDatumBound , OpaqueTyDatumBound , WellKnownTrait } ;
1817
1918use base_db:: Crate ;
2019use 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 ,
2322 data:: { TraitFlags , adt:: StructFlags } ,
24- generics:: { GenericParams , TypeOrConstParamData } ,
2523 hir:: Movability ,
2624 lang_item:: { LangItem , LangItemTarget } ,
2725} ;
2826
2927use 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,
3933 generics:: generics,
4034 lower:: trait_fn_signature,
41- lt_from_placeholder_idx , make_binders, make_single_type_binders,
35+ make_binders, make_single_type_binders,
4236 mapping:: {
4337 AnyImplAssocType , AnyTraitAssocType , ToChalk , from_assoc_type_value_id, from_chalk,
4438 to_assoc_type_id_rpitit, to_assoc_type_value_id, to_assoc_type_value_id_rpitit,
4539 } ,
4640 method_resolution:: { ALL_FLOAT_FPS , ALL_INT_FPS , TraitImpls , TyFingerprint } ,
41+ rpitit:: { RpititImplAssocTy , RpititImplAssocTyId , impl_method_rpitit_values} ,
4742 to_assoc_type_id, to_chalk_trait_id,
4843 traits:: ChalkContext ,
4944 utils:: ClosureSubst ,
@@ -952,265 +947,6 @@ fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId)
952947 Arc :: new ( impl_datum)
953948}
954949
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-
1214950pub ( crate ) fn inline_bound_to_generic_predicate (
1215951 bound : & Binders < rust_ir:: InlineBound < Interner > > ,
1216952 self_ty : Ty ,
@@ -1250,29 +986,6 @@ pub(crate) fn inline_bound_to_generic_predicate(
1250986 }
1251987}
1252988
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-
1276989pub ( crate ) fn associated_ty_value_query (
1277990 db : & dyn HirDatabase ,
1278991 krate : Crate ,
0 commit comments