Skip to content

Commit 2d718c1

Browse files
Don't rerun goals if none of their vars have changed
1 parent 5af801b commit 2d718c1

File tree

10 files changed

+232
-73
lines changed

10 files changed

+232
-73
lines changed

compiler/rustc_infer/src/infer/context.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,45 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
8989
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
9090
}
9191

92+
#[allow(rustc::usage_of_type_ir_traits)]
93+
fn is_changed_arg(&self, arg: ty::GenericArg<'tcx>) -> bool {
94+
match arg.unpack() {
95+
ty::GenericArgKind::Lifetime(lt) => {
96+
if let ty::ReVar(vid) = lt.kind() {
97+
self.opportunistic_resolve_lt_var(vid) != lt
98+
} else {
99+
true
100+
}
101+
}
102+
ty::GenericArgKind::Type(ty) => {
103+
if let ty::Infer(infer_ty) = *ty.kind() {
104+
match infer_ty {
105+
ty::InferTy::TyVar(vid) => self.opportunistic_resolve_ty_var(vid) != ty,
106+
ty::InferTy::IntVar(vid) => self.opportunistic_resolve_int_var(vid) != ty,
107+
ty::InferTy::FloatVar(vid) => {
108+
self.opportunistic_resolve_float_var(vid) != ty
109+
}
110+
ty::InferTy::FreshTy(_)
111+
| ty::InferTy::FreshIntTy(_)
112+
| ty::InferTy::FreshFloatTy(_) => true,
113+
}
114+
} else {
115+
true
116+
}
117+
}
118+
ty::GenericArgKind::Const(ct) => {
119+
if let ty::ConstKind::Infer(infer_ct) = ct.kind() {
120+
match infer_ct {
121+
ty::InferConst::Var(vid) => self.opportunistic_resolve_ct_var(vid) != ct,
122+
ty::InferConst::Fresh(_) => true,
123+
}
124+
} else {
125+
true
126+
}
127+
}
128+
}
129+
}
130+
92131
fn next_region_infer(&self) -> ty::Region<'tcx> {
93132
self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
94133
}
@@ -221,6 +260,9 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
221260
fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries {
222261
self.inner.borrow_mut().opaque_types().num_entries()
223262
}
263+
fn opaque_types_storage_num_unique_entries_raw(&self) -> usize {
264+
self.inner.borrow_mut().opaque_types().num_entries().opaque_types
265+
}
224266
fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
225267
self.inner.borrow_mut().opaque_types().iter_lookup_table().map(|(k, h)| (k, h.ty)).collect()
226268
}

compiler/rustc_infer/src/infer/opaque_types/table.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub struct OpaqueTypeStorage<'tcx> {
2020
/// the opaque types currently in the storage.
2121
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
2222
pub struct OpaqueTypeStorageEntries {
23-
opaque_types: usize,
23+
pub opaque_types: usize,
2424
duplicate_entries: usize,
2525
}
2626

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ where
5353
{
5454
/// Canonicalizes the goal remembering the original values
5555
/// for each bound variable.
56-
pub(super) fn canonicalize_goal<T: TypeFoldable<I>>(
56+
pub(super) fn canonicalize_goal(
5757
&self,
58-
goal: Goal<I, T>,
59-
) -> (Vec<I::GenericArg>, CanonicalInput<I, T>) {
58+
goal: Goal<I, I::Predicate>,
59+
) -> (Vec<I::GenericArg>, CanonicalInput<I, I::Predicate>) {
6060
// We only care about one entry per `OpaqueTypeKey` here,
6161
// so we only canonicalize the lookup table and ignore
6262
// duplicate entries.
@@ -130,7 +130,7 @@ where
130130
if goals.is_empty() {
131131
assert!(matches!(goals_certainty, Certainty::Yes));
132132
}
133-
(Certainty::Yes, NestedNormalizationGoals(goals))
133+
(Certainty::Yes, NestedNormalizationGoals::from(goals))
134134
}
135135
_ => {
136136
let certainty = shallow_certainty.and(goals_certainty);
@@ -272,7 +272,7 @@ where
272272
pub(super) fn instantiate_and_apply_query_response(
273273
&mut self,
274274
param_env: I::ParamEnv,
275-
original_values: Vec<I::GenericArg>,
275+
original_values: &[I::GenericArg],
276276
response: CanonicalResponse<I>,
277277
) -> (NestedNormalizationGoals<I>, Certainty) {
278278
let instantiation = Self::compute_query_response_instantiation_values(

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

Lines changed: 92 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ use crate::delegate::SolverDelegate;
2222
use crate::solve::inspect::{self, ProofTreeBuilder};
2323
use crate::solve::search_graph::SearchGraph;
2424
use crate::solve::{
25-
CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource,
26-
HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, QueryResult,
25+
CanonicalGoalCacheKey, CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal,
26+
GoalEvaluationKind, GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput,
27+
QueryResult,
2728
};
2829

2930
pub(super) mod canonical;
@@ -115,7 +116,7 @@ where
115116

116117
pub(super) search_graph: &'a mut SearchGraph<D>,
117118

118-
nested_goals: Vec<(GoalSource, Goal<I, I::Predicate>)>,
119+
nested_goals: Vec<(GoalSource, Goal<I, I::Predicate>, Option<CanonicalGoalCacheKey<I>>)>,
119120

120121
pub(super) origin_span: I::Span,
121122

@@ -147,8 +148,9 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
147148
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
148149
generate_proof_tree: GenerateProofTree,
149150
span: <Self::Interner as Interner>::Span,
151+
cache_key: Option<CanonicalGoalCacheKey<Self::Interner>>,
150152
) -> (
151-
Result<(HasChanged, Certainty), NoSolution>,
153+
Result<(HasChanged, Certainty, CanonicalGoalCacheKey<Self::Interner>), NoSolution>,
152154
Option<inspect::GoalEvaluation<Self::Interner>>,
153155
);
154156

@@ -171,8 +173,17 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
171173
&self,
172174
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
173175
generate_proof_tree: GenerateProofTree,
176+
cache_key: Option<CanonicalGoalCacheKey<Self::Interner>>,
174177
) -> (
175-
Result<(NestedNormalizationGoals<Self::Interner>, HasChanged, Certainty), NoSolution>,
178+
Result<
179+
(
180+
NestedNormalizationGoals<Self::Interner>,
181+
HasChanged,
182+
Certainty,
183+
CanonicalGoalCacheKey<Self::Interner>,
184+
),
185+
NoSolution,
186+
>,
176187
Option<inspect::GoalEvaluation<Self::Interner>>,
177188
);
178189
}
@@ -188,9 +199,13 @@ where
188199
goal: Goal<I, I::Predicate>,
189200
generate_proof_tree: GenerateProofTree,
190201
span: I::Span,
191-
) -> (Result<(HasChanged, Certainty), NoSolution>, Option<inspect::GoalEvaluation<I>>) {
202+
cache_key: Option<CanonicalGoalCacheKey<I>>,
203+
) -> (
204+
Result<(HasChanged, Certainty, CanonicalGoalCacheKey<I>), NoSolution>,
205+
Option<inspect::GoalEvaluation<I>>,
206+
) {
192207
EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, span, |ecx| {
193-
ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
208+
ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, cache_key)
194209
})
195210
}
196211

