From 85c8fd9c94d842fcdee98d60abaf7225250be870 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 14 Oct 2021 17:57:23 -0300 Subject: [PATCH] Make EvaluationCache consider polarity as cache's key --- compiler/rustc_middle/src/traits/select.rs | 6 ++-- .../src/traits/select/mod.rs | 30 +++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 83a2278d8ba6..560660517f34 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -16,8 +16,10 @@ pub type SelectionCache<'tcx> = Cache< SelectionResult<'tcx, SelectionCandidate<'tcx>>, >; -pub type EvaluationCache<'tcx> = - Cache>>, EvaluationResult>; +pub type EvaluationCache<'tcx> = Cache< + (ty::ParamEnvAnd<'tcx, ty::ConstnessAnd>>, ty::ImplPolarity), + EvaluationResult, +>; /// The selection process begins by considering all impls, where /// clauses, and so forth that might resolve an obligation. Sometimes diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 8a768b167298..0e3f5d746e05 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -709,7 +709,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?fresh_trait_ref); - if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_ref) { + if let Some(result) = self.check_evaluation_cache( + obligation.param_env, + fresh_trait_ref, + obligation.predicate.skip_binder().polarity, + ) { debug!(?result, "CACHE HIT"); return Ok(result); } @@ -739,12 +743,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let reached_depth = stack.reached_depth.get(); if reached_depth >= stack.depth { debug!(?result, "CACHE MISS"); - self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result); + self.insert_evaluation_cache( + obligation.param_env, + fresh_trait_ref, + obligation.predicate.skip_binder().polarity, + dep_node, + result, + ); stack.cache().on_completion(stack.dfn, |fresh_trait_ref, provisional_result| { self.insert_evaluation_cache( obligation.param_env, fresh_trait_ref, + obligation.predicate.skip_binder().polarity, dep_node, provisional_result.max(result), ); @@ -977,6 +988,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &self, param_env: ty::ParamEnv<'tcx>, trait_ref: ty::ConstnessAnd>, + polarity: ty::ImplPolarity, ) -> Option { // Neither the global nor local cache is aware of intercrate // mode, so don't do any caching. In particular, we might @@ -988,17 +1000,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); if self.can_use_global_caches(param_env) { - if let Some(res) = tcx.evaluation_cache.get(¶m_env.and(trait_ref), tcx) { + if let Some(res) = tcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx) + { return Some(res); } } - self.infcx.evaluation_cache.get(¶m_env.and(trait_ref), tcx) + self.infcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx) } fn insert_evaluation_cache( &mut self, param_env: ty::ParamEnv<'tcx>, trait_ref: ty::ConstnessAnd>, + polarity: ty::ImplPolarity, dep_node: DepNodeIndex, result: EvaluationResult, ) { @@ -1023,13 +1037,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // 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.and(trait_ref), dep_node, result); + self.tcx().evaluation_cache.insert( + (param_env.and(trait_ref), polarity), + dep_node, + result, + ); return; } } debug!(?trait_ref, ?result, "insert_evaluation_cache"); - self.infcx.evaluation_cache.insert(param_env.and(trait_ref), dep_node, result); + self.infcx.evaluation_cache.insert((param_env.and(trait_ref), polarity), dep_node, result); } /// For various reasons, it's possible for a subobligation