diff options
4 files changed, 37 insertions, 13 deletions
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index de1330ca82a..74c5b49ea92 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -53,17 +53,14 @@ where { /// Canonicalizes the goal remembering the original values /// for each bound variable. + /// + /// This expects `goal` and `opaque_types` to be eager resolved. pub(super) fn canonicalize_goal( &self, is_hir_typeck_root_goal: bool, goal: Goal<I, I::Predicate>, + opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>, ) -> (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 canonical = Canonicalizer::canonicalize_input( self.delegate, diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 053ccf285cf..8671cc7c3d3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -20,6 +20,7 @@ use super::has_only_region_constraints; use crate::coherence; use crate::delegate::SolverDelegate; use crate::placeholder::BoundVarReplacer; +use crate::resolve::eager_resolve_vars; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::ty::may_use_unstable_feature; @@ -440,6 +441,7 @@ where return Ok(( NestedNormalizationGoals::empty(), GoalEvaluation { + goal, certainty: Certainty::Maybe(stalled_on.stalled_cause), has_changed: HasChanged::No, 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) && self.delegate.in_hir_typeck(); - - let (orig_values, canonical_goal) = self.canonicalize_goal(is_hir_typeck_root_goal, goal); + let (orig_values, canonical_goal) = + self.canonicalize_goal(is_hir_typeck_root_goal, goal, opaque_types); let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); 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> { @@ -664,7 +675,7 @@ where let ( NestedNormalizationGoals(nested_goals), - GoalEvaluation { certainty, stalled_on, has_changed: _ }, + GoalEvaluation { goal, certainty, stalled_on, has_changed: _ }, ) = self.evaluate_goal_raw( GoalEvaluationKind::Nested, source, @@ -702,7 +713,15 @@ where // FIXME: Do we need to eagerly resolve here? Or should we check // if the cache key has any changed vars? 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; } @@ -714,7 +733,7 @@ where } } } 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)?; if has_changed == HasChanged::Yes { unchanged_certainty = None; diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index f39426c7689..9d52dee3c65 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -386,6 +386,10 @@ fn response_no_constraints_raw<I: Interner>( /// The result of evaluating a goal. 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 has_changed: HasChanged, /// If the [`Certainty`] was `Maybe`, then keep track of whether the goal has changed diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 3ce0f025512..70452947a8b 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -207,7 +207,7 @@ where let result = delegate.evaluate_root_goal(goal, obligation.cause.span, stalled_on); 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, Err(NoSolution) => { 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 { // We increment the recursion depth here to track the number of times // this goal has resulted in inference progress. This doesn't precisely |
