Skip to content

Commit 526da23

Browse files
authored
Rollup merge of #127627 - lcnr:rustc_search_graph, r=compiler-errors
generalize search graph to enable fuzzing I do not believe it to be feasible to correctly implement the search graph without fuzzing. This PR enables this by requiring a fuzzer to only implement three new traits: - `Cx`: implemented by all `I: Interner` - `ProofTreeBuilder`: implemented by `struct ProofTreeBuilder<D>` for all `D: SolverDelegate` - `Delegate`: implemented for a new `struct SearchGraphDelegate<D>` for all `D: SolverDelegate` It also moves the evaluation cache implementation into `rustc_type_ir`, requiring `Interner` to provide methods to create and access arbitrary `WithDepNode<T>` and to provide mutable access to a given `GlobalCache`. It otherwise does not change the API surface for users of the shared library. This change should not impact behavior in any way. r? ``@compiler-errors``
2 parents f5fa6fb + 15f770b commit 526da23

File tree

14 files changed

+982
-757
lines changed

14 files changed

+982
-757
lines changed

compiler/rustc_middle/src/traits/solve.rs

-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ use crate::ty::{
88
self, FallibleTypeFolder, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
99
};
1010

11-
mod cache;
12-
13-
pub use cache::EvaluationCache;
14-
1511
pub type Goal<'tcx, P> = ir::solve::Goal<TyCtxt<'tcx>, P>;
1612
pub type QueryInput<'tcx, P> = ir::solve::QueryInput<TyCtxt<'tcx>, P>;
1713
pub type QueryResult<'tcx> = ir::solve::QueryResult<TyCtxt<'tcx>>;

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

-121
This file was deleted.

compiler/rustc_middle/src/ty/context.rs

+22-7
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ use rustc_hir::lang_items::LangItem;
5959
use rustc_hir::{HirId, Node, TraitCandidate};
6060
use rustc_index::IndexVec;
6161
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
62+
use rustc_query_system::cache::WithDepNode;
6263
use rustc_query_system::dep_graph::DepNodeIndex;
6364
use rustc_query_system::ich::StableHashingContext;
6465
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
@@ -75,7 +76,7 @@ use rustc_type_ir::fold::TypeFoldable;
7576
use rustc_type_ir::lang_items::TraitSolverLangItem;
7677
use rustc_type_ir::solve::SolverMode;
7778
use rustc_type_ir::TyKind::*;
78-
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo};
79+
use rustc_type_ir::{search_graph, CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo};
7980
use tracing::{debug, instrument};
8081

8182
use std::assert_matches::assert_matches;
@@ -164,12 +165,26 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
164165
type Clause = Clause<'tcx>;
165166
type Clauses = ty::Clauses<'tcx>;
166167

167-
type EvaluationCache = &'tcx solve::EvaluationCache<'tcx>;
168+
type Tracked<T: fmt::Debug + Clone> = WithDepNode<T>;
169+
fn mk_tracked<T: fmt::Debug + Clone>(
170+
self,
171+
data: T,
172+
dep_node: DepNodeIndex,
173+
) -> Self::Tracked<T> {
174+
WithDepNode::new(dep_node, data)
175+
}
176+
fn get_tracked<T: fmt::Debug + Clone>(self, tracked: &Self::Tracked<T>) -> T {
177+
tracked.get(self)
178+
}
168179

