Skip to content

Commit 21ba021

Browse files
Review
1 parent ca34794 commit 21ba021

File tree

6 files changed

+120
-117
lines changed

6 files changed

+120
-117
lines changed

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

Lines changed: 73 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ use crate::delegate::SolverDelegate;
2222
use crate::solve::inspect::{self, ProofTreeBuilder};
2323
use crate::solve::search_graph::SearchGraph;
2424
use crate::solve::{
25-
CanonicalGoalCacheKey, CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal,
26-
GoalEvaluationKind, GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput,
25+
CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluation, GoalEvaluationKind,
26+
GoalSource, GoalStalledOn, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput,
2727
QueryResult,
2828
};
2929

@@ -116,7 +116,7 @@ where
116116

117117
pub(super) search_graph: &'a mut SearchGraph<D>,
118118

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

121121
pub(super) origin_span: I::Span,
122122

@@ -148,9 +148,9 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
148148
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
149149
generate_proof_tree: GenerateProofTree,
150150
span: <Self::Interner as Interner>::Span,
151-
cache_key: Option<CanonicalGoalCacheKey<Self::Interner>>,
151+
stalled_on: Option<GoalStalledOn<Self::Interner>>,
152152
) -> (
153-
Result<(HasChanged, Certainty, CanonicalGoalCacheKey<Self::Interner>), NoSolution>,
153+
Result<GoalEvaluation<Self::Interner>, NoSolution>,
154154
Option<inspect::GoalEvaluation<Self::Interner>>,
155155
);
156156

@@ -173,15 +173,10 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
173173
&self,
174174
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
175175
generate_proof_tree: GenerateProofTree,
176-
cache_key: Option<CanonicalGoalCacheKey<Self::Interner>>,
176+
stalled_on: Option<GoalStalledOn<Self::Interner>>,
177177
) -> (
178178
Result<
179-
(
180-
NestedNormalizationGoals<Self::Interner>,
181-
HasChanged,
182-
Certainty,
183-
CanonicalGoalCacheKey<Self::Interner>,
184-
),
179+
(NestedNormalizationGoals<Self::Interner>, GoalEvaluation<Self::Interner>),
185180
NoSolution,
186181
>,
187182
Option<inspect::GoalEvaluation<Self::Interner>>,
@@ -199,13 +194,10 @@ where
199194
goal: Goal<I, I::Predicate>,
200195
generate_proof_tree: GenerateProofTree,
201196
span: I::Span,
202-
cache_key: Option<CanonicalGoalCacheKey<I>>,
203-
) -> (
204-
Result<(HasChanged, Certainty, CanonicalGoalCacheKey<I>), NoSolution>,
205-
Option<inspect::GoalEvaluation<I>>,
206-
) {
197+
stalled_on: Option<GoalStalledOn<I>>,
198+
) -> (Result<GoalEvaluation<I>, NoSolution>, Option<inspect::GoalEvaluation<I>>) {
207199
EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, span, |ecx| {
208-
ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, cache_key)
200+
ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on)
209201
})
210202
}
211203

@@ -228,12 +220,9 @@ where
228220
&self,
229221
goal: Goal<I, I::Predicate>,
230222
generate_proof_tree: GenerateProofTree,
231-
cache_key: Option<CanonicalGoalCacheKey<I>>,
223+
stalled_on: Option<GoalStalledOn<I>>,
232224
) -> (
233-
Result<
234-
(NestedNormalizationGoals<I>, HasChanged, Certainty, CanonicalGoalCacheKey<I>),
235-
NoSolution,
236-
>,
225+
Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolution>,
237226
Option<inspect::GoalEvaluation<I>>,
238227
) {
239228
EvalCtxt::enter_root(
@@ -242,7 +231,7 @@ where
242231
generate_proof_tree,
243232
I::Span::dummy(),
244233
|ecx| {
245-
ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal, cache_key)
234+
ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on)
246235
},
247236
)
248237
}
@@ -468,12 +457,12 @@ where
468457
goal_evaluation_kind: GoalEvaluationKind,
469458
source: GoalSource,
470459
goal: Goal<I, I::Predicate>,
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)?;
460+
stalled_on: Option<GoalStalledOn<I>>,
461+
) -> Result<GoalEvaluation<I>, NoSolution> {
462+
let (normalization_nested_goals, goal_evaluation) =
463+
self.evaluate_goal_raw(goal_evaluation_kind, source, goal, stalled_on)?;
475464
assert!(normalization_nested_goals.is_empty());
476-
Ok((has_changed, certainty, cache_key))
465+
Ok(goal_evaluation)
477466
}
478467

