@@ -835,13 +835,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
835
835
trait_ref : ty:: PolyTraitRef < ' tcx > ,
836
836
) -> Option < EvaluationResult > {
837
837
let tcx = self . tcx ( ) ;
838
- let cache = if self . can_use_global_caches ( param_env) && !trait_ref. has_local_value ( ) {
838
+ // FIXME(eddyb) pass in the `ty::PolyTraitPredicate` instead.
839
+ let predicate = trait_ref. map_bound ( |trait_ref| ty:: TraitPredicate { trait_ref } ) ;
840
+ // FIXME(eddyb) reuse the key between checking the cache and inserting.
841
+ let cache_key = param_env. and ( predicate) ;
842
+ let cache = if self . can_use_global_caches ( & cache_key) {
839
843
& tcx. evaluation_cache
840
844
} else {
841
845
& self . infcx . evaluation_cache
842
846
} ;
843
847
844
- cache. hashmap . borrow ( ) . get ( & param_env . and ( trait_ref ) ) . map ( |v| v. get ( tcx) )
848
+ cache. hashmap . borrow ( ) . get ( & cache_key ) . map ( |v| v. get ( tcx) )
845
849
}
846
850
847
851
fn insert_evaluation_cache (
@@ -857,7 +861,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
857
861
return ;
858
862
}
859
863
860
- let cache = if self . can_use_global_caches ( param_env) && !trait_ref. has_local_value ( ) {
864
+ // FIXME(eddyb) pass in the `ty::PolyTraitPredicate` instead.
865
+ let predicate = trait_ref. map_bound ( |trait_ref| ty:: TraitPredicate { trait_ref } ) ;
866
+ // FIXME(eddyb) reuse the key between checking the cache and inserting.
867
+ let cache_key = param_env. and ( predicate) ;
868
+ let cache = if self . can_use_global_caches ( & cache_key) {
861
869
debug ! (
862
870
"insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global" ,
863
871
trait_ref, result,
@@ -872,10 +880,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
872
880
& self . infcx . evaluation_cache
873
881
} ;
874
882
875
- cache
876
- . hashmap
877
- . borrow_mut ( )
878
- . insert ( param_env. and ( trait_ref) , WithDepNode :: new ( dep_node, result) ) ;
883
+ cache. hashmap . borrow_mut ( ) . insert ( cache_key, WithDepNode :: new ( dep_node, result) ) ;
879
884
}
880
885
881
886
/// For various reasons, it's possible for a subobligation
@@ -950,7 +955,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
950
955
debug_assert ! ( !stack. obligation. predicate. has_escaping_bound_vars( ) ) ;
951
956
952
957
if let Some ( c) =
953
- self . check_candidate_cache ( stack. obligation . param_env , & cache_fresh_trait_pred)
958
+ self . check_candidate_cache ( stack. obligation . param_env , cache_fresh_trait_pred)
954
959
{
955
960
debug ! ( "CACHE HIT: SELECT({:?})={:?}" , cache_fresh_trait_pred, c) ;
956
961
return c;
@@ -1208,13 +1213,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1208
1213
}
1209
1214
1210
1215
/// Returns `true` if the global caches can be used.
1211
- /// Do note that if the type itself is not in the
1212
- /// global tcx, the local caches will be used.
1213
- fn can_use_global_caches ( & self , param_env : ty:: ParamEnv < ' tcx > ) -> bool {
1214
- // If there are any e.g. inference variables in the `ParamEnv`, then we
1215
- // always use a cache local to this particular scope. Otherwise, we
1216
- // switch to a global cache.
1217
- if param_env. has_local_value ( ) {
1216
+ fn can_use_global_caches (
1217
+ & self ,
1218
+ cache_key : & ty:: ParamEnvAnd < ' tcx , ty:: PolyTraitPredicate < ' tcx > > ,
1219
+ ) -> bool {
1220
+ // If there are any e.g. inference variables in the `ParamEnv` or predicate,
1221
+ // then we always use a cache local to this particular inference context.
1222
+ // Otherwise, we switch to a global cache.
1223
+ if cache_key. has_local_value ( ) {
1218
1224
return false ;
1219
1225
}
1220
1226
@@ -1236,17 +1242,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1236
1242
fn check_candidate_cache (
1237
1243
& mut self ,
1238
1244
param_env : ty:: ParamEnv < ' tcx > ,
1239
- cache_fresh_trait_pred : & ty:: PolyTraitPredicate < ' tcx > ,
1245
+ cache_fresh_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
1240
1246
) -> Option < SelectionResult < ' tcx , SelectionCandidate < ' tcx > > > {
1241
1247
let tcx = self . tcx ( ) ;
1242
- let trait_ref = & cache_fresh_trait_pred. skip_binder ( ) . trait_ref ;
1243
- let cache = if self . can_use_global_caches ( param_env) && !trait_ref. has_local_value ( ) {
1248
+ // FIXME(eddyb) reuse the key between checking the cache and inserting.
1249
+ let cache_key = param_env. and ( cache_fresh_trait_pred) ;
1250
+ let cache = if self . can_use_global_caches ( & cache_key) {
1244
1251
& tcx. selection_cache
1245
1252
} else {
1246
1253
& self . infcx . selection_cache
1247
1254
} ;
1248
1255
1249
- cache. hashmap . borrow ( ) . get ( & param_env . and ( * trait_ref ) ) . map ( |v| v. get ( tcx) )
1256
+ cache. hashmap . borrow ( ) . get ( & cache_key ) . map ( |v| v. get ( tcx) )
1250
1257
}
1251
1258
1252
1259
/// Determines whether can we safely cache the result
@@ -1284,13 +1291,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1284
1291
span : rustc_span:: Span ,
1285
1292
) {
1286
1293
let tcx = self . tcx ( ) ;
1287
- let trait_ref = cache_fresh_trait_pred. skip_binder ( ) . trait_ref ;
1288
1294
1289
1295
if !self . can_cache_candidate ( & candidate) {
1290
1296
debug ! (
1291
- "insert_candidate_cache(trait_ref ={:?}, candidate={:?} -\
1297
+ "insert_candidate_cache(predicate ={:?}, candidate={:?} -\
1292
1298
candidate is not cacheable",
1293
- trait_ref , candidate
1299
+ cache_fresh_trait_pred , candidate
1294
1300
) ;
1295
1301
return ;
1296
1302
}
@@ -1300,33 +1306,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1300
1306
return ;
1301
1307
}
1302
1308
1303
- let cache = if self . can_use_global_caches ( param_env) && !trait_ref. has_local_value ( ) {
1309
+ // FIXME(eddyb) reuse the key between checking the cache and inserting.
1310
+ let cache_key = param_env. and ( cache_fresh_trait_pred) ;
1311
+ let cache = if self . can_use_global_caches ( & cache_key) {
1304
1312
if candidate. has_local_value ( ) {
1305
1313
span_bug ! (
1306
1314
span,
1307
- "selecting inference-free `{}` resulted in `{:?}`?!" ,
1308
- trait_ref ,
1315
+ "selecting inference-free `{:? }` resulted in `{:?}`?!" ,
1316
+ cache_fresh_trait_pred ,
1309
1317
candidate,
1310
1318
) ;
1311
1319
}
1312
1320
debug ! (
1313
- "insert_candidate_cache(trait_ref ={:?}, candidate={:?}) global" ,
1314
- trait_ref , candidate,
1321
+ "insert_candidate_cache(predicate ={:?}, candidate={:?}) global" ,
1322
+ cache_fresh_trait_pred , candidate,
1315
1323
) ;
1316
1324
// This may overwrite the cache with the same value.
1317
1325
& tcx. selection_cache
1318
1326
} else {
1319
1327
debug ! (
1320
- "insert_candidate_cache(trait_ref ={:?}, candidate={:?}) local" ,
1321
- trait_ref , candidate,
1328
+ "insert_candidate_cache(predicate ={:?}, candidate={:?}) local" ,
1329
+ cache_fresh_trait_pred , candidate,
1322
1330
) ;
1323
1331
& self . infcx . selection_cache
1324
1332
} ;
1325
1333
1326
- cache
1327
- . hashmap
1328
- . borrow_mut ( )
1329
- . insert ( param_env. and ( trait_ref) , WithDepNode :: new ( dep_node, candidate) ) ;
1334
+ cache. hashmap . borrow_mut ( ) . insert ( cache_key, WithDepNode :: new ( dep_node, candidate) ) ;
1330
1335
}
1331
1336
1332
1337
fn assemble_candidates < ' o > (
0 commit comments