169-
fn evaluation_cache(self, mode: SolverMode) -> &'tcx solve::EvaluationCache<'tcx> {
180+
fn with_global_cache<R>(
181+
self,
182+
mode: SolverMode,
183+
f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
184+
) -> R {
170185
match mode {
171-
SolverMode::Normal => &self.new_solver_evaluation_cache,
172-
SolverMode::Coherence => &self.new_solver_coherence_evaluation_cache,
186+
SolverMode::Normal => f(&mut *self.new_solver_evaluation_cache.lock()),
187+
SolverMode::Coherence => f(&mut *self.new_solver_coherence_evaluation_cache.lock()),
173188
}
174189
}
175190

@@ -1283,8 +1298,8 @@ pub struct GlobalCtxt<'tcx> {
12831298
pub evaluation_cache: traits::EvaluationCache<'tcx>,
12841299

12851300
/// Caches the results of goal evaluation in the new solver.
1286-
pub new_solver_evaluation_cache: solve::EvaluationCache<'tcx>,
1287-
pub new_solver_coherence_evaluation_cache: solve::EvaluationCache<'tcx>,
1301+
pub new_solver_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
1302+
pub new_solver_coherence_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
12881303

12891304
pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>,
12901305

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

+7-7
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ use crate::delegate::SolverDelegate;
1616
use crate::solve::inspect::{self, ProofTreeBuilder};
1717
use crate::solve::search_graph::SearchGraph;
1818
use crate::solve::{
19-
search_graph, CanonicalInput, CanonicalResponse, Certainty, Goal, GoalEvaluationKind,
20-
GoalSource, MaybeCause, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData,
21-
QueryResult, SolverMode, FIXPOINT_STEP_LIMIT,
19+
CanonicalInput, CanonicalResponse, Certainty, Goal, GoalEvaluationKind, GoalSource, MaybeCause,
20+
NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, SolverMode,
21+
FIXPOINT_STEP_LIMIT,
2222
};
2323

2424
pub(super) mod canonical;
@@ -72,7 +72,7 @@ where
7272
/// new placeholders to the caller.
7373
pub(super) max_input_universe: ty::UniverseIndex,
7474

75-
pub(super) search_graph: &'a mut SearchGraph<I>,
75+
pub(super) search_graph: &'a mut SearchGraph<D>,
7676

7777
nested_goals: NestedGoals<I>,
7878

@@ -200,7 +200,7 @@ where
200200
generate_proof_tree: GenerateProofTree,
201201
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
202202
) -> (R, Option<inspect::GoalEvaluation<I>>) {
203-
let mut search_graph = search_graph::SearchGraph::new(delegate.solver_mode());
203+
let mut search_graph = SearchGraph::new(delegate.solver_mode());
204204

205205
let mut ecx = EvalCtxt {
206206
delegate,
@@ -241,7 +241,7 @@ where
241241
/// and registering opaques from the canonicalized input.
242242
fn enter_canonical<R>(
243243
cx: I,
244-
search_graph: &'a mut search_graph::SearchGraph<I>,
244+
search_graph: &'a mut SearchGraph<D>,
245245
canonical_input: CanonicalInput<I>,
246246
canonical_goal_evaluation: &mut ProofTreeBuilder<D>,
247247
f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
@@ -296,7 +296,7 @@ where
296296
#[instrument(level = "debug", skip(cx, search_graph, goal_evaluation), ret)]
297297
fn evaluate_canonical_goal(
298298
cx: I,
299-
search_graph: &'a mut search_graph::SearchGraph<I>,
299+
search_graph: &'a mut SearchGraph<D>,
300300
canonical_input: CanonicalInput<I>,
301301
goal_evaluation: &mut ProofTreeBuilder<D>,
302302
) -> QueryResult<I> {

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

+50-19
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::marker::PhantomData;
88
use std::mem;
99

1010
use rustc_type_ir::inherent::*;
11-
use rustc_type_ir::{self as ty, Interner};
11+
use rustc_type_ir::{self as ty, search_graph, Interner};
1212

1313
use crate::delegate::SolverDelegate;
1414
use crate::solve::eval_ctxt::canonical;
@@ -38,7 +38,7 @@ use crate::solve::{
3838
/// trees. At the end of trait solving `ProofTreeBuilder::finalize`
3939
/// is called to recursively convert the whole structure to a
4040
/// finished proof tree.
41-
pub(in crate::solve) struct ProofTreeBuilder<D, I = <D as SolverDelegate>::Interner>
41+
pub(crate) struct ProofTreeBuilder<D, I = <D as SolverDelegate>::Interner>
4242
where
4343
D: SolverDelegate<Interner = I>,
4444
I: Interner,
@@ -321,23 +321,6 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
321321
})
322322
}
323323

324-
pub fn finalize_canonical_goal_evaluation(
325-
&mut self,
326-
cx: I,
327-
) -> Option<I::CanonicalGoalEvaluationStepRef> {
328-
self.as_mut().map(|this| match this {
329-
DebugSolver::CanonicalGoalEvaluation(evaluation) => {
330-
let final_revision = mem::take(&mut evaluation.final_revision).unwrap();
331-
let final_revision =
332-
cx.intern_canonical_goal_evaluation_step(final_revision.finalize());
333-
let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision };
334-
assert_eq!(evaluation.kind.replace(kind), None);
335-
final_revision
336-
}
337-
_ => unreachable!(),
338-
})
339-
}
340-
341324
pub fn canonical_goal_evaluation(&mut self, canonical_goal_evaluation: ProofTreeBuilder<D>) {
342325
if let Some(this) = self.as_mut() {
343326
match (this, *canonical_goal_evaluation.state.unwrap()) {
@@ -571,3 +554,51 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
571554
}
572555
}
573556
}
557+
558+
impl<D, I> search_graph::ProofTreeBuilder<I> for ProofTreeBuilder<D>
559+
where
560+
D: SolverDelegate<Interner = I>,
561+
I: Interner,
562+
{
563+
fn try_apply_proof_tree(
564+
&mut self,
565+
proof_tree: Option<I::CanonicalGoalEvaluationStepRef>,
566+
) -> bool {
567+
if !self.is_noop() {
568+
if let Some(final_revision) = proof_tree {
569+
let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision };
570+
self.canonical_goal_evaluation_kind(kind);
571+
true
572+
} else {
573+
false
574+
}
575+
} else {
576+
true
577+
}
578+
}
579+
580+
fn on_provisional_cache_hit(&mut self) {
581+
self.canonical_goal_evaluation_kind(WipCanonicalGoalEvaluationKind::ProvisionalCacheHit);
582+
}
583+
584+
fn on_cycle_in_stack(&mut self) {
585+
self.canonical_goal_evaluation_kind(WipCanonicalGoalEvaluationKind::CycleInStack);
586+
}
587+
588+
fn finalize_canonical_goal_evaluation(
589+
&mut self,
590+
tcx: I,
591+
) -> Option<I::CanonicalGoalEvaluationStepRef> {
592+
self.as_mut().map(|this| match this {
593+
DebugSolver::CanonicalGoalEvaluation(evaluation) => {
594+
let final_revision = mem::take(&mut evaluation.final_revision).unwrap();
595+
let final_revision =
596+
tcx.intern_canonical_goal_evaluation_step(final_revision.finalize());
597+
let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision };
598+
assert_eq!(evaluation.kind.replace(kind), None);
599+
final_revision
600+
}
601+
_ => unreachable!(),
602+
})
603+
}
604+
}

0 commit comments

Comments
 (0)