Skip to content

Commit 15ae59b

Browse files
committed
use global cache when computing proof trees
1 parent 91bbdd9 commit 15ae59b

File tree

11 files changed

+138
-126
lines changed

11 files changed

+138
-126
lines changed

compiler/rustc_middle/src/arena.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ macro_rules! arena_types {
6969
[] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>,
7070
[] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>,
7171
[] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>,
72+
[] canonical_goal_evaluation: rustc_middle::traits::solve::inspect::GoalEvaluationStep<'tcx>,
7273
[] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>,
7374
[] type_op_subtype:
7475
rustc_middle::infer::canonical::Canonical<'tcx,

compiler/rustc_middle/src/traits/solve/cache.rs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{CanonicalInput, QueryResult};
1+
use super::{inspect, CanonicalInput, QueryResult};
22
use crate::ty::TyCtxt;
33
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
44
use rustc_data_structures::sync::Lock;
@@ -14,8 +14,10 @@ pub struct EvaluationCache<'tcx> {
1414
map: Lock<FxHashMap<CanonicalInput<'tcx>, CacheEntry<'tcx>>>,
1515
}
1616

17+
#[derive(PartialEq, Eq)]
1718
pub struct CacheData<'tcx> {
1819
pub result: QueryResult<'tcx>,
20+
pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>,
1921
pub reached_depth: usize,
2022
pub encountered_overflow: bool,
2123
}
@@ -24,22 +26,33 @@ impl<'tcx> EvaluationCache<'tcx> {
2426
/// Insert a final result into the global cache.
2527
pub fn insert(
2628
&self,
29+
tcx: TyCtxt<'tcx>,
2730
key: CanonicalInput<'tcx>,
31+
proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>,
2832
reached_depth: usize,
29-
did_overflow: bool,
33+
encountered_overflow: bool,
3034
cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
3135
dep_node: DepNodeIndex,
3236
result: QueryResult<'tcx>,
3337
) {
3438
let mut map = self.map.borrow_mut();
3539
let entry = map.entry(key).or_default();
36-
let data = WithDepNode::new(dep_node, result);
40+
let data = WithDepNode::new(dep_node, QueryData { result, proof_tree });
3741
entry.cycle_participants.extend(cycle_participants);
38-
if did_overflow {
42+
if encountered_overflow {
3943
entry.with_overflow.insert(reached_depth, data);
4044
} else {
4145
entry.success = Some(Success { data, reached_depth });
4246
}
47+
48+
if cfg!(debug_assertions) {
49+
drop(map);
50+
if Some(CacheData { result, proof_tree, reached_depth, encountered_overflow })
51+
!= self.get(tcx, key, |_| false, Limit(reached_depth))
52+
{
53+
bug!("unable to retrieve inserted element from cache: {key:?}");
54+
}
55+
}
4356
}
4457

4558
/// Try to fetch a cached result, checking the recursion limit
@@ -62,27 +75,39 @@ impl<'tcx> EvaluationCache<'tcx> {
6275

6376
if let Some(ref success) = entry.success {
6477
if available_depth.value_within_limit(success.reached_depth) {
78+
let QueryData { result, proof_tree } = success.data.get(tcx);
6579
return Some(CacheData {
66-
result: success.data.get(tcx),
80+
result,
81+
proof_tree,
6782
reached_depth: success.reached_depth,
6883
encountered_overflow: false,
6984
});
7085
}
7186
}
7287

73-
entry.with_overflow.get(&available_depth.0).map(|e| CacheData {
74-
result: e.get(tcx),
75-
reached_depth: available_depth.0,
76-
encountered_overflow: true,
88+
entry.with_overflow.get(&available_depth.0).map(|e| {
89+
let QueryData { result, proof_tree } = e.get(tcx);
90+
CacheData {
91+
result,
92+
proof_tree,
93+
reached_depth: available_depth.0,
94+
encountered_overflow: true,
95+
}
7796
})
7897
}
7998
}
8099

81100
struct Success<'tcx> {
82-
data: WithDepNode<QueryResult<'tcx>>,
101+
data: WithDepNode<QueryData<'tcx>>,
83102
reached_depth: usize,
84103
}
85104

105+
#[derive(Clone, Copy)]
106+
pub struct QueryData<'tcx> {
107+
pub result: QueryResult<'tcx>,
108+
pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>,
109+
}
110+
86111
/// The cache entry for a goal `CanonicalInput`.
87112
///
88113
/// This contains results whose computation never hit the
@@ -96,5 +121,5 @@ struct CacheEntry<'tcx> {
96121
/// See the doc comment of `StackEntry::cycle_participants` for more
97122
/// details.
98123
cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
99-
with_overflow: FxHashMap<usize, WithDepNode<QueryResult<'tcx>>>,
124+
with_overflow: FxHashMap<usize, WithDepNode<QueryData<'tcx>>>,
100125
}

compiler/rustc_middle/src/traits/solve/inspect.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ pub struct State<'tcx, T> {
4242

4343
pub type CanonicalState<'tcx, T> = Canonical<'tcx, State<'tcx, T>>;
4444

