@@ -835,18 +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
- if self . can_use_global_caches ( param_env) {
839
- let cache = tcx. evaluation_cache . hashmap . borrow ( ) ;
840
- if let Some ( cached) = cache. get ( & param_env. and ( trait_ref) ) {
841
- return Some ( cached. get ( tcx) ) ;
842
- }
843
- }
844
- self . infcx
845
- . evaluation_cache
846
- . hashmap
847
- . borrow ( )
848
- . get ( & param_env. and ( trait_ref) )
849
- . map ( |v| v. get ( tcx) )
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) {
843
+ & tcx. evaluation_cache
844
+ } else {
845
+ & self . infcx . evaluation_cache
846
+ } ;
847
+
848
+ cache. hashmap . borrow ( ) . get ( & cache_key) . map ( |v| v. get ( tcx) )
850
849
}
851
850
852
851
fn insert_evaluation_cache (
@@ -862,31 +861,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
862
861
return ;
863
862
}
864
863
865
- if self . can_use_global_caches ( param_env ) {
866
- if ! trait_ref. has_local_value ( ) {
867
- debug ! (
868
- "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global" ,
869
- trait_ref , result ,
870
- ) ;
871
- // This may overwrite the cache with the same value
872
- // FIXME: Due to #50507 this overwrites the different values
873
- // This should be changed to use HashMapExt::insert_same
874
- // when that is fixed
875
- self . tcx ( )
876
- . evaluation_cache
877
- . hashmap
878
- . borrow_mut ( )
879
- . insert ( param_env . and ( trait_ref ) , WithDepNode :: new ( dep_node , result ) ) ;
880
- return ;
881
- }
882
- }
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 ) {
869
+ debug ! (
870
+ "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global" ,
871
+ trait_ref , result ,
872
+ ) ;
873
+ // This may overwrite the cache with the same value
874
+ // FIXME: Due to #50507 this overwrites the different values
875
+ // This should be changed to use HashMapExt::insert_same
876
+ // when that is fixed
877
+ & self . tcx ( ) . evaluation_cache
878
+ } else {
879
+ debug ! ( "insert_evaluation_cache(trait_ref={:?}, candidate={:?})" , trait_ref , result , ) ;
880
+ & self . infcx . evaluation_cache
881
+ } ;
883
882
884
- debug ! ( "insert_evaluation_cache(trait_ref={:?}, candidate={:?})" , trait_ref, result, ) ;
885
- self . infcx
886
- . evaluation_cache
887
- . hashmap
888
- . borrow_mut ( )
889
- . insert ( param_env. and ( trait_ref) , WithDepNode :: new ( dep_node, result) ) ;
883
+ cache. hashmap . borrow_mut ( ) . insert ( cache_key, WithDepNode :: new ( dep_node, result) ) ;
890
884
}
891
885
892
886
/// For various reasons, it's possible for a subobligation
@@ -961,7 +955,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
961
955
debug_assert ! ( !stack. obligation. predicate. has_escaping_bound_vars( ) ) ;
962
956
963
957
if let Some ( c) =
964
- 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)
965
959
{
966
960
debug ! ( "CACHE HIT: SELECT({:?})={:?}" , cache_fresh_trait_pred, c) ;
967
961
return c;
@@ -982,6 +976,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
982
976
cache_fresh_trait_pred,
983
977
dep_node,
984
978
candidate. clone ( ) ,
979
+ stack. obligation . cause . span ,
985
980
) ;
986
981
candidate
987
982
}
@@ -1218,13 +1213,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1218
1213
}
1219
1214
1220
1215
/// Returns `true` if the global caches can be used.
1221
- /// Do note that if the type itself is not in the
1222
- /// global tcx, the local caches will be used.
1223
- fn can_use_global_caches ( & self , param_env : ty:: ParamEnv < ' tcx > ) -> bool {
1224
- // If there are any e.g. inference variables in the `ParamEnv`, then we
1225
- // always use a cache local to this particular scope. Otherwise, we
1226
- // switch to a global cache.
1227
- 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 ( ) {
1228
1224
return false ;
1229
1225
}
1230
1226
@@ -1246,22 +1242,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1246
1242
fn check_candidate_cache (
1247
1243
& mut self ,
1248
1244
param_env : ty:: ParamEnv < ' tcx > ,
1249
- cache_fresh_trait_pred : & ty:: PolyTraitPredicate < ' tcx > ,
1245
+ cache_fresh_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
1250
1246
) -> Option < SelectionResult < ' tcx , SelectionCandidate < ' tcx > > > {
1251
1247
let tcx = self . tcx ( ) ;
1252
- let trait_ref = & cache_fresh_trait_pred. skip_binder ( ) . trait_ref ;
1253
- if self . can_use_global_caches ( param_env) {
1254
- let cache = tcx. selection_cache . hashmap . borrow ( ) ;
1255
- if let Some ( cached) = cache. get ( & param_env. and ( * trait_ref) ) {
1256
- return Some ( cached. get ( tcx) ) ;
1257
- }
1258
- }
1259
- self . infcx
1260
- . selection_cache
1261
- . hashmap
1262
- . borrow ( )
1263
- . get ( & param_env. and ( * trait_ref) )
1264
- . map ( |v| v. get ( tcx) )
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) {
1251
+ & tcx. selection_cache
1252
+ } else {
1253
+ & self . infcx . selection_cache
1254
+ } ;
1255
+
1256
+ cache. hashmap . borrow ( ) . get ( & cache_key) . map ( |v| v. get ( tcx) )
1265
1257
}
1266
1258
1267
1259
/// Determines whether can we safely cache the result
@@ -1298,47 +1290,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1298
1290
cache_fresh_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
1299
1291
dep_node : DepNodeIndex ,
1300
1292
candidate : SelectionResult < ' tcx , SelectionCandidate < ' tcx > > ,
1293
+ span : rustc_span:: Span ,
1301
1294
) {
1302
1295
let tcx = self . tcx ( ) ;
1303
- let trait_ref = cache_fresh_trait_pred. skip_binder ( ) . trait_ref ;
1304
1296
1305
1297
if !self . can_cache_candidate ( & candidate) {
1306
1298
debug ! (
1307
- "insert_candidate_cache(trait_ref ={:?}, candidate={:?} -\
1299
+ "insert_candidate_cache(predicate ={:?}, candidate={:?} -\
1308
1300
candidate is not cacheable",
1309
- trait_ref , candidate
1301
+ cache_fresh_trait_pred , candidate
1310
1302
) ;
1311
1303
return ;
1312
1304
}
1313
1305
1314
- if self . can_use_global_caches ( param_env) {
1315
- if let Err ( Overflow ) = candidate {
1316
- // Don't cache overflow globally; we only produce this in certain modes.
1317
- } else if !trait_ref. has_local_value ( ) {
1318
- if !candidate. has_local_value ( ) {
1319
- debug ! (
1320
- "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global" ,
1321
- trait_ref, candidate,
1322
- ) ;
1323
- // This may overwrite the cache with the same value.
1324
- tcx. selection_cache
1325
- . hashmap
1326
- . borrow_mut ( )
1327
- . insert ( param_env. and ( trait_ref) , WithDepNode :: new ( dep_node, candidate) ) ;
1328
- return ;
1329
- }
1330
- }
1306
+ // HACK(eddyb) never cache overflow (this check used to be global-only).
1307
+ if let Err ( Overflow ) = candidate {
1308
+ return ;
1331
1309
}
1332
1310
1333
- debug ! (
1334
- "insert_candidate_cache(trait_ref={:?}, candidate={:?}) local" ,
1335
- trait_ref, candidate,
1336
- ) ;
1337
- self . infcx
1338
- . selection_cache
1339
- . hashmap
1340
- . borrow_mut ( )
1341
- . insert ( param_env. and ( trait_ref) , WithDepNode :: new ( dep_node, candidate) ) ;
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) {
1314
+ if candidate. has_local_value ( ) {
1315
+ span_bug ! (
1316
+ span,
1317
+ "selecting inference-free `{:?}` resulted in `{:?}`?!" ,
1318
+ cache_fresh_trait_pred,
1319
+ candidate,
1320
+ ) ;
1321
+ }
1322
+ debug ! (
1323
+ "insert_candidate_cache(predicate={:?}, candidate={:?}) global" ,
1324
+ cache_fresh_trait_pred, candidate,
1325
+ ) ;
1326
+ // This may overwrite the cache with the same value.
1327
+ & tcx. selection_cache
1328
+ } else {
1329
+ debug ! (
1330
+ "insert_candidate_cache(predicate={:?}, candidate={:?}) local" ,
1331
+ cache_fresh_trait_pred, candidate,
1332
+ ) ;
1333
+ & self . infcx . selection_cache
1334
+ } ;
1335
+
1336
+ cache. hashmap . borrow_mut ( ) . insert ( cache_key, WithDepNode :: new ( dep_node, candidate) ) ;
1342
1337
}
1343
1338
1344
1339
fn assemble_candidates < ' o > (
0 commit comments