Skip to content

Commit c07aa1e

Browse files
committed
Auto merge of rust-lang#132625 - compiler-errors:cache-only-if-opaque, r=lcnr
Only disable cache if predicate has opaques within it This is an alternative to rust-lang#132075. This refines the check implemented in rust-lang#126024 to only disable the global cache if the predicate being considered has opaques in it. This is still theoretically unsound, since goals can indirectly rely on opaques in the defining scope, but we're much less likely to hit it. It doesn't totally fix rust-lang#132064: for example, `lemmy` goes from 1:29 (on rust 1.81) to 9:53 (on nightly) to 4:07 (after this PR). But I think it's at least *more* sound than a total revert :/ r? lcnr
2 parents 8549802 + 4915373 commit c07aa1e

File tree

1 file changed

+18
-6
lines changed
  • compiler/rustc_trait_selection/src/traits/select

1 file changed

+18
-6
lines changed

compiler/rustc_trait_selection/src/traits/select/mod.rs

+18-6
Original file line numberDiff line numberDiff line change
@@ -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 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+
}
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

Comments
 (0)