@@ -201,7 +216,7 @@ where
201216
) -> bool {
202217
self.probe(|| {
203218
EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, I::Span::dummy(), |ecx| {
204-
ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
219+
ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, None)
205220
})
206221
.0
207222
})
@@ -213,16 +228,22 @@ where
213228
&self,
214229
goal: Goal<I, I::Predicate>,
215230
generate_proof_tree: GenerateProofTree,
231+
cache_key: Option<CanonicalGoalCacheKey<I>>,
216232
) -> (
217-
Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution>,
233+
Result<
234+
(NestedNormalizationGoals<I>, HasChanged, Certainty, CanonicalGoalCacheKey<I>),
235+
NoSolution,
236+
>,
218237
Option<inspect::GoalEvaluation<I>>,
219238
) {
220239
EvalCtxt::enter_root(
221240
self,
222241
self.cx().recursion_limit(),
223242
generate_proof_tree,
224243
I::Span::dummy(),
225-
|ecx| ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal),
244+
|ecx| {
245+
ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal, cache_key)
246+
},
226247
)
227248
}
228249
}
@@ -447,11 +468,12 @@ where
447468
goal_evaluation_kind: GoalEvaluationKind,
448469
source: GoalSource,
449470
goal: Goal<I, I::Predicate>,
450-
) -> Result<(HasChanged, Certainty), NoSolution> {
451-
let (normalization_nested_goals, has_changed, certainty) =
452-
self.evaluate_goal_raw(goal_evaluation_kind, source, goal)?;
471+
cache_key: Option<CanonicalGoalCacheKey<I>>,
472+
) -> Result<(HasChanged, Certainty, CanonicalGoalCacheKey<I>), NoSolution> {
473+
let (normalization_nested_goals, has_changed, certainty, cache_key) =
474+
self.evaluate_goal_raw(goal_evaluation_kind, source, goal, cache_key)?;
453475
assert!(normalization_nested_goals.is_empty());
454-
Ok((has_changed, certainty))
476+
Ok((has_changed, certainty, cache_key))
455477
}
456478

457479
/// Recursively evaluates `goal`, returning the nested goals in case
@@ -466,7 +488,26 @@ where
466488
goal_evaluation_kind: GoalEvaluationKind,
467489
source: GoalSource,
468490
goal: Goal<I, I::Predicate>,
469-
) -> Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution> {
491+
cache_key: Option<CanonicalGoalCacheKey<I>>,
492+
) -> Result<
493+
(NestedNormalizationGoals<I>, HasChanged, Certainty, CanonicalGoalCacheKey<I>),
494+
NoSolution,
495+
> {
496+
if let Some(cache_key) = cache_key {
497+
if !cache_key.orig_values.iter().any(|value| {
498+
cache_key.unconstrained_rhs == Some(value) || self.delegate.is_changed_arg(value)
499+
}) && self.delegate.opaque_types_storage_num_unique_entries_raw()
500+
== cache_key.num_opaques
501+
{
502+
return Ok((
503+
NestedNormalizationGoals::empty(),
504+
HasChanged::No,
505+
cache_key.certainty,
506+
cache_key,
507+
));
508+
}
509+
}
510+
470511
let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
471512
let mut goal_evaluation =
472513
self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
@@ -489,7 +530,7 @@ where
489530
if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No };
490531

