Skip to content

Commit

Permalink
global old solver cache: use TypingEnv
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Nov 20, 2024
1 parent 08c4525 commit af0d83a
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 42 deletions.
9 changes: 5 additions & 4 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,12 @@ pub struct InferCtxt<'tcx> {
lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,

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

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

/// The set of predicates on which errors have been reported, to
/// avoid reporting the same error twice.
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ pub struct DerivedCause<'tcx> {
pub parent_code: InternedObligationCauseCode<'tcx>,
}

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

#[derive(Clone, Debug, TypeVisitable)]
#[derive(Clone, Debug, PartialEq, Eq, TypeVisitable)]
pub struct SignatureMismatchData<'tcx> {
pub found_trait_ref: ty::TraitRef<'tcx>,
pub expected_trait_ref: ty::TraitRef<'tcx>,
Expand Down
18 changes: 4 additions & 14 deletions compiler/rustc_middle/src/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,10 @@ use self::EvaluationResult::*;
use super::{SelectionError, SelectionResult};
use crate::ty;

pub type SelectionCache<'tcx> = Cache<
// This cache does not use `ParamEnvAnd` in its keys because `ParamEnv::and` can replace
// caller bounds with an empty list if the `TraitPredicate` looks global, which may happen
// after erasing lifetimes from the predicate.
(ty::ParamEnv<'tcx>, ty::TraitPredicate<'tcx>),
SelectionResult<'tcx, SelectionCandidate<'tcx>>,
>;

pub type EvaluationCache<'tcx> = Cache<
// See above: this cache does not use `ParamEnvAnd` in its keys due to sometimes incorrectly
// caching with the wrong `ParamEnv`.
(ty::ParamEnv<'tcx>, ty::PolyTraitPredicate<'tcx>),
EvaluationResult,
>;
pub type SelectionCache<'tcx, ENV> =
Cache<(ENV, ty::TraitPredicate<'tcx>), SelectionResult<'tcx, SelectionCandidate<'tcx>>>;

pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>), EvaluationResult>;

/// The selection process begins by considering all impls, where
/// clauses, and so forth that might resolve an obligation. Sometimes
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1328,12 +1328,12 @@ pub struct GlobalCtxt<'tcx> {

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

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

/// Caches the results of goal evaluation in the new solver.
pub new_solver_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
Expand Down
61 changes: 41 additions & 20 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1310,13 +1310,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<EvaluationResult> {
let tcx = self.tcx();
let infcx = self.infcx;
let tcx = infcx.tcx;
if self.can_use_global_caches(param_env, trait_pred) {
if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) {
return Some(res);
let key = (infcx.typing_env(param_env), trait_pred);
if let Some(res) = tcx.evaluation_cache.get(&key, tcx) {
Some(res)
} else {
debug_assert_eq!(infcx.evaluation_cache.get(&(param_env, trait_pred), tcx), None);
None
}
} else {
self.infcx.evaluation_cache.get(&(param_env, trait_pred), tcx)
}
self.infcx.evaluation_cache.get(&(param_env, trait_pred), tcx)
}

fn insert_evaluation_cache(
Expand All @@ -1332,18 +1338,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return;
}

if self.can_use_global_caches(param_env, trait_pred) && !trait_pred.has_infer() {
let infcx = self.infcx;
let tcx = infcx.tcx;
if self.can_use_global_caches(param_env, trait_pred) {
debug!(?trait_pred, ?result, "insert_evaluation_cache global");
// This may overwrite the cache with the same value
// FIXME: Due to #50507 this overwrites the different values
// This should be changed to use HashMapExt::insert_same
// when that is fixed
self.tcx().evaluation_cache.insert((param_env, trait_pred), dep_node, result);
tcx.evaluation_cache.insert(
(infcx.typing_env(param_env), trait_pred),
dep_node,
result,
);
return;
} else {
debug!(?trait_pred, ?result, "insert_evaluation_cache local");
self.infcx.evaluation_cache.insert((param_env, trait_pred), dep_node, result);
}

debug!(?trait_pred, ?result, "insert_evaluation_cache");
self.infcx.evaluation_cache.insert((param_env, trait_pred), dep_node, result);
}

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

Expand Down Expand Up @@ -1522,15 +1531,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
let tcx = self.tcx();
let infcx = self.infcx;
let tcx = infcx.tcx;
let pred = cache_fresh_trait_pred.skip_binder();

if self.can_use_global_caches(param_env, cache_fresh_trait_pred) {
if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) {
return Some(res);
if let Some(res) = tcx.selection_cache.get(&(infcx.typing_env(param_env), pred), tcx) {
Some(res)
} else {
debug_assert_eq!(infcx.selection_cache.get(&(param_env, pred), tcx), None);
None
}
} else {
infcx.selection_cache.get(&(param_env, pred), tcx)
}
self.infcx.selection_cache.get(&(param_env, pred), tcx)
}

/// Determines whether can we safely cache the result
Expand Down Expand Up @@ -1567,7 +1581,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
dep_node: DepNodeIndex,
candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>,
) {
let tcx = self.tcx();
let infcx = self.infcx;
let tcx = infcx.tcx;
let pred = cache_fresh_trait_pred.skip_binder();

if !self.can_cache_candidate(&candidate) {
Expand All @@ -1578,10 +1593,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if self.can_use_global_caches(param_env, cache_fresh_trait_pred) {
if let Err(Overflow(OverflowError::Canonical)) = candidate {
// Don't cache overflow globally; we only produce this in certain modes.
} else if !pred.has_infer() && !candidate.has_infer() {
} else {
debug!(?pred, ?candidate, "insert_candidate_cache global");
debug_assert!(!candidate.has_infer());

// This may overwrite the cache with the same value.
tcx.selection_cache.insert((param_env, pred), dep_node, candidate);
tcx.selection_cache.insert(
(infcx.typing_env(param_env), pred),
dep_node,
candidate,
);
return;
}
}
Expand Down

0 comments on commit af0d83a

Please sign in to comment.