479468
/// Recursively evaluates `goal`, returning the nested goals in case
@@ -488,23 +477,25 @@ where
488477
goal_evaluation_kind: GoalEvaluationKind,
489478
source: GoalSource,
490479
goal: Goal<I, I::Predicate>,
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.stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value))
480+
stalled_on: Option<GoalStalledOn<I>>,
481+
) -> Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolution> {
482+
// If we have run this goal before, and it was stalled, check that any of the goal's
483+
// args have changed. Otherwise, we don't need to re-run the goal because it'll remain
484+
// stalled, since it'll canonicalize the same way and evaluation is pure.
485+
if let Some(stalled_on) = stalled_on {
486+
if !stalled_on.stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value))
498487
&& !self
499488
.delegate
500489
.opaque_types_storage_num_entries()
501-
.needs_reevaluation(cache_key.num_opaques)
490+
.needs_reevaluation(stalled_on.num_opaques)
502491
{
503492
return Ok((
504493
NestedNormalizationGoals::empty(),
505-
HasChanged::No,
506-
cache_key.certainty,
507-
cache_key,
494+
GoalEvaluation {
495+
certainty: Certainty::Maybe(stalled_on.stalled_cause),
496+
has_changed: HasChanged::No,
497+
stalled_on: Some(stalled_on),
498+
},
508499
));
509500
}
510501
}
@@ -544,33 +535,35 @@ where
544535
// Once we have decided on how to handle trait-system-refactor-initiative#75,
545536
// we should re-add an assert here.
546537

547-
// Remove the unconstrained RHS arg, which is expected to have changed.
548-
let mut stalled_vars = orig_values;
549-
if let Some(normalizes_to) = goal.predicate.as_normalizes_to() {
550-
let normalizes_to = normalizes_to.skip_binder();
551-
let rhs_arg: I::GenericArg = normalizes_to.term.into();
552-
let idx = stalled_vars
553-
.iter()
554-
.rposition(|arg| *arg == rhs_arg)
555-
.expect("expected unconstrained arg");
556-
stalled_vars.swap_remove(idx);
557-
}
538+
let stalled_on = match certainty {
539+
Certainty::Yes => None,
540+
Certainty::Maybe(stalled_cause) => {
541+
// Remove the unconstrained RHS arg, which is expected to have changed.
542+
let mut stalled_vars = orig_values;
543+
if let Some(normalizes_to) = goal.predicate.as_normalizes_to() {
544+
let normalizes_to = normalizes_to.skip_binder();
545+
let rhs_arg: I::GenericArg = normalizes_to.term.into();
546+
let idx = stalled_vars
547+
.iter()
548+
.rposition(|arg| *arg == rhs_arg)
549+
.expect("expected unconstrained arg");
550+
stalled_vars.swap_remove(idx);
551+
}
558552

559-
Ok((
560-
normalization_nested_goals,
561-
has_changed,
562-
certainty,
563-
CanonicalGoalCacheKey {
564-
num_opaques: canonical_goal
565-
.canonical
566-
.value
567-
.predefined_opaques_in_body
568-
.opaque_types
569-
.len(),
570-
stalled_vars,
571-
certainty,
572-
},
573-
))
553+
Some(GoalStalledOn {
554+
num_opaques: canonical_goal
555+
.canonical
556+
.value
557+
.predefined_opaques_in_body
558+
.opaque_types
559+
.len(),
560+
stalled_vars,
561+
stalled_cause,
562+
})
563+
}
564+
};
565+
566+
Ok((normalization_nested_goals, GoalEvaluation { certainty, has_changed, stalled_on }))
574567
}
575568