45-
#[derive(Debug, Eq, PartialEq)]
46-
pub enum CacheHit {
47-
Provisional,
48-
Global,
49-
}
50-
5145
/// When evaluating the root goals we also store the
5246
/// original values for the `CanonicalVarValues` of the
5347
/// canonicalized goal. We use this to map any [CanonicalState]
@@ -78,8 +72,8 @@ pub struct CanonicalGoalEvaluation<'tcx> {
7872
#[derive(Eq, PartialEq)]
7973
pub enum CanonicalGoalEvaluationKind<'tcx> {
8074
Overflow,
81-
CacheHit(CacheHit),
82-
Uncached { revisions: Vec<GoalEvaluationStep<'tcx>> },
75+
CycleInStack,
76+
Evaluation { revisions: &'tcx [GoalEvaluationStep<'tcx>] },
8377
}
8478
impl Debug for GoalEvaluation<'_> {
8579
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

compiler/rustc_middle/src/traits/solve/inspect/format.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,10 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
7474
CanonicalGoalEvaluationKind::Overflow => {
7575
writeln!(self.f, "OVERFLOW: {:?}", eval.result)
7676
}
77-
CanonicalGoalEvaluationKind::CacheHit(CacheHit::Global) => {
78-
writeln!(self.f, "GLOBAL CACHE HIT: {:?}", eval.result)
77+
CanonicalGoalEvaluationKind::CycleInStack => {
78+
writeln!(self.f, "CYCLE IN STACK: {:?}", eval.result)
7979
}
80-
CanonicalGoalEvaluationKind::CacheHit(CacheHit::Provisional) => {
81-
writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", eval.result)
82-
}
83-
CanonicalGoalEvaluationKind::Uncached { revisions } => {
80+
CanonicalGoalEvaluationKind::Evaluation { revisions } => {
8481
for (n, step) in revisions.iter().enumerate() {
8582
writeln!(self.f, "REVISION {n}")?;
8683
self.nested(|this| this.format_evaluation_step(step))?;

compiler/rustc_session/src/options.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,8 +1529,6 @@ options! {
15291529
dump_solver_proof_tree: DumpSolverProofTree = (DumpSolverProofTree::Never, parse_dump_solver_proof_tree, [UNTRACKED],
15301530
"dump a proof tree for every goal evaluated by the new trait solver. If the flag is specified without any options after it
15311531
then it defaults to `always`. If the flag is not specified at all it defaults to `on-request`."),
1532-
dump_solver_proof_tree_use_cache: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
1533-
"determines whether dumped proof trees use the global cache"),
15341532
dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
15351533
"version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
15361534
dylib_lto: bool = (false, parse_bool, [UNTRACKED],

compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -119,25 +119,11 @@ impl NestedGoals<'_> {
119119

120120
#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
121121
pub enum GenerateProofTree {
122-
Yes(UseGlobalCache),
122+
Yes,
123123
IfEnabled,
124124
Never,
125125
}
126126

127-
#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
128-
pub enum UseGlobalCache {
129-
Yes,
130-
No,
131-
}
132-
impl UseGlobalCache {
133-
pub fn from_bool(use_cache: bool) -> Self {
134-
match use_cache {
135-
true => UseGlobalCache::Yes,
136-
false => UseGlobalCache::No,
137-
}
138-
}
139-
}
140-
141127
pub trait InferCtxtEvalExt<'tcx> {
142128
/// Evaluates a goal from **outside** of the trait solver.
143129
///

compiler/rustc_trait_selection/src/solve/inspect/analyse.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_middle::traits::solve::{Certainty, Goal};
1717
use rustc_middle::ty;
1818

1919
use crate::solve::inspect::ProofTreeBuilder;
20-
use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache};
20+
use crate::solve::{GenerateProofTree, InferCtxtEvalExt};
2121

2222
pub struct InspectGoal<'a, 'tcx> {
2323
infcx: &'a InferCtxt<'tcx>,
@@ -82,8 +82,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
8282
}
8383

8484
for &goal in &instantiated_goals {
85-
let (_, proof_tree) =
86-
infcx.evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No));
85+
let (_, proof_tree) = infcx.evaluate_root_goal(goal, GenerateProofTree::Yes);
8786
let proof_tree = proof_tree.unwrap();
8887
visitor.visit_goal(&InspectGoal::new(
8988
infcx,
@@ -169,11 +168,11 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
169168
let mut candidates = vec![];
170169
let last_eval_step = match self.evaluation.evaluation.kind {
171170
inspect::CanonicalGoalEvaluationKind::Overflow
172-
| inspect::CanonicalGoalEvaluationKind::CacheHit(_) => {
171+
| inspect::CanonicalGoalEvaluationKind::CycleInStack => {
173172
warn!("unexpected root evaluation: {:?}", self.evaluation);
174173
return vec![];
175174
}
176-
inspect::CanonicalGoalEvaluationKind::Uncached { ref revisions } => {
175+
inspect::CanonicalGoalEvaluationKind::Evaluation { ref revisions } => {
177176
if let Some(last) = revisions.last() {
178177
last
179178
} else {
@@ -227,8 +226,7 @@ impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> {
227226
goal: Goal<'tcx, ty::Predicate<'tcx>>,
228227
visitor: &mut V,
229228
) -> ControlFlow<V::BreakTy> {
230-
let (_, proof_tree) =
231-
self.evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No));
229+
let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
232230
let proof_tree = proof_tree.unwrap();
233231
visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree))
234232
}

0 commit comments

Comments
 (0)