@@ -1310,7 +1310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1310
1310
trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
1311
1311
) -> Option < EvaluationResult > {
1312
1312
let tcx = self . tcx ( ) ;
1313
- if self . can_use_global_caches ( param_env) {
1313
+ if self . can_use_global_caches ( param_env, trait_pred ) {
1314
1314
if let Some ( res) = tcx. evaluation_cache . get ( & ( param_env, trait_pred) , tcx) {
1315
1315
return Some ( res) ;
1316
1316
}
@@ -1331,7 +1331,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1331
1331
return ;
1332
1332
}
1333
1333
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 ( ) {
1335
1335
debug ! ( ?trait_pred, ?result, "insert_evaluation_cache global" ) ;
1336
1336
// This may overwrite the cache with the same value
1337
1337
// FIXME: Due to #50507 this overwrites the different values
@@ -1476,7 +1476,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1476
1476
}
1477
1477
1478
1478
/// 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 {
1480
1484
// If there are any inference variables in the `ParamEnv`, then we
1481
1485
// always use a cache local to this particular scope. Otherwise, we
1482
1486
// switch to a global cache.
@@ -1494,7 +1498,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1494
1498
TypingMode :: Coherence => false ,
1495
1499
// Avoid using the global cache when we're defining opaque types
1496
1500
// 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 opaques in 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
+ }
1498
1510
// The global cache is only used if there are no opaque types in
1499
1511
// the defining scope or we're outside of analysis.
1500
1512
//
@@ -1512,7 +1524,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1512
1524
let tcx = self . tcx ( ) ;
1513
1525
let pred = cache_fresh_trait_pred. skip_binder ( ) ;
1514
1526
1515
- if self . can_use_global_caches ( param_env) {
1527
+ if self . can_use_global_caches ( param_env, cache_fresh_trait_pred ) {
1516
1528
if let Some ( res) = tcx. selection_cache . get ( & ( param_env, pred) , tcx) {
1517
1529
return Some ( res) ;
1518
1530
}
@@ -1562,7 +1574,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1562
1574
return ;
1563
1575
}
1564
1576
1565
- if self . can_use_global_caches ( param_env) {
1577
+ if self . can_use_global_caches ( param_env, cache_fresh_trait_pred ) {
1566
1578
if let Err ( Overflow ( OverflowError :: Canonical ) ) = candidate {
1567
1579
// Don't cache overflow globally; we only produce this in certain modes.
1568
1580
} else if !pred. has_infer ( ) && !candidate. has_infer ( ) {
0 commit comments