diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ece056afafc..27d0cf6890f 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -746,11 +746,11 @@ pub enum TraitSolver { } #[derive(Default, Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub enum SolverProofTreeCondition { - #[default] - OnRequest, +pub enum DumpSolverProofTree { Always, OnError, + #[default] + Never, } pub enum Input { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 58ea6ef1f9e..ce8846f604b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -418,8 +418,7 @@ mod desc { "a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf`"; pub const parse_proc_macro_execution_strategy: &str = "one of supported execution strategies (`same-thread`, or `cross-thread`)"; - pub const parse_solver_proof_tree_condition: &str = - "one of: `always`, `on-request`, `on-error`"; + pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`"; } mod parse { @@ -1241,14 +1240,14 @@ mod parse { true } - pub(crate) fn parse_solver_proof_tree_condition( - slot: &mut SolverProofTreeCondition, + pub(crate) fn parse_dump_solver_proof_tree( + slot: &mut DumpSolverProofTree, v: Option<&str>, ) -> bool { match v { - None | Some("always") => *slot = SolverProofTreeCondition::Always, - Some("on-request") => *slot = SolverProofTreeCondition::OnRequest, - Some("on-error") => *slot = SolverProofTreeCondition::OnError, + None | Some("always") => *slot = DumpSolverProofTree::Always, + Some("never") => *slot = DumpSolverProofTree::Never, + Some("on-error") => *slot = DumpSolverProofTree::OnError, _ => return false, }; true @@ -1478,11 +1477,11 @@ options! { "output statistics about monomorphization collection"), dump_mono_stats_format: DumpMonoStatsFormat = (DumpMonoStatsFormat::Markdown, parse_dump_mono_stats, [UNTRACKED], "the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)"), - dump_solver_proof_tree: SolverProofTreeCondition = (SolverProofTreeCondition::OnRequest, parse_solver_proof_tree_condition, [UNTRACKED], + dump_solver_proof_tree: DumpSolverProofTree = (DumpSolverProofTree::Never, parse_dump_solver_proof_tree, [UNTRACKED], "dump a proof tree for every goal evaluated by the new trait solver. If the flag is specified without any options after it then it defaults to `always`. If the flag is not specified at all it defaults to `on-request`."), dump_solver_proof_tree_use_cache: Option = (None, parse_opt_bool, [UNTRACKED], - "determines whether proof tree generation uses the global cache"), + "determines whether dumped proof trees use the global cache"), dwarf_version: Option = (None, parse_opt_number, [TRACKED], "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), dylib_lto: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 5d1083090e3..4f15724e812 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::{ self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_session::config::SolverProofTreeCondition; +use rustc_session::config::DumpSolverProofTree; use rustc_span::DUMMY_SP; use std::io::Write; use std::ops::ControlFlow; @@ -115,20 +115,20 @@ impl NestedGoals<'_> { #[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)] pub enum GenerateProofTree { - Yes(DisableGlobalCache), + Yes(UseGlobalCache), No, } #[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)] -pub enum DisableGlobalCache { +pub enum UseGlobalCache { Yes, No, } -impl DisableGlobalCache { - pub fn from_bool(disable_cache: bool) -> Self { - match disable_cache { - true => DisableGlobalCache::Yes, - false => DisableGlobalCache::No, +impl UseGlobalCache { + pub fn from_bool(use_cache: bool) -> Self { + match use_cache { + true => UseGlobalCache::Yes, + false => UseGlobalCache::No, } } } @@ -198,7 +198,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { let result = f(&mut ecx); let tree = ecx.inspect.finalize(); - if let (Some(tree), SolverProofTreeCondition::Always) = + if let (Some(tree), DumpSolverProofTree::Always) = (&tree, infcx.tcx.sess.opts.unstable_opts.dump_solver_proof_tree) { let mut lock = std::io::stdout().lock(); diff --git a/compiler/rustc_trait_selection/src/solve/inspect.rs b/compiler/rustc_trait_selection/src/solve/inspect.rs index 2061c3feb82..2d6717fdad9 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect.rs @@ -4,9 +4,9 @@ use rustc_middle::traits::solve::{ CanonicalInput, Certainty, Goal, IsNormalizesToHack, QueryInput, QueryResult, }; use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::config::SolverProofTreeCondition; +use rustc_session::config::DumpSolverProofTree; -use super::eval_ctxt::DisableGlobalCache; +use super::eval_ctxt::UseGlobalCache; use super::GenerateProofTree; #[derive(Eq, PartialEq, Debug, Hash, HashStable)] @@ -146,24 +146,42 @@ impl<'tcx> From> for DebugSolver<'tcx> { } pub struct ProofTreeBuilder<'tcx> { - state: Option>>, - disable_global_cache: DisableGlobalCache, + state: Option>>, +} + +struct BuilderData<'tcx> { + tree: DebugSolver<'tcx>, + use_global_cache: UseGlobalCache, } impl<'tcx> ProofTreeBuilder<'tcx> { fn new( state: impl Into>, - disable_global_cache: DisableGlobalCache, + use_global_cache: UseGlobalCache, ) -> ProofTreeBuilder<'tcx> { - ProofTreeBuilder { state: Some(Box::new(state.into())), disable_global_cache } + ProofTreeBuilder { + state: Some(Box::new(BuilderData { tree: state.into(), use_global_cache })), + } + } + + fn nested(&self, state: impl Into>) -> 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 }, + } } fn as_mut(&mut self) -> Option<&mut DebugSolver<'tcx>> { - self.state.as_mut().map(|boxed| &mut **boxed) + self.state.as_mut().map(|boxed| &mut boxed.tree) } pub fn finalize(self) -> Option> { - match *(self.state?) { + match self.state?.tree { DebugSolver::GoalEvaluation(wip_goal_evaluation) => { Some(wip_goal_evaluation.finalize()) } @@ -171,8 +189,11 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn disable_global_cache(&self) -> DisableGlobalCache { - self.disable_global_cache + 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( @@ -185,17 +206,17 @@ impl<'tcx> ProofTreeBuilder<'tcx> { generate_proof_tree, ) { (_, Some(use_cache), GenerateProofTree::Yes(_)) => { - GenerateProofTree::Yes(DisableGlobalCache::from_bool(!use_cache)) + GenerateProofTree::Yes(UseGlobalCache::from_bool(use_cache)) } - (SolverProofTreeCondition::Always, use_cache, GenerateProofTree::No) => { + (DumpSolverProofTree::Always, use_cache, GenerateProofTree::No) => { let use_cache = use_cache.unwrap_or(true); - GenerateProofTree::Yes(DisableGlobalCache::from_bool(!use_cache)) + GenerateProofTree::Yes(UseGlobalCache::from_bool(use_cache)) } (_, None, GenerateProofTree::Yes(_)) => generate_proof_tree, - (SolverProofTreeCondition::OnRequest, _, _) => generate_proof_tree, - (SolverProofTreeCondition::OnError, _, _) => generate_proof_tree, + (DumpSolverProofTree::Never, _, _) => generate_proof_tree, + (DumpSolverProofTree::OnError, _, _) => generate_proof_tree, }; match generate_proof_tree { @@ -206,12 +227,12 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn new_root(disable_global_cache: DisableGlobalCache) -> ProofTreeBuilder<'tcx> { - ProofTreeBuilder::new(DebugSolver::Root, disable_global_cache) + pub fn new_root(use_global_cache: UseGlobalCache) -> ProofTreeBuilder<'tcx> { + ProofTreeBuilder::new(DebugSolver::Root, use_global_cache) } pub fn new_noop() -> ProofTreeBuilder<'tcx> { - ProofTreeBuilder { state: None, disable_global_cache: DisableGlobalCache::No } + ProofTreeBuilder { state: None } } pub fn is_noop(&self) -> bool { @@ -224,24 +245,18 @@ impl<'tcx> ProofTreeBuilder<'tcx> { is_normalizes_to_hack: IsNormalizesToHack, ) -> ProofTreeBuilder<'tcx> { if self.state.is_none() { - return ProofTreeBuilder { - state: None, - disable_global_cache: self.disable_global_cache, - }; + return ProofTreeBuilder { state: 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, - ) + self.nested(WipGoalEvaluation { + uncanonicalized_goal: goal, + canonicalized_goal: None, + evaluation_steps: vec![], + is_normalizes_to_hack, + cache_hit: None, + returned_goals: vec![], + result: None, + }) } pub fn canonicalized_goal(&mut self, canonical_goal: CanonicalInput<'tcx>) { @@ -279,7 +294,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()) { + match (this, goal_evaluation.state.unwrap().tree) { ( DebugSolver::AddedGoalsEvaluation(WipAddedGoalsEvaluation { evaluations, .. @@ -297,25 +312,19 @@ impl<'tcx> ProofTreeBuilder<'tcx> { instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, ) -> ProofTreeBuilder<'tcx> { if self.state.is_none() { - return ProofTreeBuilder { - state: None, - disable_global_cache: self.disable_global_cache, - }; + return ProofTreeBuilder { state: None }; } - ProofTreeBuilder::new( - WipGoalEvaluationStep { - instantiated_goal, - nested_goal_evaluations: vec![], - candidates: vec![], - result: None, - }, - self.disable_global_cache, - ) + self.nested(WipGoalEvaluationStep { + instantiated_goal, + nested_goal_evaluations: vec![], + candidates: vec![], + result: None, + }) } pub fn goal_evaluation_step(&mut self, goal_eval_step: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, *goal_eval_step.state.unwrap()) { + match (this, goal_eval_step.state.unwrap().tree) { (DebugSolver::GoalEvaluation(goal_eval), DebugSolver::GoalEvaluationStep(step)) => { goal_eval.evaluation_steps.push(step); } @@ -326,17 +335,14 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn new_goal_candidate(&mut self) -> ProofTreeBuilder<'tcx> { if self.state.is_none() { - return ProofTreeBuilder { - state: None, - - disable_global_cache: self.disable_global_cache, - }; + return ProofTreeBuilder { state: None }; } - ProofTreeBuilder::new( - WipGoalCandidate { nested_goal_evaluations: vec![], candidates: vec![], kind: None }, - self.disable_global_cache, - ) + self.nested(WipGoalCandidate { + nested_goal_evaluations: vec![], + candidates: vec![], + kind: None, + }) } pub fn candidate_kind(&mut self, candidate_kind: CandidateKind<'tcx>) { @@ -352,7 +358,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn goal_candidate(&mut self, candidate: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, *candidate.state.unwrap()) { + match (this, candidate.state.unwrap().tree) { ( DebugSolver::GoalCandidate(WipGoalCandidate { candidates, .. }) | DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { candidates, .. }), @@ -365,17 +371,10 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn new_evaluate_added_goals(&mut self) -> ProofTreeBuilder<'tcx> { if self.state.is_none() { - return ProofTreeBuilder { - state: None, - - disable_global_cache: self.disable_global_cache, - }; + return ProofTreeBuilder { state: None }; } - ProofTreeBuilder::new( - WipAddedGoalsEvaluation { evaluations: vec![], result: None }, - self.disable_global_cache, - ) + self.nested(WipAddedGoalsEvaluation { evaluations: vec![], result: None }) } pub fn evaluate_added_goals_loop_start(&mut self) { @@ -402,7 +401,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { pub fn added_goals_evaluation(&mut self, goals_evaluation: ProofTreeBuilder<'tcx>) { if let Some(this) = self.as_mut() { - match (this, *goals_evaluation.state.unwrap()) { + match (this, goals_evaluation.state.unwrap().tree) { ( DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { nested_goal_evaluations, diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index c0f71fe70a6..8f142a309d7 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -34,7 +34,7 @@ mod trait_goals; mod weak_types; pub use eval_ctxt::{ - DisableGlobalCache, EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt, + EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt, UseGlobalCache, }; 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 da41ed01acd..f00456e26df 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,6 @@ 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; @@ -214,9 +213,7 @@ 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() - && inspect.disable_global_cache() == DisableGlobalCache::No - { + if self.should_use_global_cache() && inspect.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(CacheHit::Global); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 0b91a5fc70a..9a55fdaf7bb 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -10,7 +10,7 @@ use super::{ use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{self, InferCtxt}; -use crate::solve::{DisableGlobalCache, GenerateProofTree, InferCtxtEvalExt}; +use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache}; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::normalize::QueryNormalizeExt as _; use crate::traits::specialize::to_pretty_impl_header; @@ -39,7 +39,7 @@ use rustc_middle::ty::{ self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, }; -use rustc_session::config::{SolverProofTreeCondition, TraitSolver}; +use rustc_session::config::{DumpSolverProofTree, TraitSolver}; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::sym; @@ -634,7 +634,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) { let tcx = self.tcx; - if tcx.sess.opts.unstable_opts.dump_solver_proof_tree == SolverProofTreeCondition::OnError { + if tcx.sess.opts.unstable_opts.dump_solver_proof_tree == DumpSolverProofTree::OnError { dump_proof_tree(root_obligation, self.infcx); } @@ -1537,9 +1537,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { #[instrument(skip(self), level = "debug")] fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) { - if self.tcx.sess.opts.unstable_opts.dump_solver_proof_tree - == SolverProofTreeCondition::OnError - { + if self.tcx.sess.opts.unstable_opts.dump_solver_proof_tree == DumpSolverProofTree::OnError { dump_proof_tree(&error.root_obligation, self.infcx); } @@ -3518,7 +3516,7 @@ pub fn dump_proof_tree<'tcx>(o: &Obligation<'tcx, ty::Predicate<'tcx>>, infcx: & infcx.probe(|_| { let goal = Goal { predicate: o.predicate, param_env: o.param_env }; let tree = infcx - .evaluate_root_goal(goal, GenerateProofTree::Yes(DisableGlobalCache::Yes)) + .evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No)) .1 .expect("proof tree should have been generated"); let mut lock = std::io::stdout().lock();