576569
fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
@@ -670,7 +663,7 @@ where
670663
let cx = self.cx();
671664
// If this loop did not result in any progress, what's our final certainty.
672665
let mut unchanged_certainty = Some(Certainty::Yes);
673-
for (source, goal, cache_key) in mem::take(&mut self.nested_goals) {
666+
for (source, goal, stalled_on) in mem::take(&mut self.nested_goals) {
674667
if let Some(has_changed) = self.delegate.compute_goal_fast_path(goal, self.origin_span)
675668
{
676669
if matches!(has_changed, HasChanged::Yes) {
@@ -698,13 +691,15 @@ where
698691
let unconstrained_goal =
699692
goal.with(cx, ty::NormalizesTo { alias: pred.alias, term: unconstrained_rhs });
700693

701-
let (NestedNormalizationGoals(nested_goals), _, certainty, cache_key) = self
702-
.evaluate_goal_raw(
703-
GoalEvaluationKind::Nested,
704-
source,
705-
unconstrained_goal,
706-
cache_key,
707-
)?;
694+
let (
695+
NestedNormalizationGoals(nested_goals),
696+
GoalEvaluation { certainty, stalled_on, has_changed: _ },
697+
) = self.evaluate_goal_raw(
698+
GoalEvaluationKind::Nested,
699+
source,
700+
unconstrained_goal,
701+
stalled_on,
702+
)?;
708703
// Add the nested goals from normalization to our own nested goals.
709704
trace!(?nested_goals);
710705
self.nested_goals.extend(nested_goals.into_iter().map(|(s, g)| (s, g, None)));
@@ -743,21 +738,21 @@ where
743738
match certainty {
744739
Certainty::Yes => {}
745740
Certainty::Maybe(_) => {
746-
self.nested_goals.push((source, with_resolved_vars, Some(cache_key)));
741+
self.nested_goals.push((source, with_resolved_vars, stalled_on));
747742
unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
748743
}
749744
}
750745
} else {
751-
let (has_changed, certainty, cache_key) =
752-
self.evaluate_goal(GoalEvaluationKind::Nested, source, goal, cache_key)?;
746+
let GoalEvaluation { certainty, has_changed, stalled_on } =
747+
self.evaluate_goal(GoalEvaluationKind::Nested, source, goal, stalled_on)?;
753748
if has_changed == HasChanged::Yes {
754749
unchanged_certainty = None;
755750
}
756751

757752
match certainty {
758753
Certainty::Yes => {}
759754
Certainty::Maybe(_) => {
760-
self.nested_goals.push((source, goal, Some(cache_key)));
755+
self.nested_goals.push((source, goal, stalled_on));
761756
unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
762757
}
763758
}

compiler/rustc_next_trait_solver/src/solve/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mod project_goals;
2121
mod search_graph;
2222
mod trait_goals;
2323

24+
use derive_where::derive_where;
2425
use rustc_type_ir::inherent::*;
2526
pub use rustc_type_ir::solve::*;
2627
use rustc_type_ir::{self as ty, Interner, TypingMode};
@@ -369,3 +370,18 @@ fn response_no_constraints_raw<I: Interner>(
369370
},
370371
}
371372
}
373+
374+
pub struct GoalEvaluation<I: Interner> {
375+
pub certainty: Certainty,
376+
pub has_changed: HasChanged,
377+
/// Returns the args that must change for the goal to warrant re-evaluation.
378+
pub stalled_on: Option<GoalStalledOn<I>>,
379+
}
380+
381+
#[derive_where(Clone, Debug; I: Interner)]
382+
pub struct GoalStalledOn<I: Interner> {
383+
pub num_opaques: usize,
384+
pub stalled_vars: Vec<I::GenericArg>,
385+
/// The cause that will be returned on subsequent evaluations if this goal remains stalled.
386+
pub stalled_cause: MaybeCause,
387+
}

0 commit comments

Comments
 (0)