From 6b07cec05c614c34d211cff23f738f03d3026ae8 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 1 Dec 2021 23:22:42 +0800 Subject: [PATCH] Cache with consistent env and bound --- compiler/rustc_middle/src/ty/mod.rs | 18 +++++++++++++ .../src/traits/select/mod.rs | 26 +++++++++++++------ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 72191bce4c7..cd60519ac34 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -230,6 +230,19 @@ pub enum BoundConstness { ConstIfConst, } +impl BoundConstness { + /// Reduce `self` and `constness` to two possible combined states instead of four. + pub fn and(&mut self, constness: hir::Constness) -> hir::Constness { + match (constness, self) { + (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const, + (_, this) => { + *this = BoundConstness::NotConst; + hir::Constness::NotConst + } + } + } +} + impl fmt::Display for BoundConstness { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -1326,6 +1339,11 @@ impl<'tcx> ParamEnv<'tcx> { self } + pub fn with_constness(mut self, constness: hir::Constness) -> Self { + self.packed.set_tag(ParamTag { constness, ..self.packed.tag() }); + self + } + pub fn with_const(mut self) -> Self { self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() }); self diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index dde4529a21b..dd62411cb8e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -675,11 +675,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } let stack = self.push_stack(previous_stack, &obligation); - let fresh_trait_pred = stack.fresh_trait_pred; + let mut fresh_trait_pred = stack.fresh_trait_pred; + let mut param_env = obligation.param_env; + + fresh_trait_pred = fresh_trait_pred.map_bound(|mut pred| { + param_env = param_env.with_constness(pred.constness.and(param_env.constness())); + pred + }); debug!(?fresh_trait_pred); - if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_pred) { + if let Some(result) = self.check_evaluation_cache(param_env, fresh_trait_pred) { debug!(?result, "CACHE HIT"); return Ok(result); } @@ -709,11 +715,11 @@ 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_pred, dep_node, result); + self.insert_evaluation_cache(param_env, fresh_trait_pred, dep_node, result); stack.cache().on_completion(stack.dfn, |fresh_trait_pred, provisional_result| { self.insert_evaluation_cache( - obligation.param_env, + param_env, fresh_trait_pred, dep_node, provisional_result.max(result), @@ -1200,7 +1206,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn check_candidate_cache( &mut self, - param_env: ty::ParamEnv<'tcx>, + mut param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option>> { // Neither the global nor local cache is aware of intercrate @@ -1211,7 +1217,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return None; } let tcx = self.tcx(); - let pred = cache_fresh_trait_pred.skip_binder(); + let mut pred = cache_fresh_trait_pred.skip_binder(); + param_env = param_env.with_constness(pred.constness.and(param_env.constness())); + if self.can_use_global_caches(param_env) { if let Some(res) = tcx.selection_cache.get(¶m_env.and(pred), tcx) { return Some(res); @@ -1255,13 +1263,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn insert_candidate_cache( &mut self, - param_env: ty::ParamEnv<'tcx>, + mut param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, dep_node: DepNodeIndex, candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>, ) { let tcx = self.tcx(); - let pred = cache_fresh_trait_pred.skip_binder(); + let mut pred = cache_fresh_trait_pred.skip_binder(); + + param_env = param_env.with_constness(pred.constness.and(param_env.constness())); if !self.can_cache_candidate(&candidate) { debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable");