Skip to content

Commit 7b86c98

Browse files
committed
do not use the global solver cache for proof trees
doing so requires overwriting global cache entries and generally adds significant complexity to the solver. This is also only ever done for root goals, so it feels easier to wrap the `evaluate_canonical_goal` in an ordinary query if necessary.
1 parent 1d8f135 commit 7b86c98

File tree

10 files changed

+74
-209
lines changed

10 files changed

+74
-209
lines changed

compiler/rustc_middle/src/arena.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,6 @@ macro_rules! arena_types {
6161
[] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>,
6262
[] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>,
6363
[] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>,
64-
[] canonical_goal_evaluation:
65-
rustc_type_ir::solve::inspect::CanonicalGoalEvaluationStep<
66-
rustc_middle::ty::TyCtxt<'tcx>
67-
>,
6864
[] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>,
6965
[] type_op_subtype:
7066
rustc_middle::infer::canonical::Canonical<'tcx,

compiler/rustc_middle/src/ty/context.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
107107
self.mk_predefined_opaques_in_body(data)
108108
}
109109
type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>;
110-
type CanonicalGoalEvaluationStepRef =
111-
&'tcx solve::inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>;
112110
type CanonicalVars = CanonicalVarInfos<'tcx>;
113111
fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
114112
self.mk_canonical_var_infos(infos)
@@ -277,13 +275,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
277275
self.debug_assert_args_compatible(def_id, args);
278276
}
279277

280-
fn intern_canonical_goal_evaluation_step(
281-
self,
282-
step: solve::inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>,
283-
) -> &'tcx solve::inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>> {
284-
self.arena.alloc(step)
285-
}
286-
287278
fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
288279
where
289280
I: Iterator<Item = T>,

compiler/rustc_next_trait_solver/src/solve/inspect/build.rs

Lines changed: 14 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
//! see the comment on [ProofTreeBuilder].
66
77
use std::marker::PhantomData;
8-
use std::mem;
98

109
use derive_where::derive_where;
1110
use rustc_type_ir::inherent::*;
12-
use rustc_type_ir::{self as ty, search_graph, Interner};
11+
use rustc_type_ir::{self as ty, Interner};
1312

1413
use crate::delegate::SolverDelegate;
1514
use crate::solve::eval_ctxt::canonical;
@@ -94,31 +93,10 @@ impl<I: Interner> WipGoalEvaluation<I> {
9493
}
9594
}
9695

97-
#[derive_where(PartialEq, Eq; I: Interner)]
98-
pub(in crate::solve) enum WipCanonicalGoalEvaluationKind<I: Interner> {
99-
Overflow,
100-
CycleInStack,
101-
ProvisionalCacheHit,
102-
Interned { final_revision: I::CanonicalGoalEvaluationStepRef },
103-
}
104-
105-
impl<I: Interner> std::fmt::Debug for WipCanonicalGoalEvaluationKind<I> {
106-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107-
match self {
108-
Self::Overflow => write!(f, "Overflow"),
109-
Self::CycleInStack => write!(f, "CycleInStack"),
110-
Self::ProvisionalCacheHit => write!(f, "ProvisionalCacheHit"),
111-
Self::Interned { final_revision: _ } => {
112-
f.debug_struct("Interned").finish_non_exhaustive()
113-
}
114-
}
115-
}
116-
}
117-
11896
#[derive_where(PartialEq, Eq, Debug; I: Interner)]
11997
struct WipCanonicalGoalEvaluation<I: Interner> {
12098
goal: CanonicalInput<I>,
121-
kind: Option<WipCanonicalGoalEvaluationKind<I>>,
99+
encountered_overflow: bool,
122100
/// Only used for uncached goals. After we finished evaluating
123101
/// the goal, this is interned and moved into `kind`.
124102
final_revision: Option<WipCanonicalGoalEvaluationStep<I>>,
@@ -127,25 +105,17 @@ struct WipCanonicalGoalEvaluation<I: Interner> {
127105

128106
impl<I: Interner> WipCanonicalGoalEvaluation<I> {
129107
fn finalize(self) -> inspect::CanonicalGoalEvaluation<I> {
130-
// We've already interned the final revision in
131-
// `fn finalize_canonical_goal_evaluation`.
132-
assert!(self.final_revision.is_none());
133-
let kind = match self.kind.unwrap() {
134-
WipCanonicalGoalEvaluationKind::Overflow => {
108+
inspect::CanonicalGoalEvaluation {
109+
goal: self.goal,
110+
kind: if self.encountered_overflow {
111+
assert!(self.final_revision.is_none());
135112
inspect::CanonicalGoalEvaluationKind::Overflow
136-
}
137-
WipCanonicalGoalEvaluationKind::CycleInStack => {
138-
inspect::CanonicalGoalEvaluationKind::CycleInStack
139-
}
140-
WipCanonicalGoalEvaluationKind::ProvisionalCacheHit => {
141-
inspect::CanonicalGoalEvaluationKind::ProvisionalCacheHit
142-
}
143-
WipCanonicalGoalEvaluationKind::Interned { final_revision } => {
113+
} else {
114+
let final_revision = self.final_revision.unwrap().finalize();
144115
inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision }
145-
}
146-
};
147-
148-
inspect::CanonicalGoalEvaluation { goal: self.goal, kind, result: self.result.unwrap() }
116+
},
117+
result: self.result.unwrap(),
118+
}
149119
}
150120
}
151121

@@ -308,7 +278,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
308278
) -> ProofTreeBuilder<D> {
309279
self.nested(|| WipCanonicalGoalEvaluation {
310280
goal,
311-
kind: None,
281+
encountered_overflow: false,
312282
final_revision: None,
313283
result: None,
314284
})
@@ -329,11 +299,11 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
329299
}
330300
}
331301

332-
pub fn canonical_goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind<I>) {
302+
pub fn canonical_goal_evaluation_overflow(&mut self) {
333303
if let Some(this) = self.as_mut() {
334304
match this {
335305
DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => {
336-
assert_eq!(canonical_goal_evaluation.kind.replace(kind), None);
306+
canonical_goal_evaluation.encountered_overflow = true;
337307
}
338308
_ => unreachable!(),
339309
};
@@ -547,51 +517,3 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
547517
}
548518
}
549519
}
550-
551-
impl<D, I> search_graph::ProofTreeBuilder<I> for ProofTreeBuilder<D>
552-
where
553-
D: SolverDelegate<Interner = I>,
554-
I: Interner,
555-
{
556-
fn try_apply_proof_tree(
557-
&mut self,
558-
proof_tree: Option<I::CanonicalGoalEvaluationStepRef>,
559-
) -> bool {
560-
if !self.is_noop() {
561-
if let Some(final_revision) = proof_tree {
562-
let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision };
563-
self.canonical_goal_evaluation_kind(kind);
564-
true
565-
} else {
566-
false
567-
}
568-
} else {
569-
true
570-
}
571-
}
572-
573-
fn on_provisional_cache_hit(&mut self) {
574-
self.canonical_goal_evaluation_kind(WipCanonicalGoalEvaluationKind::ProvisionalCacheHit);
575-
}
576-
577-
fn on_cycle_in_stack(&mut self) {
578-
self.canonical_goal_evaluation_kind(WipCanonicalGoalEvaluationKind::CycleInStack);
579-
}
580-
581-
fn finalize_canonical_goal_evaluation(
582-
&mut self,
583-
tcx: I,
584-
) -> Option<I::CanonicalGoalEvaluationStepRef> {
585-
self.as_mut().map(|this| match this {
586-
DebugSolver::CanonicalGoalEvaluation(evaluation) => {
587-
let final_revision = mem::take(&mut evaluation.final_revision).unwrap();
588-
let final_revision =
589-
tcx.intern_canonical_goal_evaluation_step(final_revision.finalize());
590-
let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision };
591-
assert_eq!(evaluation.kind.replace(kind), None);
592-
final_revision
593-
}
594-
_ => unreachable!(),
595-
})
596-
}
597-
}

