@@ -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
@@ -1286,13 +1293,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1286
1293
span : rustc_span:: Span ,
1287
1294
) {
1288
1295
let tcx = self . tcx ( ) ;
1289
- let trait_ref = cache_fresh_trait_pred. skip_binder ( ) . trait_ref ;
1290
1296
1291
1297
if !self . can_cache_candidate ( & candidate) {
1292
1298
debug ! (
1293
- "insert_candidate_cache(trait_ref ={:?}, candidate={:?} -\
1299
+ "insert_candidate_cache(predicate ={:?}, candidate={:?} -\
1294
1300
candidate is not cacheable",
1295
- trait_ref , candidate
1301
+ cache_fresh_trait_pred , candidate
1296
1302
) ;
1297
1303
return ;
1298
1304
}
@@ -1302,33 +1308,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1302
1308
return ;
1303
1309
}
1304
1310
1305
- let cache = if self . can_use_global_caches ( param_env) && !trait_ref. has_local_value ( ) {
1311
+ // FIXME(eddyb) reuse the key between checking the cache and inserting.
1312
+ let cache_key = param_env. and ( cache_fresh_trait_pred) ;
1313
+ let cache = if self . can_use_global_caches ( & cache_key) {
1306
1314
if candidate. has_local_value ( ) {
1307
1315
span_bug ! (
1308
1316
span,
1309
- "selecting inference-free `{}` resulted in `{:?}`?!" ,
1310
- trait_ref ,
1317
+ "selecting inference-free `{:? }` resulted in `{:?}`?!" ,
1318
+ cache_fresh_trait_pred ,
1311
1319
candidate,
1312
1320
) ;
1313
1321
}
1314
1322
debug ! (
1315
- "insert_candidate_cache(trait_ref ={:?}, candidate={:?}) global" ,
1316
- trait_ref , candidate,
1323
+ "insert_candidate_cache(predicate ={:?}, candidate={:?}) global" ,
1324
+ cache_fresh_trait_pred , candidate,
1317
1325
) ;
1318
1326
// This may overwrite the cache with the same value.
1319
1327
& tcx. selection_cache
1320
1328
} else {
1321
1329
debug ! (
1322
- "insert_candidate_cache(trait_ref ={:?}, candidate={:?}) local" ,
1323
- trait_ref , candidate,
1330
+ "insert_candidate_cache(predicate ={:?}, candidate={:?}) local" ,
1331
+ cache_fresh_trait_pred , candidate,
1324
1332
) ;
1325
1333
& self . infcx . selection_cache
1326
1334
} ;
1327
1335
1328
- cache
1329
- . hashmap
1330
- . borrow_mut ( )
1331
- . insert ( param_env. and ( trait_ref) , WithDepNode :: new ( dep_node, candidate) ) ;
1336
+ cache. hashmap . borrow_mut ( ) . insert ( cache_key, WithDepNode :: new ( dep_node, candidate) ) ;
1332
1337
}
1333
1338
1334
1339
fn assemble_candidates < ' o > (
0 commit comments