Skip to content

Commit fae7cd5

Browse files
committed
Reuse one base universe for proof tree replay
Store `max_input_universe` in `GoalEvaluation`/`InspectGoal` and pass it to `instantiate_canonical_state` for all replay of a single goal. This keeps every canonical state from that goal using the same universe mapping instead of rebuilding it from `orig_values`. Inline universe creation for query response instantiation.
1 parent 4e3228d commit fae7cd5

4 files changed

Lines changed: 37 additions & 109 deletions

File tree

compiler/rustc_next_trait_solver/src/canonical/mod.rs

Lines changed: 7 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@
1010
//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
1111
1212
use std::iter;
13-
use std::marker::PhantomData;
1413

1514
use canonicalizer::Canonicalizer;
1615
use rustc_index::IndexVec;
1716
use rustc_type_ir::inherent::*;
1817
use rustc_type_ir::relate::solver_relating::RelateExt;
1918
use rustc_type_ir::{
2019
self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner,
21-
TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, TypingMode, TypingModeEqWrapper,
20+
TypeFoldable, TypingMode, TypingModeEqWrapper,
2221
};
2322
use tracing::instrument;
2423

@@ -151,7 +150,11 @@ where
151150
// FIXME: Longterm canonical queries should deal with all placeholders
152151
// created inside of the query directly instead of returning them to the
153152
// caller.
154-
let prev_universe = create_universes_for_response(delegate, response);
153+
let prev_universe = delegate.universe();
154+
let universes_created_in_query = response.max_universe.index();
155+
for _ in 0..universes_created_in_query {
156+
delegate.create_next_universe();
157+
}
155158

156159
compute_query_response_instantiation_values_in_universe(
157160
delegate,
@@ -257,106 +260,6 @@ where
257260
})
258261
}
259262

