@@ -1310,7 +1310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13101310 trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
13111311 ) -> Option < EvaluationResult > {
13121312 let tcx = self . tcx ( ) ;
1313- if self . can_use_global_caches ( param_env) {
1313+ if self . can_use_global_caches ( param_env, trait_pred ) {
13141314 if let Some ( res) = tcx. evaluation_cache . get ( & ( param_env, trait_pred) , tcx) {
13151315 return Some ( res) ;
13161316 }
@@ -1331,7 +1331,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13311331 return ;
13321332 }
13331333
1334- if self . can_use_global_caches ( param_env) && !trait_pred. has_infer ( ) {
1334+ if self . can_use_global_caches ( param_env, trait_pred ) && !trait_pred. has_infer ( ) {
13351335 debug ! ( ?trait_pred, ?result, "insert_evaluation_cache global" ) ;
13361336 // This may overwrite the cache with the same value
13371337 // FIXME: Due to #50507 this overwrites the different values
@@ -1476,7 +1476,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14761476 }
14771477
14781478 /// Returns `true` if the global caches can be used.
1479- fn can_use_global_caches ( & self , param_env : ty:: ParamEnv < ' tcx > ) -> bool {
1479+ fn can_use_global_caches (
1480+ & self ,
1481+ param_env : ty:: ParamEnv < ' tcx > ,
1482+ pred : ty:: PolyTraitPredicate < ' tcx > ,
1483+ ) -> bool {
14801484 // If there are any inference variables in the `ParamEnv`, then we
14811485 // always use a cache local to this particular scope. Otherwise, we
14821486 // switch to a global cache.
@@ -1494,7 +1498,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14941498 TypingMode :: Coherence => false ,
14951499 // Avoid using the global cache when we're defining opaque types
14961500 // as their hidden type may impact the result of candidate selection.
1497- TypingMode :: Analysis { defining_opaque_types } => defining_opaque_types. is_empty ( ) ,
1501+ //
1502+ // HACK: This is still theoretically unsound. Goals can indirectly rely
1503+ // on opaquesvin the defining scope, and it's easier to do so with TAIT.
1504+ // However, if we disqualify *all* goals from being cached, perf suffers.
1505+ // This is likely fixed by better caching in general in the new solver.
1506+ // See: <https://github.com/rust-lang/rust/issues/132064>.
1507+ TypingMode :: Analysis { defining_opaque_types } => {
1508+ defining_opaque_types. is_empty ( ) || !pred. has_opaque_types ( )
1509+ }
14981510 // The global cache is only used if there are no opaque types in
14991511 // the defining scope or we're outside of analysis.
15001512 //
@@ -1512,7 +1524,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15121524 let tcx = self . tcx ( ) ;
15131525 let pred = cache_fresh_trait_pred. skip_binder ( ) ;
15141526
1515- if self . can_use_global_caches ( param_env) {
1527+ if self . can_use_global_caches ( param_env, cache_fresh_trait_pred ) {
15161528 if let Some ( res) = tcx. selection_cache . get ( & ( param_env, pred) , tcx) {
15171529 return Some ( res) ;
15181530 }
@@ -1562,7 +1574,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15621574 return ;
15631575 }
15641576
1565- if self . can_use_global_caches ( param_env) {
1577+ if self . can_use_global_caches ( param_env, cache_fresh_trait_pred ) {
15661578 if let Err ( Overflow ( OverflowError :: Canonical ) ) = candidate {
15671579 // Don't cache overflow globally; we only produce this in certain modes.
15681580 } else if !pred. has_infer ( ) && !candidate. has_infer ( ) {
0 commit comments