diff options
Diffstat (limited to 'compiler/rustc_next_trait_solver/src')
3 files changed, 23 insertions, 4 deletions
diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 90a7c2e9f78..bb923612cff 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -3,6 +3,8 @@ use std::ops::Deref; use rustc_type_ir::solve::{Certainty, Goal, NoSolution}; use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable}; +use crate::solve::HasChanged; + pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized { type Infcx: InferCtxtLike<Interner = Self::Interner>; type Interner: Interner; @@ -17,6 +19,12 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized { where V: TypeFoldable<Self::Interner>; + fn compute_goal_fast_path( + &self, + goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>, + span: <Self::Interner as Interner>::Span, + ) -> Option<HasChanged>; + fn fresh_var_for_kind_with_span( &self, arg: <Self::Interner as Interner>::GenericArg, 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 36f68808a2c..c62f2e2e0e9 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 @@ -12,6 +12,7 @@ use std::iter; use rustc_index::IndexVec; +use rustc_type_ir::data_structures::HashSet; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::{ @@ -158,10 +159,12 @@ where self.compute_external_query_constraints(certainty, normalization_nested_goals); let (var_values, mut external_constraints) = (self.var_values, external_constraints) .fold_with(&mut EagerResolver::new(self.delegate)); - // Remove any trivial region constraints once we've resolved regions - external_constraints - .region_constraints - .retain(|outlives| outlives.0.as_region().is_none_or(|re| re != outlives.1)); + + // Remove any trivial or duplicated region constraints once we've resolved regions + let mut unique = HashSet::default(); + external_constraints.region_constraints.retain(|outlives| { + outlives.0.as_region().is_none_or(|re| re != outlives.1) && unique.insert(*outlives) + }); let canonical = Canonicalizer::canonicalize_response( 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 fc5dad9a3ed..9a4b95903a9 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 @@ -603,6 +603,14 @@ where // If this loop did not result in any progress, what's our final certainty. let mut unchanged_certainty = Some(Certainty::Yes); for (source, goal) in mem::take(&mut self.nested_goals) { + if let Some(has_changed) = self.delegate.compute_goal_fast_path(goal, self.origin_span) + { + if matches!(has_changed, HasChanged::Yes) { + unchanged_certainty = None; + } + continue; + } + // We treat normalizes-to goals specially here. In each iteration we take the // RHS of the projection, replace it with a fresh inference variable, and only // after evaluating that goal do we equate the fresh inference variable with the |
