Skip to content

Commit 0ac5a0b

Browse files
committed
global old solver cache: use TypingEnv
1 parent 4498d1f commit 0ac5a0b

File tree

5 files changed

+54
-42
lines changed

5 files changed

+54
-42
lines changed

compiler/rustc_infer/src/infer/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,12 @@ pub struct InferCtxt<'tcx> {
264264
lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
265265

266266
/// Caches the results of trait selection. This cache is used
267-
/// for things that have to do with the parameters in scope.
268-
pub selection_cache: select::SelectionCache<'tcx>,
267+
/// for things that depends on inference variables or placeholders.
268+
pub selection_cache: select::SelectionCache<'tcx, ty::ParamEnv<'tcx>>,
269269

270-
/// Caches the results of trait evaluation.
271-
pub evaluation_cache: select::EvaluationCache<'tcx>,
270+
/// Caches the results of trait evaluation. This cache is used
271+
/// for things that depends on inference variables or placeholders.
272+
pub evaluation_cache: select::EvaluationCache<'tcx, ty::ParamEnv<'tcx>>,
272273

273274
/// The set of predicates on which errors have been reported, to
274275
/// avoid reporting the same error twice.

compiler/rustc_middle/src/traits/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ pub struct DerivedCause<'tcx> {
551551
pub parent_code: InternedObligationCauseCode<'tcx>,
552552
}
553553

554-
#[derive(Clone, Debug, TypeVisitable)]
554+
#[derive(Clone, Debug, PartialEq, Eq, TypeVisitable)]
555555
pub enum SelectionError<'tcx> {
556556
/// The trait is not implemented.
557557
Unimplemented,
@@ -573,7 +573,7 @@ pub enum SelectionError<'tcx> {
573573
ConstArgHasWrongType { ct: ty::Const<'tcx>, ct_ty: Ty<'tcx>, expected_ty: Ty<'tcx> },
574574
}
575575

576-
#[derive(Clone, Debug, TypeVisitable)]
576+
#[derive(Clone, Debug, PartialEq, Eq, TypeVisitable)]
577577
pub struct SignatureMismatchData<'tcx> {
578578
pub found_trait_ref: ty::TraitRef<'tcx>,
579579
pub expected_trait_ref: ty::TraitRef<'tcx>,

compiler/rustc_middle/src/traits/select.rs

+4-14
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,10 @@ use self::EvaluationResult::*;
1111
use super::{SelectionError, SelectionResult};
1212
use crate::ty;
1313

14-
pub type SelectionCache<'tcx> = Cache<
15-
// This cache does not use `ParamEnvAnd` in its keys because `ParamEnv::and` can replace
16-
// caller bounds with an empty list if the `TraitPredicate` looks global, which may happen
17-
// after erasing lifetimes from the predicate.
18-
(ty::ParamEnv<'tcx>, ty::TraitPredicate<'tcx>),
19-
SelectionResult<'tcx, SelectionCandidate<'tcx>>,
20-
>;
21-
22-
pub type EvaluationCache<'tcx> = Cache<
23-
// See above: this cache does not use `ParamEnvAnd` in its keys due to sometimes incorrectly
24-
// caching with the wrong `ParamEnv`.
25-
(ty::ParamEnv<'tcx>, ty::PolyTraitPredicate<'tcx>),
26-
EvaluationResult,
27-
>;
14+
pub type SelectionCache<'tcx, ENV> =
15+
Cache<(ENV, ty::TraitPredicate<'tcx>), SelectionResult<'tcx, SelectionCandidate<'tcx>>>;
16+
17+
pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>), EvaluationResult>;
2818

2919
/// The selection process begins by considering all impls, where
3020
/// clauses, and so forth that might resolve an obligation. Sometimes

compiler/rustc_middle/src/ty/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1318,12 +1318,12 @@ pub struct GlobalCtxt<'tcx> {
13181318

13191319
/// Caches the results of trait selection. This cache is used
13201320
/// for things that do not have to do with the parameters in scope.
1321-
pub selection_cache: traits::SelectionCache<'tcx>,
1321+
pub selection_cache: traits::SelectionCache<'tcx, ty::TypingEnv<'tcx>>,
13221322

13231323
/// Caches the results of trait evaluation. This cache is used
13241324
/// for things that do not have to do with the parameters in scope.
13251325
/// Merge this with `selection_cache`?
1326-
pub evaluation_cache: traits::EvaluationCache<'tcx>,
1326+
pub evaluation_cache: traits::EvaluationCache<'tcx, ty::TypingEnv<'tcx>>,
13271327

13281328
/// Caches the results of goal evaluation in the new solver.
13291329
pub new_solver_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,

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

