about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBoxy <supbscripter@gmail.com>2023-06-08 19:58:04 +0100
committerBoxy <supbscripter@gmail.com>2023-06-19 09:01:37 +0100
commit7a3665d016d07af35a7952c25435deab0bee5ed6 (patch)
tree8544c8144f463b5fe156ded20379248ef8657e40
parent3587d4ced8b786e26f7d30f064a8a4d895f545ec (diff)
downloadrust-7a3665d016d07af35a7952c25435deab0bee5ed6.tar.gz
rust-7a3665d016d07af35a7952c25435deab0bee5ed6.zip
dont use a trait
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs38
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/mod.rs209
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/mod.rs8
3 files changed, 116 insertions, 139 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index 7ac1ef19bbc..d06450820ce 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -21,10 +21,9 @@ use rustc_middle::ty::{
 use rustc_span::DUMMY_SP;
 use std::ops::ControlFlow;
 
-use crate::solve::inspect::DebugSolver;
 use crate::traits::specialization_graph;
 
-use super::inspect::InspectSolve;
+use super::inspect::ProofTreeBuilder;
 use super::search_graph::{self, OverflowHandler};
 use super::SolverMode;
 use super::{search_graph::SearchGraph, Goal};
@@ -76,7 +75,7 @@ pub struct EvalCtxt<'a, 'tcx> {
     // evaluation code.
     tainted: Result<(), NoSolution>,
 
-    inspect: Box<dyn InspectSolve<'tcx> + 'tcx>,
+    inspect: ProofTreeBuilder<'tcx>,
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -147,25 +146,20 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
             var_values: CanonicalVarValues::dummy(),
             nested_goals: NestedGoals::new(),
             tainted: Ok(()),
-            inspect: match self.tcx.sess.opts.unstable_opts.dump_solver_proof_tree {
-                true => Box::new(DebugSolver::new()),
-                false => Box::new(()),
-            },
+            inspect: self
+                .tcx
+                .sess
+                .opts
+                .unstable_opts
+                .dump_solver_proof_tree
+                .then(ProofTreeBuilder::new_root)
+                .unwrap_or_else(ProofTreeBuilder::new_noop),
         };
         let result = ecx.evaluate_goal(IsNormalizesToHack::No, goal);
 
-        let tcx = ecx.tcx();
-        match ecx.inspect.into_debug_solver() {
-            Some(tree) => match Box::leak(tree) {
-                DebugSolver::GoalEvaluation(tree) => {
-                    if tcx.sess.opts.unstable_opts.dump_solver_proof_tree {
-                        println!("{:?}", tree);
-                    }
-                }
-                _ => unreachable!("unable to convert to `DebugSolver::GoalEvaluation`"),
-            },
-            _ => unreachable!("unable to convert to `DebugSolver::GoalEvaluation`"),
-        };
+        if let Some(tree) = ecx.inspect.into_proof_tree() {
+            println!("{:?}", tree);
+        }
 
         assert!(
             ecx.nested_goals.is_empty(),
@@ -196,7 +190,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         tcx: TyCtxt<'tcx>,
         search_graph: &'a mut search_graph::SearchGraph<'tcx>,
         canonical_input: CanonicalInput<'tcx>,
-        mut goal_evaluation: &mut dyn InspectSolve<'tcx>,
+        mut goal_evaluation: &mut ProofTreeBuilder<'tcx>,
     ) -> QueryResult<'tcx> {
         goal_evaluation.canonicalized_goal(canonical_input);
 
@@ -272,7 +266,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             self.tcx(),
             self.search_graph,
             canonical_goal,
-            &mut *goal_evaluation,
+            &mut goal_evaluation,
         );
         goal_evaluation.query_result(canonical_response);
         self.inspect.goal_evaluation(goal_evaluation);
@@ -309,7 +303,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                 self.search_graph,
                 canonical_goal,
                 // FIXME(-Ztrait-solver=next): we do not track what happens in `evaluate_canonical_goal`
