@@ -835,18 +835,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
835835 trait_ref : ty:: PolyTraitRef < ' tcx > ,
836836 ) -> Option < EvaluationResult > {
837837 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) )
850849 }
851850
852851 fn insert_evaluation_cache (
@@ -862,31 +861,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
862861 return ;
863862 }
864863
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+ } ;
883882
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) ) ;
890884 }
891885
892886 /// For various reasons, it's possible for a subobligation
@@ -961,7 +955,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
961955 debug_assert ! ( !stack. obligation. predicate. has_escaping_bound_vars( ) ) ;
962956
963957 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)
965959 {
966960 debug ! ( "CACHE HIT: SELECT({:?})={:?}" , cache_fresh_trait_pred, c) ;
967961 return c;
@@ -982,6 +976,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
982976 cache_fresh_trait_pred,
983977 dep_node,
984978 candidate. clone ( ) ,
979+ stack. obligation . cause . span ,
985980 ) ;
986981 candidate
987982 }
@@ -1218,13 +1213,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12181213 }
12191214
12201215 /// 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 ( ) {
12281224 return false ;
12291225 }
12301226
@@ -1246,22 +1242,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12461242 fn check_candidate_cache (
12471243 & mut self ,
12481244 param_env : ty:: ParamEnv < ' tcx > ,
1249- cache_fresh_trait_pred : & ty:: PolyTraitPredicate < ' tcx > ,
1245+ cache_fresh_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
12501246 ) -> Option < SelectionResult < ' tcx , SelectionCandidate < ' tcx > > > {
12511247 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) )
12651257 }
12661258
12671259 /// Determines whether can we safely cache the result
@@ -1298,47 +1290,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12981290 cache_fresh_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
12991291 dep_node : DepNodeIndex ,
13001292 candidate : SelectionResult < ' tcx , SelectionCandidate < ' tcx > > ,
1293+ span : rustc_span:: Span ,
13011294 ) {
13021295 let tcx = self . tcx ( ) ;
1303- let trait_ref = cache_fresh_trait_pred. skip_binder ( ) . trait_ref ;
13041296
13051297 if !self . can_cache_candidate ( & candidate) {
13061298 debug ! (
1307- "insert_candidate_cache(trait_ref ={:?}, candidate={:?} -\
1299+ "insert_candidate_cache(predicate ={:?}, candidate={:?} -\
13081300 candidate is not cacheable",
1309- trait_ref , candidate
1301+ cache_fresh_trait_pred , candidate
13101302 ) ;
13111303 return ;
13121304 }
13131305
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 ;
13311309 }
13321310
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) ) ;
13421337 }
13431338
13441339 fn assemble_candidates < ' o > (
0 commit comments