diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve/inspect/build.rs')
-rw-r--r-- | compiler/rustc_trait_selection/src/solve/inspect/build.rs | 121 |
1 files changed, 61 insertions, 60 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs index 2eba98b02..088455b38 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs @@ -3,6 +3,8 @@ //! This code is *a bit* of a mess and can hopefully be //! mostly ignored. For a general overview of how it works, //! see the comment on [ProofTreeBuilder]. +use std::mem; + use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{ CanonicalInput, Certainty, Goal, IsNormalizesToHack, QueryInput, QueryResult, @@ -10,7 +12,6 @@ use rustc_middle::traits::solve::{ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::DumpSolverProofTree; -use crate::solve::eval_ctxt::UseGlobalCache; use crate::solve::{self, inspect, EvalCtxt, GenerateProofTree}; /// The core data structure when building proof trees. @@ -34,12 +35,7 @@ use crate::solve::{self, inspect, EvalCtxt, GenerateProofTree}; /// is called to recursively convert the whole structure to a /// finished proof tree. pub(in crate::solve) struct ProofTreeBuilder<'tcx> { - state: Option<Box<BuilderData<'tcx>>>, -} - -struct BuilderData<'tcx> { - tree: DebugSolver<'tcx>, - use_global_cache: UseGlobalCache, + state: Option<Box<DebugSolver<'tcx>>>, } /// The current state of the proof tree builder, at most places @@ -118,36 +114,46 @@ pub(in crate::solve) enum WipGoalEvaluationKind<'tcx> { Nested { is_normalizes_to_hack: IsNormalizesToHack }, } -#[derive(Eq, PartialEq, Debug)] -pub(in crate::solve) enum WipCanonicalGoalEvaluationKind { +#[derive(Eq, PartialEq)] +pub(in crate::solve) enum WipCanonicalGoalEvaluationKind<'tcx> { Overflow, - CacheHit(inspect::CacheHit), + CycleInStack, + Interned { revisions: &'tcx [inspect::GoalEvaluationStep<'tcx>] }, +} + +impl std::fmt::Debug for WipCanonicalGoalEvaluationKind<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Overflow => write!(f, "Overflow"), + Self::CycleInStack => write!(f, "CycleInStack"), + Self::Interned { revisions: _ } => f.debug_struct("Interned").finish_non_exhaustive(), + } + } } #[derive(Eq, PartialEq, Debug)] struct WipCanonicalGoalEvaluation<'tcx> { goal: CanonicalInput<'tcx>, - kind: Option<WipCanonicalGoalEvaluationKind>, + kind: Option<WipCanonicalGoalEvaluationKind<'tcx>>, + /// Only used for uncached goals. After we finished evaluating + /// the goal, this is interned and moved into `kind`. revisions: Vec<WipGoalEvaluationStep<'tcx>>, result: Option<QueryResult<'tcx>>, } impl<'tcx> WipCanonicalGoalEvaluation<'tcx> { fn finalize(self) -> inspect::CanonicalGoalEvaluation<'tcx> { - let kind = match self.kind { - Some(WipCanonicalGoalEvaluationKind::Overflow) => { + assert!(self.revisions.is_empty()); + let kind = match self.kind.unwrap() { + WipCanonicalGoalEvaluationKind::Overflow => { inspect::CanonicalGoalEvaluationKind::Overflow } - Some(WipCanonicalGoalEvaluationKind::CacheHit(hit)) => { - inspect::CanonicalGoalEvaluationKind::CacheHit(hit) + WipCanonicalGoalEvaluationKind::CycleInStack => { + inspect::CanonicalGoalEvaluationKind::CycleInStack + } + WipCanonicalGoalEvaluationKind::Interned { revisions } => { + inspect::CanonicalGoalEvaluationKind::Evaluation { revisions } } - None => inspect::CanonicalGoalEvaluationKind::Uncached { - revisions: self - .revisions - .into_iter() - .map(WipGoalEvaluationStep::finalize) - .collect(), - }, }; inspect::CanonicalGoalEvaluation { goal: self.goal, kind, result: self.result.unwrap() } @@ -226,33 +232,20 @@ impl<'tcx> WipProbeStep<'tcx> { } impl<'tcx> ProofTreeBuilder<'tcx> { - fn new( - state: impl Into<DebugSolver<'tcx>>, - use_global_cache: UseGlobalCache, - ) -> ProofTreeBuilder<'tcx> { - ProofTreeBuilder { - state: Some(Box::new(BuilderData { tree: state.into(), use_global_cache })), - } + fn new(state: impl Into<DebugSolver<'tcx>>) -> ProofTreeBuilder<'tcx> { + ProofTreeBuilder { state: Some(Box::new(state.into())) } } fn nested<T: Into<DebugSolver<'tcx>>>(&self, state: impl FnOnce() -> T) -> Self { - match &self.state { - Some(prev_state) => Self { - state: Some(Box::new(BuilderData { - tree: state().into(), - use_global_cache: prev_state.use_global_cache, - })), - }, - None => Self { state: None }, - } + ProofTreeBuilder { state: self.state.as_ref().map(|_| Box::new(state().into())) } } fn as_mut(&mut self) -> Option<&mut DebugSolver<'tcx>> { - self.state.as_mut().map(|boxed| &mut boxed.tree) + self.state.as_deref_mut() } pub fn finalize(self) -> Option<inspect::GoalEvaluation<'tcx>> { - match self.state?.tree { + match *self.state? { DebugSolver::GoalEvaluation(wip_goal_evaluation) => { Some(wip_goal_evaluation.finalize()) } @@ -260,13 +253,6 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn use_global_cache(&self) -> bool { - self.state - .as_ref() - .map(|state| matches!(state.use_global_cache, UseGlobalCache::Yes)) - .unwrap_or(true) - } - pub fn new_maybe_root( tcx: TyCtxt<'tcx>, generate_proof_tree: GenerateProofTree, @@ -276,10 +262,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { GenerateProofTree::IfEnabled => { let opts = &tcx.sess.opts.unstable_opts; match opts.dump_solver_proof_tree { - DumpSolverProofTree::Always => { - let use_cache = opts.dump_solver_proof_tree_use_cache.unwrap_or(true); - ProofTreeBuilder::new_root(UseGlobalCache::from_bool(use_cache)) - } + DumpSolverProofTree::Always => ProofTreeBuilder::new_root(), // `OnError` is handled by reevaluating goals in error // reporting with `GenerateProofTree::Yes`. DumpSolverProofTree::OnError | DumpSolverProofTree::Never => { @@ -287,12 +270,12 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } } - GenerateProofTree::Yes(use_cache) => ProofTreeBuilder::new_root(use_cache), + GenerateProofTree::Yes => ProofTreeBuilder::new_root(), } } - pub fn new_root(use_global_cache: UseGlobalCache) -> ProofTreeBuilder<'tcx> { - ProofTreeBuilder::new(DebugSolver::Root, use_global_cache) + pub fn new_root() -> ProofTreeBuilder<'tcx> { + ProofTreeBuilder::new(DebugSolver::Root) } pub fn new_noop() -> ProofTreeBuilder<'tcx> { @@ -336,9 +319,27 @@ impl<'tcx> ProofTreeBuilder<'tcx> { }) } + pub fn finalize_evaluation( + &mut self, + tcx: TyCtxt<'tcx>, + ) -> Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]> { + self.as_mut().map(|this| match this { + DebugSolver::CanonicalGoalEvaluation(evaluation) => { + let revisions = mem::take(&mut evaluation.revisions) + .into_iter() + .map(WipGoalEvaluationStep::finalize); + let revisions = &*tcx.arena.alloc_from_iter(revisions); + let kind = WipCanonicalGoalEvaluationKind::Interned { revisions }; + assert_eq!(evaluation.kind.replace(kind), None); + revisions + } + _ => unreachable!(), + }) + } + pub fn canonical_goal_evaluation(&mut self, canonical_goal_evaluation: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, canonical_goal_evaluation.state.unwrap().tree) { + match (this, *canonical_goal_evaluation.state.unwrap()) { ( DebugSolver::GoalEvaluation(goal_evaluation), DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation), @@ -348,7 +349,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind) { + pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind<'tcx>) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { @@ -372,7 +373,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, goal_evaluation.state.unwrap().tree) { + match (this, *goal_evaluation.state.unwrap()) { ( DebugSolver::AddedGoalsEvaluation(WipAddedGoalsEvaluation { evaluations, .. @@ -396,7 +397,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, goal_evaluation_step.state.unwrap().tree) { + match (this, *goal_evaluation_step.state.unwrap()) { ( DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations), DebugSolver::GoalEvaluationStep(goal_evaluation_step), @@ -444,7 +445,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn finish_probe(&mut self, probe: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, probe.state.unwrap().tree) { + match (this, *probe.state.unwrap()) { ( DebugSolver::Probe(WipProbe { steps, .. }) | DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { @@ -486,7 +487,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn added_goals_evaluation(&mut self, added_goals_evaluation: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, added_goals_evaluation.state.unwrap().tree) { + match (this, *added_goals_evaluation.state.unwrap()) { ( DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { evaluation: WipProbe { steps, .. }, |