diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs index 8cbdb493ccd..6060e8f3546 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -2,6 +2,12 @@ use crate::ty; use std::fmt::{Debug, Write}; +#[derive(Eq, PartialEq, Hash, HashStable)] +pub enum CacheHit { + Provisional, + Global, +} + #[derive(Eq, PartialEq, Hash, HashStable)] pub struct GoalEvaluation<'tcx> { pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>, @@ -12,7 +18,7 @@ pub struct GoalEvaluation<'tcx> { /// is represented as an entry in this vec. pub evaluation_steps: Vec>, - pub cache_hit: bool, + pub cache_hit: Option, pub result: Option>, } @@ -92,8 +98,9 @@ fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Res writeln!(f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?; match goal.cache_hit { - true => writeln!(f, "CACHE HIT: {:?}", goal.result), - false => { + Some(CacheHit::Global) => writeln!(f, "GLOBAL CACHE HIT: {:?}", goal.result), + Some(CacheHit::Provisional) => writeln!(f, "PROVISIONAL CACHE HIT: {:?}", goal.result), + None => { for (n, step) in goal.evaluation_steps.iter().enumerate() { let f = &mut *self.f; writeln!(f, "REVISION {n}: {:?}", step.result.unwrap())?; diff --git a/compiler/rustc_trait_selection/src/solve/inspect/mod.rs b/compiler/rustc_trait_selection/src/solve/inspect/mod.rs index eb05315b164..0dcee5a9296 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/mod.rs @@ -23,7 +23,7 @@ fn new_goal_evaluation( goal: Goal<'tcx, ty::Predicate<'tcx>>, ) -> Box + 'tcx>; fn canonicalized_goal(&mut self, canonical_goal: CanonicalInput<'tcx>); - fn cache_hit(&mut self); + fn cache_hit(&mut self, cache_hit: CacheHit); fn goal_evaluation(&mut self, goal_evaluation: Box + 'tcx>); fn new_goal_evaluation_step( @@ -59,7 +59,7 @@ fn new_goal_evaluation( Box::new(()) } fn canonicalized_goal(&mut self, _canonical_goal: CanonicalInput<'tcx>) {} - fn cache_hit(&mut self) {} + fn cache_hit(&mut self, _cache_hit: CacheHit) {} fn goal_evaluation(&mut self, _goal_evaluation: Box + 'tcx>) {} fn new_goal_evaluation_step( @@ -104,7 +104,7 @@ fn new_goal_evaluation( uncanonicalized_goal: goal, canonicalized_goal: None, evaluation_steps: vec![], - cache_hit: false, + cache_hit: None, result: None, })) } @@ -117,9 +117,11 @@ fn canonicalized_goal(&mut self, canonical_goal: CanonicalInput<'tcx>) { _ => unreachable!(), } } - fn cache_hit(&mut self) { + fn cache_hit(&mut self, cache_hit: CacheHit) { match self { - DebugSolver::GoalEvaluation(goal_evaluation) => goal_evaluation.cache_hit = true, + DebugSolver::GoalEvaluation(goal_evaluation) => { + goal_evaluation.cache_hit = Some(cache_hit) + } _ => unreachable!(), }; } diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs index 131c72a5232..86cc1778c59 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -2,6 +2,7 @@ mod overflow; pub(super) use overflow::OverflowHandler; +use rustc_middle::traits::solve::inspect::CacheHit; use self::cache::ProvisionalEntry; use cache::ProvisionalCache; @@ -89,11 +90,12 @@ pub(super) fn in_cycle(&self) -> bool { /// Tries putting the new goal on the stack, returning an error if it is already cached. /// /// This correctly updates the provisional cache if there is a cycle. - #[instrument(level = "debug", skip(self, tcx), ret)] + #[instrument(level = "debug", skip(self, tcx, inspect), ret)] fn try_push_stack( &mut self, tcx: TyCtxt<'tcx>, input: CanonicalInput<'tcx>, + inspect: &mut dyn InspectSolve<'tcx>, ) -> Result<(), QueryResult<'tcx>> { // Look at the provisional cache to check for cycles. let cache = &mut self.provisional_cache; @@ -120,6 +122,8 @@ fn try_push_stack( // Finally we can return either the provisional response for that goal if we have a // coinductive cycle or an ambiguous result if the cycle is inductive. Entry::Occupied(entry_index) => { + inspect.cache_hit(CacheHit::Provisional); + let entry_index = *entry_index.get(); let stack_depth = cache.depth(entry_index); @@ -212,12 +216,12 @@ pub(super) fn with_new_goal( if self.should_use_global_cache() { if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_input, tcx) { debug!(?canonical_input, ?result, "cache hit"); - inspect.cache_hit(); + inspect.cache_hit(CacheHit::Global); return result; } } - match self.try_push_stack(tcx, canonical_input) { + match self.try_push_stack(tcx, canonical_input, inspect) { Ok(()) => {} // Our goal is already on the stack, eager return. Err(response) => return response,