about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDeadbeef <ent3rm4n@gmail.com>2021-12-01 23:22:42 +0800
committerDeadbeef <ent3rm4n@gmail.com>2021-12-01 23:22:42 +0800
commit6b07cec05c614c34d211cff23f738f03d3026ae8 (patch)
tree31dcd5edb87e511d641f92d498d3310ba1fd4ee3
parent87cd1ce6c149c002e158e29cee9ff863073c5412 (diff)
downloadrust-6b07cec05c614c34d211cff23f738f03d3026ae8.tar.gz
rust-6b07cec05c614c34d211cff23f738f03d3026ae8.zip
Cache with consistent env and bound
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs26
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<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
         // 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(&param_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");