491532
let (normalization_nested_goals, certainty) =
492-
self.instantiate_and_apply_query_response(goal.param_env, orig_values, response);
533+
self.instantiate_and_apply_query_response(goal.param_env, &orig_values, response);
493534
self.inspect.goal_evaluation(goal_evaluation);
494535

495536
// FIXME: We previously had an assert here that checked that recomputing
@@ -502,7 +543,22 @@ where
502543
// Once we have decided on how to handle trait-system-refactor-initiative#75,
503544
// we should re-add an assert here.
504545

505-
Ok((normalization_nested_goals, has_changed, certainty))
546+
Ok((
547+
normalization_nested_goals,
548+
has_changed,
549+
certainty,
550+
CanonicalGoalCacheKey {
551+
num_opaques: canonical_goal
552+
.canonical
553+
.value
554+
.predefined_opaques_in_body
555+
.opaque_types
556+
.len(),
557+
unconstrained_rhs: None,
558+
orig_values: self.cx().mk_args(&orig_values),
559+
certainty,
560+
},
561+
))
506562
}
507563

508564
fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
@@ -602,7 +658,7 @@ where
602658
let cx = self.cx();
603659
// If this loop did not result in any progress, what's our final certainty.
604660
let mut unchanged_certainty = Some(Certainty::Yes);
605-
for (source, goal) in mem::take(&mut self.nested_goals) {
661+
for (source, goal, cache_key) in mem::take(&mut self.nested_goals) {
606662
if let Some(has_changed) = self.delegate.compute_goal_fast_path(goal, self.origin_span)
607663
{
608664
if matches!(has_changed, HasChanged::Yes) {
@@ -630,11 +686,16 @@ where
630686
let unconstrained_goal =
631687
goal.with(cx, ty::NormalizesTo { alias: pred.alias, term: unconstrained_rhs });
632688

633-
let (NestedNormalizationGoals(nested_goals), _, certainty) =
634-
self.evaluate_goal_raw(GoalEvaluationKind::Nested, source, unconstrained_goal)?;
689+
let (NestedNormalizationGoals(nested_goals), _, certainty, cache_key) = self
690+
.evaluate_goal_raw(
691+
GoalEvaluationKind::Nested,
692+
source,
693+
unconstrained_goal,
694+
cache_key,
695+
)?;
635696
// Add the nested goals from normalization to our own nested goals.
636697
trace!(?nested_goals);
637-
self.nested_goals.extend(nested_goals);
698+
self.nested_goals.extend(nested_goals.into_iter().map(|(s, g)| (s, g, None)));
638699

639700
// Finally, equate the goal's RHS with the unconstrained var.
640701
//
@@ -660,6 +721,8 @@ where
660721
// looking at the "has changed" return from evaluate_goal,
661722
// because we expect the `unconstrained_rhs` part of the predicate
662723
// to have changed -- that means we actually normalized successfully!
724+
// FIXME: Do we need to eagerly resolve here? Or should we check
725+
// if the cache key has any changed vars?
663726
let with_resolved_vars = self.resolve_vars_if_possible(goal);
664727
if pred.alias != goal.predicate.as_normalizes_to().unwrap().skip_binder().alias {
665728
unchanged_certainty = None;
@@ -668,21 +731,24 @@ where
668731
match certainty {
669732
Certainty::Yes => {}
670733
Certainty::Maybe(_) => {
671-
self.nested_goals.push((source, with_resolved_vars));
734+
let mut cache_key = cache_key;
735+
// FIXME: lmao
736+
cache_key.unconstrained_rhs = Some(unconstrained_rhs.into());
737+
self.nested_goals.push((source, with_resolved_vars, Some(cache_key)));
672738
unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
673739
}
674740
}
675741
} else {
676-
let (has_changed, certainty) =
677-
self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?;
742+
let (has_changed, certainty, cache_key) =
743+
self.evaluate_goal(GoalEvaluationKind::Nested, source, goal, cache_key)?;
678744
if has_changed == HasChanged::Yes {
679745
unchanged_certainty = None;
680746
}
681747

682748
match certainty {
683749
Certainty::Yes => {}
684750
Certainty::Maybe(_) => {
685-
self.nested_goals.push((source, goal));
751+
self.nested_goals.push((source, goal, Some(cache_key)));
686752
unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
687753
}
688754
}
@@ -706,7 +772,7 @@ where
706772
goal.predicate =
707773
goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env));
708774
self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal);
709-
self.nested_goals.push((source, goal));
775+
self.nested_goals.push((source, goal, None));
710776
}
711777

712778
#[instrument(level = "trace", skip(self, goals))]

0 commit comments

Comments
 (0)