260-
fn create_universes_for_response<D, I, T>(
261-
delegate: &D,
262-
response: &Canonical<I, T>,
263-
) -> ty::UniverseIndex
264-
where
265-
D: SolverDelegate<Interner = I>,
266-
I: Interner,
267-
{
268-
let prev_universe = delegate.universe();
269-
let universes_created_in_query = response.max_universe.index();
270-
for _ in 0..universes_created_in_query {
271-
delegate.create_next_universe();
272-
}
273-
prev_universe
274-
}
275-
276-
// Recover the caller-side max input universe for replaying a canonical state.
277-
//
278-
// We want the base universe the canonical state was relative to when it was
279-
// first recorded, not the max universe of the current resolved contents of
280-
// `orig_values`. Resolved inference vars may now point at placeholders from
281-
// later replay work, so looking through them would overestimate the base
282-
// universe and shift the replayed placeholders.
283-
fn max_input_universe_for_canonical_state<D, I>(
284-
delegate: &D,
285-
orig_values: &[I::GenericArg],
286-
) -> ty::UniverseIndex
287-
where
288-
D: SolverDelegate<Interner = I>,
289-
I: Interner,
290-
{
291-
struct MaxUniverseVisitor<'a, D, I> {
292-
delegate: &'a D,
293-
max_universe: ty::UniverseIndex,
294-
_interner: PhantomData<I>,
295-
}
296-
297-
impl<D, I> TypeVisitor<I> for MaxUniverseVisitor<'_, D, I>
298-
where
299-
D: SolverDelegate<Interner = I>,
300-
I: Interner,
301-
{
302-
type Result = ();
303-
304-
fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
305-
match t.kind() {
306-
ty::Placeholder(placeholder) => {
307-
self.max_universe = self.max_universe.max(placeholder.universe());
308-
}
309-
ty::Infer(ty::TyVar(vid)) => {
310-
if let Some(universe) = self.delegate.universe_of_ty(vid) {
311-
self.max_universe = self.max_universe.max(universe);
312-
}
313-
}
314-
_ => {}
315-
}
316-
t.super_visit_with(self)
317-
}
318-
319-
fn visit_region(&mut self, r: I::Region) -> Self::Result {
320-
match r.kind() {
321-
ty::RePlaceholder(placeholder) => {
322-
self.max_universe = self.max_universe.max(placeholder.universe());
323-
}
324-
ty::ReVar(vid) => {
325-
if let Some(universe) = self.delegate.universe_of_lt(vid) {
326-
self.max_universe = self.max_universe.max(universe);
327-
}
328-
}
329-
_ => {}
330-
}
331-
}
332-
333-
fn visit_const(&mut self, c: I::Const) -> Self::Result {
334-
match c.kind() {
335-
ty::ConstKind::Placeholder(placeholder) => {
336-
self.max_universe = self.max_universe.max(placeholder.universe());
337-
}
338-
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
339-
if let Some(universe) = self.delegate.universe_of_ct(vid) {
340-
self.max_universe = self.max_universe.max(universe);
341-
}
342-
}
343-
_ => {}
344-
}
345-
c.super_visit_with(self)
346-
}
347-
}
348-
349-
let mut visitor = MaxUniverseVisitor {
350-
delegate,
351-
max_universe: ty::UniverseIndex::ROOT,
352-
_interner: PhantomData,
353-
};
354-
for value in orig_values {
355-
value.visit_with(&mut visitor);
356-
}
357-
visitor.max_universe
358-
}
359-
360263
/// Unify the `original_values` with the `var_values` returned by the canonical query..
361264
///
362265
/// This assumes that this unification will always succeed. This is the case when
@@ -461,6 +364,7 @@ pub fn instantiate_canonical_state<D, I, T>(
461364
delegate: &D,
462365
span: I::Span,
463366
param_env: I::ParamEnv,
367+
prev_universe: ty::UniverseIndex,
464368
orig_values: &mut Vec<I::GenericArg>,
465369
state: inspect::CanonicalState<I, T>,
466370
) -> T
@@ -471,7 +375,6 @@ where
471375
{
472376
// In case any fresh inference variables have been created between `state`
473377
// and the previous instantiation, extend `orig_values` for it.
474-
let prev_universe = max_input_universe_for_canonical_state(delegate, orig_values);
475378
let max_universe = prev_universe + state.max_universe.index();
476379
while delegate.universe() < max_universe {
477380
delegate.create_next_universe();

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1789,13 +1789,15 @@ pub(super) fn evaluate_root_goal_for_proof_tree<D: SolverDelegate<Interner = I>,
17891789

17901790
let (orig_values, canonical_goal) =
17911791
canonicalize_goal(delegate, goal, &opaque_types, typing_mode.into());
1792+
let max_input_universe = canonical_goal.canonical.max_universe;
17921793

17931794
let (canonical_result, final_revision) =
17941795
delegate.cx().evaluate_root_goal_for_proof_tree_raw(canonical_goal);
17951796

17961797
let proof_tree = inspect::GoalEvaluation {
17971798
uncanonicalized_goal: goal,
17981799
orig_values,
1800+
max_input_universe,
17991801
final_revision,
18001802
result: canonical_result,
18011803
};

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

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub struct InspectGoal<'a, 'tcx> {
3232
infcx: &'a SolverDelegate<'tcx>,
3333
depth: usize,
3434
orig_values: Vec<ty::GenericArg<'tcx>>,
35+
max_input_universe: ty::UniverseIndex,
3536
goal: Goal<'tcx, ty::Predicate<'tcx>>,
3637
result: Result<Certainty, NoSolution>,
3738
final_revision: &'tcx inspect::Probe<TyCtxt<'tcx>>,
@@ -102,16 +103,29 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
102103
match **step {
103104
inspect::ProbeStep::AddGoal(source, goal) => instantiated_goals.push((
104105
source,
105-
instantiate_canonical_state(infcx, span, param_env, &mut orig_values, goal),
106+
instantiate_canonical_state(
107+
infcx,
108+
span,
109+
param_env,
110+
self.goal.max_input_universe,
111+
&mut orig_values,
112+
goal,
113+
),
106114
)),
107115
inspect::ProbeStep::RecordImplArgs { .. } => {}
108116
inspect::ProbeStep::MakeCanonicalResponse { .. }
109117
| inspect::ProbeStep::NestedProbe(_) => unreachable!(),
110118
}
111119
}
112120

113-
let () =
114-
instantiate_canonical_state(infcx, span, param_env, &mut orig_values, self.final_state);
121+
let () = instantiate_canonical_state(
122+
infcx,
123+
span,
124+
param_env,
125+
self.goal.max_input_universe,
126+
&mut orig_values,
127+
self.final_state,
128+
);
115129

116130
instantiated_goals
117131
.into_iter()
@@ -139,6 +153,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
139153
infcx,
140154
span,
141155
param_env,
156+
self.goal.max_input_universe,
142157
&mut orig_values,
143158
impl_args,
144159
);
@@ -147,6 +162,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
147162
infcx,
148163
span,
149164
param_env,
165+
self.goal.max_input_universe,
150166
&mut orig_values,
151167
self.final_state,
152168
);
@@ -321,8 +337,13 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
321337
) -> Self {
322338
let infcx = <&SolverDelegate<'tcx>>::from(infcx);
323339

324-
let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, final_revision, result } =
325-
root;
340+
let inspect::GoalEvaluation {
341+
uncanonicalized_goal,
342+
orig_values,
343+
max_input_universe,
344+
final_revision,
345+
result,
346+
} = root;
326347
// If there's a normalizes-to goal, AND the evaluation result with the result of
327348
// constraining the normalizes-to RHS and computing the nested goals.
328349
let result = result.map(|ok| ok.value.certainty);
@@ -331,6 +352,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
331352
infcx,
332353
depth,
333354
orig_values,
355+
max_input_universe,
334356
goal: eager_resolve_vars(&**infcx, uncanonicalized_goal),
335357
result,
336358
final_revision,

compiler/rustc_type_ir/src/solve/inspect.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ pub type CanonicalState<I, T> = Canonical<I, State<I, T>>;
4949
pub struct GoalEvaluation<I: Interner> {
5050
pub uncanonicalized_goal: Goal<I, I::Predicate>,
5151
pub orig_values: Vec<I::GenericArg>,
52+
pub max_input_universe: crate::UniverseIndex,
5253
pub final_revision: I::Probe,
5354
pub result: QueryResult<I>,
5455
}

0 commit comments

Comments
 (0)