-                &mut (),
+                &mut ProofTreeBuilder::new_noop(),
             )?;
             // We only check for modulo regions as we convert all regions in
             // the input to new existentials, even if they're expected to be
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/mod.rs b/compiler/rustc_trait_selection/src/solve/inspect/mod.rs
index 0dcee5a9296..20d77f86ca8 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/mod.rs
@@ -15,101 +15,44 @@ pub enum DebugSolver<'tcx> {
     GoalCandidate(GoalCandidate<'tcx>),
 }
 
-pub trait InspectSolve<'tcx> {
-    fn into_debug_solver(self: Box<Self>) -> Option<Box<DebugSolver<'tcx>>>;
+pub struct ProofTreeBuilder<'tcx>(Option<Box<DebugSolver<'tcx>>>);
 
-    fn new_goal_evaluation(
-        &mut self,
-        goal: Goal<'tcx, ty::Predicate<'tcx>>,
-    ) -> Box<dyn InspectSolve<'tcx> + 'tcx>;
-    fn canonicalized_goal(&mut self, canonical_goal: CanonicalInput<'tcx>);
-    fn cache_hit(&mut self, cache_hit: CacheHit);
-    fn goal_evaluation(&mut self, goal_evaluation: Box<dyn InspectSolve<'tcx> + 'tcx>);
-
-    fn new_goal_evaluation_step(
-        &mut self,
-        instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>,
-    ) -> Box<dyn InspectSolve<'tcx> + 'tcx>;
-    fn goal_evaluation_step(&mut self, goal_eval_step: Box<dyn InspectSolve<'tcx> + 'tcx>);
-
-    fn new_goal_candidate(&mut self) -> Box<dyn InspectSolve<'tcx> + 'tcx>;
-    fn candidate_name(&mut self, f: &mut dyn FnMut() -> String);
-    fn goal_candidate(&mut self, candidate: Box<dyn InspectSolve<'tcx> + 'tcx>);
-
-    fn new_evaluate_added_goals(&mut self) -> Box<dyn InspectSolve<'tcx> + 'tcx>;
-    fn evaluate_added_goals_loop_start(&mut self);
-    fn eval_added_goals_result(&mut self, result: Result<Certainty, NoSolution>);
-    fn added_goals_evaluation(&mut self, goals_evaluation: Box<dyn InspectSolve<'tcx> + 'tcx>);
-
-    fn query_result(&mut self, result: QueryResult<'tcx>);
-}
-
-/// No-op `InspectSolve` impl to use for normal trait solving when we do not want
-/// to take a performance hit from recording information about how things are being
-/// proven.
-impl<'tcx> InspectSolve<'tcx> for () {
-    fn into_debug_solver(self: Box<Self>) -> Option<Box<DebugSolver<'tcx>>> {
-        None
-    }
-
-    fn new_goal_evaluation(
-        &mut self,
-        _goal: Goal<'tcx, ty::Predicate<'tcx>>,
-    ) -> Box<dyn InspectSolve<'tcx> + 'tcx> {
-        Box::new(())
-    }
-    fn canonicalized_goal(&mut self, _canonical_goal: CanonicalInput<'tcx>) {}
-    fn cache_hit(&mut self, _cache_hit: CacheHit) {}
-    fn goal_evaluation(&mut self, _goal_evaluation: Box<dyn InspectSolve<'tcx> + 'tcx>) {}
-
-    fn new_goal_evaluation_step(
-        &mut self,
-        _instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>,
-    ) -> Box<dyn InspectSolve<'tcx> + 'tcx> {
-        Box::new(())
+impl<'tcx> ProofTreeBuilder<'tcx> {
+    pub fn into_proof_tree(self) -> Option<DebugSolver<'tcx>> {
+        self.0.map(|tree| *tree)
     }
-    fn goal_evaluation_step(&mut self, _goal_eval_step: Box<dyn InspectSolve<'tcx> + 'tcx>) {}
 
-    fn new_goal_candidate(&mut self) -> Box<dyn InspectSolve<'tcx> + 'tcx> {
-        Box::new(())
+    pub fn new_root() -> ProofTreeBuilder<'tcx> {
+        Self(Some(Box::new(DebugSolver::Root)))
     }
-    fn candidate_name(&mut self, _f: &mut dyn FnMut() -> String) {}
-    fn goal_candidate(&mut self, _candidate: Box<dyn InspectSolve<'tcx> + 'tcx>) {}
 
-    fn new_evaluate_added_goals(&mut self) -> Box<dyn InspectSolve<'tcx> + 'tcx> {
-        Box::new(())
-    }
-    fn evaluate_added_goals_loop_start(&mut self) {}
-    fn eval_added_goals_result(&mut self, _result: Result<Certainty, NoSolution>) {}
-    fn added_goals_evaluation(&mut self, _goals_evaluation: Box<dyn InspectSolve<'tcx> + 'tcx>) {}
-
-    fn query_result(&mut self, _result: QueryResult<'tcx>) {}
-}
-
-impl<'tcx> DebugSolver<'tcx> {
-    pub fn new() -> Self {
-        Self::Root
-    }
-}
-impl<'tcx> InspectSolve<'tcx> for DebugSolver<'tcx> {
-    fn into_debug_solver(self: Box<Self>) -> Option<Box<DebugSolver<'tcx>>> {
-        Some(self)
+    pub fn new_noop() -> ProofTreeBuilder<'tcx> {
+        Self(None)
     }
 
-    fn new_goal_evaluation(
+    pub fn new_goal_evaluation(
         &mut self,
         goal: Goal<'tcx, ty::Predicate<'tcx>>,
-    ) -> Box<dyn InspectSolve<'tcx> + 'tcx> {
-        Box::new(DebugSolver::GoalEvaluation(GoalEvaluation {
+    ) -> ProofTreeBuilder<'tcx> {
+        if self.0.is_none() {
+            return ProofTreeBuilder(None);
+        }
+
+        Self(Some(Box::new(DebugSolver::GoalEvaluation(GoalEvaluation {
             uncanonicalized_goal: goal,
             canonicalized_goal: None,
             evaluation_steps: vec![],
             cache_hit: None,
             result: None,
-        }))
+        }))))
     }
-    fn canonicalized_goal(&mut self, canonical_goal: CanonicalInput<'tcx>) {
-        match self {
+    pub fn canonicalized_goal(&mut self, canonical_goal: CanonicalInput<'tcx>) {
+        let this = match self.0.as_mut() {
+            None => return,
+            Some(this) => &mut **this,
+        };
+
+        match this {
             DebugSolver::GoalEvaluation(goal_evaluation) => {
                 assert!(goal_evaluation.canonicalized_goal.is_none());
                 goal_evaluation.canonicalized_goal = Some(canonical_goal)
@@ -117,17 +60,26 @@ impl<'tcx> InspectSolve<'tcx> for DebugSolver<'tcx> {
             _ => unreachable!(),
         }
     }
-    fn cache_hit(&mut self, cache_hit: CacheHit) {
-        match self {
+    pub fn cache_hit(&mut self, cache_hit: CacheHit) {
+        let this = match self.0.as_mut() {
+            None => return,
+            Some(this) => &mut **this,
+        };
+
+        match this {
             DebugSolver::GoalEvaluation(goal_evaluation) => {
                 goal_evaluation.cache_hit = Some(cache_hit)
             }
             _ => unreachable!(),
         };
     }
-    fn goal_evaluation(&mut self, goal_evaluation: Box<dyn InspectSolve<'tcx> + 'tcx>) {
-        let goal_evaluation = goal_evaluation.into_debug_solver().unwrap();
-        match (self, *goal_evaluation) {
+    pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<'tcx>) {
+        let this = match self.0.as_mut() {
+            None => return,
+            Some(this) => &mut **this,
+        };
+
+        match (this, *goal_evaluation.0.unwrap()) {
             (
                 DebugSolver::AddedGoalsEvaluation(AddedGoalsEvaluation { evaluations, .. }),
                 DebugSolver::GoalEvaluation(goal_evaluation),
@@ -137,20 +89,24 @@ impl<'tcx> InspectSolve<'tcx> for DebugSolver<'tcx> {
         }
     }
 
-    fn new_goal_evaluation_step(
+    pub fn new_goal_evaluation_step(
         &mut self,
         instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>,
-    ) -> Box<dyn InspectSolve<'tcx> + 'tcx> {
-        Box::new(DebugSolver::GoalEvaluationStep(GoalEvaluationStep {
+    ) -> ProofTreeBuilder<'tcx> {
+        Self(Some(Box::new(DebugSolver::GoalEvaluationStep(GoalEvaluationStep {
             instantiated_goal,
             nested_goal_evaluations: vec![],
             candidates: vec![],
             result: None,
-        }))
+        }))))
     }
-    fn goal_evaluation_step(&mut self, goal_eval_step: Box<dyn InspectSolve<'tcx> + 'tcx>) {
-        let goal_eval_step = goal_eval_step.into_debug_solver().unwrap();
-        match (self, *goal_eval_step) {
+    pub fn goal_evaluation_step(&mut self, goal_eval_step: ProofTreeBuilder<'tcx>) {
+        let this = match self.0.as_mut() {
+            None => return,
+            Some(this) => &mut **this,
+        };
+
+        match (this, *goal_eval_step.0.unwrap()) {
             (DebugSolver::GoalEvaluation(goal_eval), DebugSolver::GoalEvaluationStep(step)) => {
                 goal_eval.evaluation_steps.push(step);
             }
@@ -158,28 +114,36 @@ impl<'tcx> InspectSolve<'tcx> for DebugSolver<'tcx> {
         }
     }
 
-    fn new_goal_candidate(&mut self) -> Box<dyn InspectSolve<'tcx> + 'tcx> {
-        Box::new(DebugSolver::GoalCandidate(GoalCandidate {
+    pub fn new_goal_candidate(&mut self) -> ProofTreeBuilder<'tcx> {
+        Self(Some(Box::new(DebugSolver::GoalCandidate(GoalCandidate {
             nested_goal_evaluations: vec![],
             candidates: vec![],
             name: None,
             result: None,
-        }))
+        }))))
     }
-    fn candidate_name(&mut self, f: &mut dyn FnMut() -> String) {
-        let name = f();
+    pub fn candidate_name(&mut self, f: &mut dyn FnMut() -> String) {
+        let this = match self.0.as_mut() {
+            None => return,
+            Some(this) => &mut **this,
+        };
 
-        match self {
+        match this {
             DebugSolver::GoalCandidate(goal_candidate) => {
+                let name = f();
                 assert!(goal_candidate.name.is_none());
                 goal_candidate.name = Some(name);
             }
             _ => unreachable!(),
         }
     }
-    fn goal_candidate(&mut self, candidate: Box<dyn InspectSolve<'tcx> + 'tcx>) {
-        let candidate = candidate.into_debug_solver().unwrap();
-        match (self, *candidate) {
+    pub fn goal_candidate(&mut self, candidate: ProofTreeBuilder<'tcx>) {
+        let this = match self.0.as_mut() {
+            None => return,
+            Some(this) => &mut **this,
+        };
+
+        match (this, *candidate.0.unwrap()) {
             (
                 DebugSolver::GoalCandidate(GoalCandidate { candidates, .. })
                 | DebugSolver::GoalEvaluationStep(GoalEvaluationStep { candidates, .. }),
@@ -189,22 +153,32 @@ impl<'tcx> InspectSolve<'tcx> for DebugSolver<'tcx> {
         }
     }
 
-    fn new_evaluate_added_goals(&mut self) -> Box<dyn InspectSolve<'tcx> + 'tcx> {
-        Box::new(DebugSolver::AddedGoalsEvaluation(AddedGoalsEvaluation {
+    pub fn new_evaluate_added_goals(&mut self) -> ProofTreeBuilder<'tcx> {
+        Self(Some(Box::new(DebugSolver::AddedGoalsEvaluation(AddedGoalsEvaluation {
             evaluations: vec![],
             result: None,
-        }))
+        }))))
     }
-    fn evaluate_added_goals_loop_start(&mut self) {
-        match self {
+    pub fn evaluate_added_goals_loop_start(&mut self) {
+        let this = match self.0.as_mut() {
+            None => return,
+            Some(this) => &mut **this,
+        };
+
+        match this {
             DebugSolver::AddedGoalsEvaluation(this) => {
                 this.evaluations.push(vec![]);
             }
             _ => unreachable!(),
         }
     }
-    fn eval_added_goals_result(&mut self, result: Result<Certainty, NoSolution>) {
-        match self {
+    pub fn eval_added_goals_result(&mut self, result: Result<Certainty, NoSolution>) {
+        let this = match self.0.as_mut() {
+            None => return,
+            Some(this) => &mut **this,
+        };
+
+        match this {
             DebugSolver::AddedGoalsEvaluation(this) => {
                 assert!(this.result.is_none());
                 this.result = Some(result);
@@ -212,9 +186,13 @@ impl<'tcx> InspectSolve<'tcx> for DebugSolver<'tcx> {
             _ => unreachable!(),
         }
     }
-    fn added_goals_evaluation(&mut self, goals_evaluation: Box<dyn InspectSolve<'tcx> + 'tcx>) {
-        let goals_evaluation = goals_evaluation.into_debug_solver().unwrap();
-        match (self, *goals_evaluation) {
+    pub fn added_goals_evaluation(&mut self, goals_evaluation: ProofTreeBuilder<'tcx>) {
+        let this = match self.0.as_mut() {
+            None => return,
+            Some(this) => &mut **this,
+        };
+
+        match (this, *goals_evaluation.0.unwrap()) {
             (
                 DebugSolver::GoalEvaluationStep(GoalEvaluationStep {
                     nested_goal_evaluations, ..
@@ -226,8 +204,13 @@ impl<'tcx> InspectSolve<'tcx> for DebugSolver<'tcx> {
         }
     }
 
-    fn query_result(&mut self, result: QueryResult<'tcx>) {
-        match self {
+    pub fn query_result(&mut self, result: QueryResult<'tcx>) {
+        let this = match self.0.as_mut() {
+            None => return,
+            Some(this) => &mut **this,
+        };
+
+        match this {
             DebugSolver::GoalEvaluation(goal_evaluation) => {
                 assert!(goal_evaluation.result.is_none());
                 goal_evaluation.result = Some(result);
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 86cc1778c59..d167ee46b39 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
@@ -13,7 +13,7 @@ use rustc_middle::traits::solve::{CanonicalInput, Certainty, MaybeCause, QueryRe
 use rustc_middle::ty::TyCtxt;
 use std::{collections::hash_map::Entry, mem};
 
-use super::inspect::InspectSolve;
+use super::inspect::ProofTreeBuilder;
 use super::SolverMode;
 
 rustc_index::newtype_index! {
@@ -95,7 +95,7 @@ impl<'tcx> SearchGraph<'tcx> {
         &mut self,
         tcx: TyCtxt<'tcx>,
         input: CanonicalInput<'tcx>,
-        inspect: &mut dyn InspectSolve<'tcx>,
+        inspect: &mut ProofTreeBuilder<'tcx>,
     ) -> Result<(), QueryResult<'tcx>> {
         // Look at the provisional cache to check for cycles.
         let cache = &mut self.provisional_cache;
@@ -210,8 +210,8 @@ impl<'tcx> SearchGraph<'tcx> {
         &mut self,
         tcx: TyCtxt<'tcx>,
         canonical_input: CanonicalInput<'tcx>,
-        inspect: &mut dyn InspectSolve<'tcx>,
-        mut loop_body: impl FnMut(&mut Self, &mut dyn InspectSolve<'tcx>) -> QueryResult<'tcx>,
+        inspect: &mut ProofTreeBuilder<'tcx>,
+        mut loop_body: impl FnMut(&mut Self, &mut ProofTreeBuilder<'tcx>) -> QueryResult<'tcx>,
     ) -> QueryResult<'tcx> {
         if self.should_use_global_cache() {
             if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_input, tcx) {