compiler/rustc_next_trait_solver/src/solve/search_graph.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_type_ir::search_graph::{self, CycleKind, UsageKind};
55
use rustc_type_ir::solve::{CanonicalInput, Certainty, QueryResult};
66
use rustc_type_ir::Interner;
77

8-
use super::inspect::{self, ProofTreeBuilder};
8+
use super::inspect::ProofTreeBuilder;
99
use super::FIXPOINT_STEP_LIMIT;
1010
use crate::delegate::SolverDelegate;
1111

@@ -25,6 +25,9 @@ where
2525
const FIXPOINT_STEP_LIMIT: usize = FIXPOINT_STEP_LIMIT;
2626

2727
type ProofTreeBuilder = ProofTreeBuilder<D>;
28+
fn inspect_is_noop(inspect: &mut Self::ProofTreeBuilder) -> bool {
29+
inspect.is_noop()
30+
}
2831

2932
fn recursion_limit(cx: I) -> usize {
3033
cx.recursion_limit()
@@ -68,7 +71,7 @@ where
6871
inspect: &mut ProofTreeBuilder<D>,
6972
input: CanonicalInput<I>,
7073
) -> QueryResult<I> {
71-
inspect.canonical_goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::Overflow);
74+
inspect.canonical_goal_evaluation_overflow();
7275
response_no_constraints(cx, input, Certainty::overflow(true))
7376
}
7477

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -332,13 +332,9 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
332332

333333
pub fn candidates(&'a self) -> Vec<InspectCandidate<'a, 'tcx>> {
334334
let mut candidates = vec![];
335-
let last_eval_step = match self.evaluation_kind {
336-
inspect::CanonicalGoalEvaluationKind::Overflow
337-
| inspect::CanonicalGoalEvaluationKind::CycleInStack
338-
| inspect::CanonicalGoalEvaluationKind::ProvisionalCacheHit => {
339-
warn!("unexpected root evaluation: {:?}", self.evaluation_kind);
340-
return vec![];
341-
}
335+
let last_eval_step = match &self.evaluation_kind {
336+
// An annoying edge case in case the recursion limit is 0.
337+
inspect::CanonicalGoalEvaluationKind::Overflow => return vec![],
342338
inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision } => final_revision,
343339
};
344340

compiler/rustc_type_ir/src/interner.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use crate::inherent::*;
1111
use crate::ir_print::IrPrint;
1212
use crate::lang_items::TraitSolverLangItem;
1313
use crate::relate::Relate;
14-
use crate::solve::inspect::CanonicalGoalEvaluationStep;
1514
use crate::solve::{
1615
CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult, SolverMode,
1716
};
@@ -65,11 +64,6 @@ pub trait Interner:
6564
+ Eq
6665
+ TypeVisitable<Self>
6766
+ SliceLike<Item = Self::LocalDefId>;
68-
type CanonicalGoalEvaluationStepRef: Copy
69-
+ Debug
70-
+ Hash
71-
+ Eq
72-
+ Deref<Target = CanonicalGoalEvaluationStep<Self>>;
7367

7468
type CanonicalVars: Copy
7569
+ Debug
@@ -177,11 +171,6 @@ pub trait Interner:
177171

178172
fn debug_assert_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs);
179173

180-
fn intern_canonical_goal_evaluation_step(
181-
self,
182-
step: CanonicalGoalEvaluationStep<Self>,
183-
) -> Self::CanonicalGoalEvaluationStepRef;
184-
185174
fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
186175
where
187176
I: Iterator<Item = T>,
@@ -390,7 +379,6 @@ impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
390379
}
391380

