resuse eagerly resolved goal from previous iteration
This commit is contained in:
@@ -53,17 +53,14 @@ where
|
|||||||
{
|
{
|
||||||
/// Canonicalizes the goal remembering the original values
|
/// Canonicalizes the goal remembering the original values
|
||||||
/// for each bound variable.
|
/// for each bound variable.
|
||||||
|
///
|
||||||
|
/// This expects `goal` and `opaque_types` to be eager resolved.
|
||||||
pub(super) fn canonicalize_goal(
|
pub(super) fn canonicalize_goal(
|
||||||
&self,
|
&self,
|
||||||
is_hir_typeck_root_goal: bool,
|
is_hir_typeck_root_goal: bool,
|
||||||
goal: Goal<I, I::Predicate>,
|
goal: Goal<I, I::Predicate>,
|
||||||
|
opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>,
|
||||||
) -> (Vec<I::GenericArg>, CanonicalInput<I, I::Predicate>) {
|
) -> (Vec<I::GenericArg>, CanonicalInput<I, I::Predicate>) {
|
||||||
// We only care about one entry per `OpaqueTypeKey` here,
|
|
||||||
// so we only canonicalize the lookup table and ignore
|
|
||||||
// duplicate entries.
|
|
||||||
let opaque_types = self.delegate.clone_opaque_types_lookup_table();
|
|
||||||
let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types));
|
|
||||||
|
|
||||||
let mut orig_values = Default::default();
|
let mut orig_values = Default::default();
|
||||||
let canonical = Canonicalizer::canonicalize_input(
|
let canonical = Canonicalizer::canonicalize_input(
|
||||||
self.delegate,
|
self.delegate,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ use super::has_only_region_constraints;
|
|||||||
use crate::coherence;
|
use crate::coherence;
|
||||||
use crate::delegate::SolverDelegate;
|
use crate::delegate::SolverDelegate;
|
||||||
use crate::placeholder::BoundVarReplacer;
|
use crate::placeholder::BoundVarReplacer;
|
||||||
|
use crate::resolve::eager_resolve_vars;
|
||||||
use crate::solve::inspect::{self, ProofTreeBuilder};
|
use crate::solve::inspect::{self, ProofTreeBuilder};
|
||||||
use crate::solve::search_graph::SearchGraph;
|
use crate::solve::search_graph::SearchGraph;
|
||||||
use crate::solve::ty::may_use_unstable_feature;
|
use crate::solve::ty::may_use_unstable_feature;
|
||||||
@@ -440,6 +441,7 @@ where
|
|||||||
return Ok((
|
return Ok((
|
||||||
NestedNormalizationGoals::empty(),
|
NestedNormalizationGoals::empty(),
|
||||||
GoalEvaluation {
|
GoalEvaluation {
|
||||||
|
goal,
|
||||||
certainty: Certainty::Maybe(stalled_on.stalled_cause),
|
certainty: Certainty::Maybe(stalled_on.stalled_cause),
|
||||||
has_changed: HasChanged::No,
|
has_changed: HasChanged::No,
|
||||||
stalled_on: Some(stalled_on),
|
stalled_on: Some(stalled_on),
|
||||||
@@ -447,10 +449,16 @@ where
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We only care about one entry per `OpaqueTypeKey` here,
|
||||||
|
// so we only canonicalize the lookup table and ignore
|
||||||
|
// duplicate entries.
|
||||||
|
let opaque_types = self.delegate.clone_opaque_types_lookup_table();
|
||||||
|
let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types));
|
||||||
|
|
||||||
let is_hir_typeck_root_goal = matches!(goal_evaluation_kind, GoalEvaluationKind::Root)
|
let is_hir_typeck_root_goal = matches!(goal_evaluation_kind, GoalEvaluationKind::Root)
|
||||||
&& self.delegate.in_hir_typeck();
|
&& self.delegate.in_hir_typeck();
|
||||||
|
let (orig_values, canonical_goal) =
|
||||||
let (orig_values, canonical_goal) = self.canonicalize_goal(is_hir_typeck_root_goal, goal);
|
self.canonicalize_goal(is_hir_typeck_root_goal, goal, opaque_types);
|
||||||
let mut goal_evaluation =
|
let mut goal_evaluation =
|
||||||
self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
|
self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
|
||||||
let canonical_result = self.search_graph.evaluate_goal(
|
let canonical_result = self.search_graph.evaluate_goal(
|
||||||
@@ -528,7 +536,10 @@ where
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((normalization_nested_goals, GoalEvaluation { certainty, has_changed, stalled_on }))
|
Ok((
|
||||||
|
normalization_nested_goals,
|
||||||
|
GoalEvaluation { goal, certainty, has_changed, stalled_on },
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
|
pub(super) fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
|
||||||
@@ -664,7 +675,7 @@ where
|
|||||||
|
|
||||||
let (
|
let (
|
||||||
NestedNormalizationGoals(nested_goals),
|
NestedNormalizationGoals(nested_goals),
|
||||||
GoalEvaluation { certainty, stalled_on, has_changed: _ },
|
GoalEvaluation { goal, certainty, stalled_on, has_changed: _ },
|
||||||
) = self.evaluate_goal_raw(
|
) = self.evaluate_goal_raw(
|
||||||
GoalEvaluationKind::Nested,
|
GoalEvaluationKind::Nested,
|
||||||
source,
|
source,
|
||||||
@@ -702,7 +713,15 @@ where
|
|||||||
// FIXME: Do we need to eagerly resolve here? Or should we check
|
// FIXME: Do we need to eagerly resolve here? Or should we check
|
||||||
// if the cache key has any changed vars?
|
// if the cache key has any changed vars?
|
||||||
let with_resolved_vars = self.resolve_vars_if_possible(goal);
|
let with_resolved_vars = self.resolve_vars_if_possible(goal);
|
||||||
if pred.alias != goal.predicate.as_normalizes_to().unwrap().skip_binder().alias {
|
if pred.alias
|
||||||
|
!= with_resolved_vars
|
||||||
|
.predicate
|
||||||
|
.as_normalizes_to()
|
||||||
|
.unwrap()
|
||||||
|
.no_bound_vars()
|
||||||
|
.unwrap()
|
||||||
|
.alias
|
||||||
|
{
|
||||||
unchanged_certainty = None;
|
unchanged_certainty = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,7 +733,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let GoalEvaluation { certainty, has_changed, stalled_on } =
|
let GoalEvaluation { goal, certainty, has_changed, stalled_on } =
|
||||||
self.evaluate_goal(GoalEvaluationKind::Nested, source, goal, stalled_on)?;
|
self.evaluate_goal(GoalEvaluationKind::Nested, source, goal, stalled_on)?;
|
||||||
if has_changed == HasChanged::Yes {
|
if has_changed == HasChanged::Yes {
|
||||||
unchanged_certainty = None;
|
unchanged_certainty = None;
|
||||||
|
|||||||
@@ -386,6 +386,10 @@ fn response_no_constraints_raw<I: Interner>(
|
|||||||
|
|
||||||
/// The result of evaluating a goal.
|
/// The result of evaluating a goal.
|
||||||
pub struct GoalEvaluation<I: Interner> {
|
pub struct GoalEvaluation<I: Interner> {
|
||||||
|
/// The goal we've evaluated. This is the input goal, but potentially with its
|
||||||
|
/// inference variables resolved. This never applies any inference constraints
|
||||||
|
/// from evaluating the goal.
|
||||||
|
pub goal: Goal<I, I::Predicate>,
|
||||||
pub certainty: Certainty,
|
pub certainty: Certainty,
|
||||||
pub has_changed: HasChanged,
|
pub has_changed: HasChanged,
|
||||||
/// If the [`Certainty`] was `Maybe`, then keep track of whether the goal has changed
|
/// If the [`Certainty`] was `Maybe`, then keep track of whether the goal has changed
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ where
|
|||||||
|
|
||||||
let result = delegate.evaluate_root_goal(goal, obligation.cause.span, stalled_on);
|
let result = delegate.evaluate_root_goal(goal, obligation.cause.span, stalled_on);
|
||||||
self.inspect_evaluated_obligation(infcx, &obligation, &result);
|
self.inspect_evaluated_obligation(infcx, &obligation, &result);
|
||||||
let GoalEvaluation { certainty, has_changed, stalled_on } = match result {
|
let GoalEvaluation { goal, certainty, has_changed, stalled_on } = match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(NoSolution) => {
|
Err(NoSolution) => {
|
||||||
errors.push(E::from_solver_error(
|
errors.push(E::from_solver_error(
|
||||||
@@ -218,6 +218,10 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We've resolved the goal in `evaluate_root_goal`, avoid redoing this work
|
||||||
|
// in the next iteration. This does not resolve the inference variables
|
||||||
|
// constrained by evaluating the goal.
|
||||||
|
obligation.predicate = goal.predicate;
|
||||||
if has_changed == HasChanged::Yes {
|
if has_changed == HasChanged::Yes {
|
||||||
// We increment the recursion depth here to track the number of times
|
// We increment the recursion depth here to track the number of times
|
||||||
// this goal has resulted in inference progress. This doesn't precisely
|
// this goal has resulted in inference progress. This doesn't precisely
|
||||||
|
|||||||
Reference in New Issue
Block a user