+41-20
Original file line numberDiff line numberDiff line change
@@ -1310,13 +1310,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13101310
param_env: ty::ParamEnv<'tcx>,
13111311
trait_pred: ty::PolyTraitPredicate<'tcx>,
13121312
) -> Option<EvaluationResult> {
1313-
let tcx = self.tcx();
1313+
let infcx = self.infcx;
1314+
let tcx = infcx.tcx;
13141315
if self.can_use_global_caches(param_env, trait_pred) {
1315-
if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) {
1316-
return Some(res);
1316+
let key = (infcx.typing_env(param_env), trait_pred);
1317+
if let Some(res) = tcx.evaluation_cache.get(&key, tcx) {
1318+
Some(res)
1319+
} else {
1320+
debug_assert_eq!(infcx.evaluation_cache.get(&(param_env, trait_pred), tcx), None);
1321+
None
13171322
}
1323+
} else {
1324+
self.infcx.evaluation_cache.get(&(param_env, trait_pred), tcx)
13181325
}
1319-
self.infcx.evaluation_cache.get(&(param_env, trait_pred), tcx)
13201326
}
13211327

13221328
fn insert_evaluation_cache(
@@ -1332,18 +1338,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13321338
return;
13331339
}
13341340

1335-
if self.can_use_global_caches(param_env, trait_pred) && !trait_pred.has_infer() {
1341+
let infcx = self.infcx;
1342+
let tcx = infcx.tcx;
1343+
if self.can_use_global_caches(param_env, trait_pred) {
13361344
debug!(?trait_pred, ?result, "insert_evaluation_cache global");
13371345
// This may overwrite the cache with the same value
1338-
// FIXME: Due to #50507 this overwrites the different values
1339-
// This should be changed to use HashMapExt::insert_same
1340-
// when that is fixed
1341-
self.tcx().evaluation_cache.insert((param_env, trait_pred), dep_node, result);
1346+
tcx.evaluation_cache.insert(
1347+
(infcx.typing_env(param_env), trait_pred),
1348+
dep_node,
1349+
result,
1350+
);
13421351
return;
1352+
} else {
1353+
debug!(?trait_pred, ?result, "insert_evaluation_cache local");
1354+
self.infcx.evaluation_cache.insert((param_env, trait_pred), dep_node, result);
13431355
}
1344-
1345-
debug!(?trait_pred, ?result, "insert_evaluation_cache");
1346-
self.infcx.evaluation_cache.insert((param_env, trait_pred), dep_node, result);
13471356
}
13481357

13491358
fn check_recursion_depth<T>(
@@ -1485,7 +1494,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14851494
// If there are any inference variables in the `ParamEnv`, then we
14861495
// always use a cache local to this particular scope. Otherwise, we
14871496
// switch to a global cache.
1488-
if param_env.has_infer() {
1497+
if param_env.has_infer() || pred.has_infer() {
14891498
return false;
14901499
}
14911500

@@ -1522,15 +1531,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15221531
param_env: ty::ParamEnv<'tcx>,
15231532
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
15241533
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
1525-
let tcx = self.tcx();
1534+
let infcx = self.infcx;
1535+
let tcx = infcx.tcx;
15261536
let pred = cache_fresh_trait_pred.skip_binder();
15271537

15281538
if self.can_use_global_caches(param_env, cache_fresh_trait_pred) {
1529-
if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) {
1530-
return Some(res);
1539+
if let Some(res) = tcx.selection_cache.get(&(infcx.typing_env(param_env), pred), tcx) {
1540+
Some(res)
1541+
} else {
1542+
debug_assert_eq!(infcx.selection_cache.get(&(param_env, pred), tcx), None);
1543+
None
15311544
}
1545+
} else {
1546+
infcx.selection_cache.get(&(param_env, pred), tcx)
15321547
}
1533-
self.infcx.selection_cache.get(&(param_env, pred), tcx)
15341548
}
15351549

15361550
/// Determines whether can we safely cache the result
@@ -1567,7 +1581,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15671581
dep_node: DepNodeIndex,
15681582
candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>,
15691583
) {
1570-
let tcx = self.tcx();
1584+
let infcx = self.infcx;
1585+
let tcx = infcx.tcx;
15711586
let pred = cache_fresh_trait_pred.skip_binder();
15721587

15731588
if !self.can_cache_candidate(&candidate) {
@@ -1578,10 +1593,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15781593
if self.can_use_global_caches(param_env, cache_fresh_trait_pred) {
15791594
if let Err(Overflow(OverflowError::Canonical)) = candidate {
15801595
// Don't cache overflow globally; we only produce this in certain modes.
1581-
} else if !pred.has_infer() && !candidate.has_infer() {
1596+
} else {
15821597
debug!(?pred, ?candidate, "insert_candidate_cache global");
1598+
debug_assert!(!candidate.has_infer());
1599+
15831600
// This may overwrite the cache with the same value.
1584-
tcx.selection_cache.insert((param_env, pred), dep_node, candidate);
1601+
tcx.selection_cache.insert(
1602+
(infcx.typing_env(param_env), pred),
1603+
dep_node,
1604+
candidate,
1605+
);
15851606
return;
15861607
}
15871608
}

0 commit comments

Comments
 (0)