Fast path for processing some obligations in the new solver
This commit is contained in:
parent
7205fc537d
commit
1d0d258a86
5 changed files with 67 additions and 7 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -6,14 +6,15 @@ use rustc_infer::infer::canonical::query_response::make_query_region_constraints
|
|||
use rustc_infer::infer::canonical::{
|
||||
Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues,
|
||||
};
|
||||
use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt};
|
||||
use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt};
|
||||
use rustc_infer::traits::solve::Goal;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::solve::Certainty;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, TypingMode};
|
||||
use rustc_next_trait_solver::solve::HasChanged;
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||
|
||||
use crate::traits::{EvaluateConstErr, specialization_graph};
|
||||
use crate::traits::{EvaluateConstErr, ObligationCause, specialization_graph};
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct SolverDelegate<'tcx>(InferCtxt<'tcx>);
|
||||
|
|
@ -55,6 +56,37 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
|||
(SolverDelegate(infcx), value, vars)
|
||||
}
|
||||
|
||||
fn compute_goal_fast_path(
|
||||
&self,
|
||||
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
||||
span: Span,
|
||||
) -> Option<HasChanged> {
|
||||
let pred = goal.predicate.kind();
|
||||
match pred.no_bound_vars()? {
|
||||
ty::PredicateKind::DynCompatible(def_id) if self.0.tcx.is_dyn_compatible(def_id) => {
|
||||
Some(HasChanged::No)
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(outlives)) => {
|
||||
self.0.sub_regions(
|
||||
SubregionOrigin::RelateRegionParamBound(span, None),
|
||||
outlives.1,
|
||||
outlives.0,
|
||||
);
|
||||
Some(HasChanged::No)
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
|
||||
self.0.register_region_obligation_with_cause(
|
||||
outlives.0,
|
||||
outlives.1,
|
||||
&ObligationCause::dummy_with_span(span),
|
||||
);
|
||||
|
||||
Some(HasChanged::No)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn fresh_var_for_kind_with_span(
|
||||
&self,
|
||||
arg: ty::GenericArg<'tcx>,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use rustc_infer::traits::{
|
|||
use rustc_middle::ty::{
|
||||
self, DelayedSet, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, TypingMode,
|
||||
};
|
||||
use rustc_next_trait_solver::delegate::SolverDelegate as _;
|
||||
use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _};
|
||||
use rustc_span::Span;
|
||||
use tracing::instrument;
|
||||
|
|
@ -172,7 +173,15 @@ where
|
|||
}
|
||||
|
||||
let goal = obligation.as_goal();
|
||||
let result = <&SolverDelegate<'tcx>>::from(infcx)
|
||||
let delegate = <&SolverDelegate<'tcx>>::from(infcx);
|
||||
if let Some(fast_path_has_changed) =
|
||||
delegate.compute_goal_fast_path(goal, obligation.cause.span)
|
||||
{
|
||||
has_changed |= matches!(fast_path_has_changed, HasChanged::Yes);
|
||||
continue;
|
||||
}
|
||||
|
||||
let result = delegate
|
||||
.evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span)
|
||||
.0;
|
||||
self.inspect_evaluated_obligation(infcx, &obligation, &result);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue