diff options
| author | Boxy <supbscripter@gmail.com> | 2023-07-03 21:00:10 +0100 |
|---|---|---|
| committer | Boxy <supbscripter@gmail.com> | 2023-07-03 21:00:16 +0100 |
| commit | 040aa58d0a5e35b73c487e395e3d59263de188ff (patch) | |
| tree | 6ee545db70bac74a562b5bc6127c78d088238e70 /compiler/rustc_trait_selection/src/solve | |
| parent | 8931edf746da6aa2d86412516d805f5680929a5e (diff) | |
| download | rust-040aa58d0a5e35b73c487e395e3d59263de188ff.tar.gz rust-040aa58d0a5e35b73c487e395e3d59263de188ff.zip | |
add flag for disabling global cache and printing proof trees on error
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve')
5 files changed, 121 insertions, 45 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 3b0c5849099..9fe860fe114 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -19,7 +19,9 @@ use rustc_middle::ty::{ self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; +use rustc_session::config::SolverProofTreeCondition; use rustc_span::DUMMY_SP; +use std::io::Write; use std::ops::ControlFlow; use crate::traits::specialization_graph; @@ -113,9 +115,23 @@ impl NestedGoals<'_> { #[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)] pub enum GenerateProofTree { + Yes(DisableGlobalCache), + No, +} + +#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)] +pub enum DisableGlobalCache { Yes, No, } +impl DisableGlobalCache { + pub fn from_bool(disable_cache: bool) -> Self { + match disable_cache { + true => DisableGlobalCache::Yes, + false => DisableGlobalCache::No, + } + } +} pub trait InferCtxtEvalExt<'tcx> { /// Evaluates a goal from **outside** of the trait solver. @@ -164,6 +180,36 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { let mode = if infcx.intercrate { SolverMode::Coherence } else { SolverMode::Normal }; let mut search_graph = search_graph::SearchGraph::new(infcx.tcx, mode); + let inspect = { + let generate_proof_tree = match ( + infcx.tcx.sess.opts.unstable_opts.dump_solver_proof_tree, + infcx.tcx.sess.opts.unstable_opts.dump_solver_proof_tree_uses_cache, + generate_proof_tree, + ) { + (_, Some(use_cache), GenerateProofTree::Yes(_)) => { + GenerateProofTree::Yes(DisableGlobalCache::from_bool(!use_cache)) + } + + (SolverProofTreeCondition::Always, use_cache, GenerateProofTree::No) => { + let use_cache = use_cache.unwrap_or(true); + GenerateProofTree::Yes(DisableGlobalCache::from_bool(!use_cache)) + } + + (_, None, GenerateProofTree::Yes(_)) => generate_proof_tree, + // `Never` is kind of weird- it doesn't actually force us to not generate proof trees + // its just the default setting for rustflags forced proof tree generation. + (SolverProofTreeCondition::Never, _, _) => generate_proof_tree, + (SolverProofTreeCondition::OnError, _, _) => generate_proof_tree, + }; + + match generate_proof_tree { + GenerateProofTree::No => ProofTreeBuilder::new_noop(), + GenerateProofTree::Yes(global_cache_disabled) => { + ProofTreeBuilder::new_root(global_cache_disabled) + } + } + }; + let mut ecx = EvalCtxt { search_graph: &mut search_graph, infcx: infcx, @@ -177,17 +223,17 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { var_values: CanonicalVarValues::dummy(), nested_goals: NestedGoals::new(), tainted: Ok(()), - inspect: (infcx.tcx.sess.opts.unstable_opts.dump_solver_proof_tree - || matches!(generate_proof_tree, GenerateProofTree::Yes)) - .then(ProofTreeBuilder::new_root) - .unwrap_or_else(ProofTreeBuilder::new_noop), + inspect, }; let result = f(&mut ecx); let tree = ecx.inspect.finalize(); - if let Some(tree) = &tree { - // module to allow more granular RUSTC_LOG filtering to just proof tree output - super::inspect::dump::print_tree(tree); + if let (Some(tree), SolverProofTreeCondition::Always) = + (&tree, infcx.tcx.sess.opts.unstable_opts.dump_solver_proof_tree) + { + let mut lock = std::io::stdout().lock(); + let _ = lock.write_fmt(format_args!("{tree:?}")); + let _ = lock.flush(); } assert!( diff --git a/compiler/rustc_trait_selection/src/solve/inspect.rs b/compiler/rustc_trait_selection/src/solve/inspect.rs index 6d7804a8fad..1872c0c92d8 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect.rs @@ -5,7 +5,7 @@ use rustc_middle::traits::solve::{ }; use rustc_middle::ty; -pub mod dump; +use super::eval_ctxt::DisableGlobalCache; #[derive(Eq, PartialEq, Debug, Hash, HashStable)] pub struct WipGoalEvaluation<'tcx> { @@ -145,11 +145,15 @@ impl<'tcx> From<WipGoalCandidate<'tcx>> for DebugSolver<'tcx> { pub struct ProofTreeBuilder<'tcx> { state: Option<Box<DebugSolver<'tcx>>>, + disable_global_cache: DisableGlobalCache, } impl<'tcx> ProofTreeBuilder<'tcx> { - fn new(state: impl Into<DebugSolver<'tcx>>) -> ProofTreeBuilder<'tcx> { - ProofTreeBuilder { state: Some(Box::new(state.into())) } + fn new( + state: impl Into<DebugSolver<'tcx>>, + disable_global_cache: DisableGlobalCache, + ) -> ProofTreeBuilder<'tcx> { + ProofTreeBuilder { state: Some(Box::new(state.into())), disable_global_cache } } fn as_mut(&mut self) -> Option<&mut DebugSolver<'tcx>> { @@ -165,12 +169,16 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn new_root() -> ProofTreeBuilder<'tcx> { - ProofTreeBuilder::new(DebugSolver::Root) + pub fn disable_global_cache(&self) -> DisableGlobalCache { + self.disable_global_cache + } + + pub fn new_root(disable_global_cache: DisableGlobalCache) -> ProofTreeBuilder<'tcx> { + ProofTreeBuilder::new(DebugSolver::Root, disable_global_cache) } pub fn new_noop() -> ProofTreeBuilder<'tcx> { - ProofTreeBuilder { state: None } + ProofTreeBuilder { state: None, disable_global_cache: DisableGlobalCache::No } } pub fn is_noop(&self) -> bool { @@ -183,18 +191,24 @@ impl<'tcx> ProofTreeBuilder<'tcx> { is_normalizes_to_hack: IsNormalizesToHack, ) -> ProofTreeBuilder<'tcx> { if self.state.is_none() { - return ProofTreeBuilder { state: None }; + return ProofTreeBuilder { + state: None, + disable_global_cache: self.disable_global_cache, + }; } - ProofTreeBuilder::new(WipGoalEvaluation { - uncanonicalized_goal: goal, - canonicalized_goal: None, - evaluation_steps: vec![], - is_normalizes_to_hack, - cache_hit: None, - returned_goals: vec![], - result: None, - }) + ProofTreeBuilder::new( + WipGoalEvaluation { + uncanonicalized_goal: goal, + canonicalized_goal: None, + evaluation_steps: vec![], + is_normalizes_to_hack, + cache_hit: None, + returned_goals: vec![], + result: None, + }, + self.disable_global_cache, + ) } pub fn canonicalized_goal(&mut self, canonical_goal: CanonicalInput<'tcx>) { @@ -250,15 +264,21 @@ impl<'tcx> ProofTreeBuilder<'tcx> { instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, ) -> ProofTreeBuilder<'tcx> { if self.state.is_none() { - return ProofTreeBuilder { state: None }; + return ProofTreeBuilder { + state: None, + disable_global_cache: self.disable_global_cache, + }; } - ProofTreeBuilder::new(WipGoalEvaluationStep { - instantiated_goal, - nested_goal_evaluations: vec![], - candidates: vec![], - result: None, - }) + ProofTreeBuilder::new( + WipGoalEvaluationStep { + instantiated_goal, + nested_goal_evaluations: vec![], + candidates: vec![], + result: None, + }, + self.disable_global_cache, + ) } pub fn goal_evaluation_step(&mut self, goal_eval_step: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { @@ -273,14 +293,17 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn new_goal_candidate(&mut self) -> ProofTreeBuilder<'tcx> { if self.state.is_none() { - return ProofTreeBuilder { state: None }; + return ProofTreeBuilder { + state: None, + + disable_global_cache: self.disable_global_cache, + }; } - ProofTreeBuilder::new(WipGoalCandidate { - nested_goal_evaluations: vec![], - candidates: vec![], - kind: None, - }) + ProofTreeBuilder::new( + WipGoalCandidate { nested_goal_evaluations: vec![], candidates: vec![], kind: None }, + self.disable_global_cache, + ) } pub fn candidate_kind(&mut self, candidate_kind: CandidateKind<'tcx>) { @@ -309,10 +332,17 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn new_evaluate_added_goals(&mut self) -> ProofTreeBuilder<'tcx> { if self.state.is_none() { - return ProofTreeBuilder { state: None }; + return ProofTreeBuilder { + state: None, + + disable_global_cache: self.disable_global_cache, + }; } - ProofTreeBuilder::new(WipAddedGoalsEvaluation { evaluations: vec![], result: None }) + ProofTreeBuilder::new( + WipAddedGoalsEvaluation { evaluations: vec![], result: None }, + self.disable_global_cache, + ) } pub fn evaluate_added_goals_loop_start(&mut self) { diff --git a/compiler/rustc_trait_selection/src/solve/inspect/dump.rs b/compiler/rustc_trait_selection/src/solve/inspect/dump.rs deleted file mode 100644 index b755ee86215..00000000000 --- a/compiler/rustc_trait_selection/src/solve/inspect/dump.rs +++ /dev/null @@ -1,5 +0,0 @@ -use rustc_middle::traits::solve::inspect::GoalEvaluation; - -pub fn print_tree(tree: &GoalEvaluation<'_>) { - debug!(?tree); -} diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index f3f78cdf09d..c0f71fe70a6 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -33,7 +33,9 @@ mod search_graph; mod trait_goals; mod weak_types; -pub use eval_ctxt::{EvalCtxt, InferCtxtEvalExt, InferCtxtSelectExt}; +pub use eval_ctxt::{ + DisableGlobalCache, EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt, +}; pub use fulfill::FulfillmentCtxt; pub(crate) use normalize::deeply_normalize; 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 d167ee46b39..da41ed01acd 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -13,6 +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::eval_ctxt::DisableGlobalCache; use super::inspect::ProofTreeBuilder; use super::SolverMode; @@ -213,7 +214,9 @@ impl<'tcx> SearchGraph<'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 self.should_use_global_cache() + && inspect.disable_global_cache() == DisableGlobalCache::No + { if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_input, tcx) { debug!(?canonical_input, ?result, "cache hit"); inspect.cache_hit(CacheHit::Global); |