392381
impl<I: Interner> search_graph::Cx for I {
393-
type ProofTree = Option<I::CanonicalGoalEvaluationStepRef>;
394382
type Input = CanonicalInput<I>;
395383
type Result = QueryResult<I>;
396384

compiler/rustc_type_ir/src/search_graph/global_cache.rs

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@ use rustc_index::IndexVec;
44
use super::{AvailableDepth, Cx, StackDepth, StackEntry};
55
use crate::data_structures::{HashMap, HashSet};
66

7-
#[derive_where(Debug, Clone, Copy; X: Cx)]
8-
struct QueryData<X: Cx> {
9-
result: X::Result,
10-
proof_tree: X::ProofTree,
11-
}
12-
137
struct Success<X: Cx> {
14-
data: X::Tracked<QueryData<X>>,
8+
result: X::Tracked<X::Result>,
159
additional_depth: usize,
1610
}
1711

@@ -28,13 +22,12 @@ struct CacheEntry<X: Cx> {
2822
/// See the doc comment of `StackEntry::cycle_participants` for more
2923
/// details.
3024
nested_goals: HashSet<X::Input>,
31-
with_overflow: HashMap<usize, X::Tracked<QueryData<X>>>,
25+
with_overflow: HashMap<usize, X::Tracked<X::Result>>,
3226
}
3327

3428
#[derive_where(Debug; X: Cx)]
3529
pub(super) struct CacheData<'a, X: Cx> {
3630
pub(super) result: X::Result,
37-
pub(super) proof_tree: X::ProofTree,
3831
pub(super) additional_depth: usize,
3932
pub(super) encountered_overflow: bool,
4033
// FIXME: This is currently unused, but impacts the design
@@ -55,20 +48,19 @@ impl<X: Cx> GlobalCache<X> {
5548
input: X::Input,
5649

5750
result: X::Result,
58-
proof_tree: X::ProofTree,
5951
dep_node: X::DepNodeIndex,
6052

6153
additional_depth: usize,
6254
encountered_overflow: bool,
6355
nested_goals: &HashSet<X::Input>,
6456
) {
65-
let data = cx.mk_tracked(QueryData { result, proof_tree }, dep_node);
57+
let result = cx.mk_tracked(result, dep_node);
6658
let entry = self.map.entry(input).or_default();
6759
entry.nested_goals.extend(nested_goals);
6860
if encountered_overflow {
69-
entry.with_overflow.insert(additional_depth, data);
61+
entry.with_overflow.insert(additional_depth, result);
7062
} else {
71-
entry.success = Some(Success { data, additional_depth });
63+
entry.success = Some(Success { result, additional_depth });
7264
}
7365
}
7466

@@ -90,26 +82,20 @@ impl<X: Cx> GlobalCache<X> {
9082

9183
if let Some(ref success) = entry.success {
9284
if available_depth.cache_entry_is_applicable(success.additional_depth) {
93-
let QueryData { result, proof_tree } = cx.get_tracked(&success.data);
9485
return Some(CacheData {
95-
result,
96-
proof_tree,
86+
result: cx.get_tracked(&success.result),
9787
additional_depth: success.additional_depth,
9888
encountered_overflow: false,
9989
nested_goals: &entry.nested_goals,
10090
});
10191
}
10292
}
10393

104-
entry.with_overflow.get(&available_depth.0).map(|e| {
105-
let QueryData { result, proof_tree } = cx.get_tracked(e);
106-
CacheData {
107-
result,
108-
proof_tree,
109-
additional_depth: available_depth.0,
110-
encountered_overflow: true,
111-
nested_goals: &entry.nested_goals,
112-
}
94+
entry.with_overflow.get(&available_depth.0).map(|e| CacheData {
95+
result: cx.get_tracked(e),
96+
additional_depth: available_depth.0,
97+
encountered_overflow: true,
98+
nested_goals: &entry.nested_goals,
11399
})
114100
}
115101
}

0 commit comments

Comments
 (0)