Skip to content

Commit 9e31dcb

Browse files
Fast path for processing some obligations in the new solver
1 parent 9578b59 commit 9e31dcb

File tree

5 files changed

+59
-7
lines changed

5 files changed

+59
-7
lines changed

compiler/rustc_next_trait_solver/src/delegate.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
1717
where
1818
V: TypeFoldable<Self::Interner>;
1919

20+
fn compute_goal_fast_path(
21+
&self,
22+
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
23+
span: <Self::Interner as Interner>::Span,
24+
) -> Option<()>;
25+
2026
fn fresh_var_for_kind_with_span(
2127
&self,
2228
arg: <Self::Interner as Interner>::GenericArg,

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use std::iter;
1313

1414
use rustc_index::IndexVec;
15+
use rustc_type_ir::data_structures::HashSet;
1516
use rustc_type_ir::inherent::*;
1617
use rustc_type_ir::relate::solver_relating::RelateExt;
1718
use rustc_type_ir::{
@@ -158,10 +159,12 @@ where
158159
self.compute_external_query_constraints(certainty, normalization_nested_goals);
159160
let (var_values, mut external_constraints) = (self.var_values, external_constraints)
160161
.fold_with(&mut EagerResolver::new(self.delegate));
161-
// Remove any trivial region constraints once we've resolved regions
162-
external_constraints
163-
.region_constraints
164-
.retain(|outlives| outlives.0.as_region().is_none_or(|re| re != outlives.1));
162+
163+
// Remove any trivial or duplicated region constraints once we've resolved regions
164+
let mut unique = HashSet::default();
165+
external_constraints.region_constraints.retain(|outlives| {
166+
outlives.0.as_region().is_none_or(|re| re != outlives.1) && unique.insert(*outlives)
167+
});
165168

166169
let canonical = Canonicalizer::canonicalize_response(
167170
self.delegate,

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,11 @@ where
603603
// If this loop did not result in any progress, what's our final certainty.
604604
let mut unchanged_certainty = Some(Certainty::Yes);
605605
for (source, goal) in mem::take(&mut self.nested_goals) {
606+
if let Some(()) = self.delegate.compute_goal_fast_path(goal, self.origin_span) {
607+
unchanged_certainty = None;
608+
continue;
609+
}
610+
606611
// We treat normalizes-to goals specially here. In each iteration we take the
607612
// RHS of the projection, replace it with a fresh inference variable, and only
608613
// after evaluating that goal do we equate the fresh inference variable with the

compiler/rustc_trait_selection/src/solve/delegate.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ use rustc_infer::infer::canonical::query_response::make_query_region_constraints
66
use rustc_infer::infer::canonical::{
77
Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues,
88
};
9-
use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt};
9+
use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt};
1010
use rustc_infer::traits::solve::Goal;
1111
use rustc_middle::traits::query::NoSolution;
1212
use rustc_middle::traits::solve::Certainty;
1313
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, TypingMode};
1414
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
1515

16-
use crate::traits::{EvaluateConstErr, specialization_graph};
16+
use crate::traits::{EvaluateConstErr, ObligationCause, specialization_graph};
1717

1818
#[repr(transparent)]
1919
pub struct SolverDelegate<'tcx>(InferCtxt<'tcx>);
@@ -55,6 +55,37 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
5555
(SolverDelegate(infcx), value, vars)
5656
}
5757

58+
fn compute_goal_fast_path(
59+
&self,
60+
goal: Goal<'tcx, ty::Predicate<'tcx>>,
61+
span: Span,
62+
) -> Option<()> {
63+
let pred = goal.predicate.kind();
64+
match pred.no_bound_vars()? {
65+
ty::PredicateKind::DynCompatible(def_id) if self.0.tcx.is_dyn_compatible(def_id) => {
66+
Some(())
67+
}
68+
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(outlives)) => {
69+
self.0.sub_regions(
70+
SubregionOrigin::RelateRegionParamBound(span, None),
71+
outlives.1,
72+
outlives.0,
73+
);
74+
Some(())
75+
}
76+
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
77+
self.0.register_region_obligation_with_cause(
78+
outlives.0,
79+
outlives.1,
80+
&ObligationCause::dummy_with_span(span),
81+
);
82+
83+
Some(())
84+
}
85+
_ => None,
86+
}
87+
}
88+
5889
fn fresh_var_for_kind_with_span(
5990
&self,
6091
arg: ty::GenericArg<'tcx>,

compiler/rustc_trait_selection/src/solve/fulfill.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_infer::traits::{
1212
use rustc_middle::ty::{
1313
self, DelayedSet, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, TypingMode,
1414
};
15+
use rustc_next_trait_solver::delegate::SolverDelegate as _;
1516
use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _};
1617
use rustc_span::Span;
1718
use tracing::instrument;
@@ -172,7 +173,13 @@ where
172173
}
173174

174175
let goal = obligation.as_goal();
175-
let result = <&SolverDelegate<'tcx>>::from(infcx)
176+
let delegate = <&SolverDelegate<'tcx>>::from(infcx);
177+
if let Some(()) = delegate.compute_goal_fast_path(goal, obligation.cause.span) {
178+
has_changed = true;
179+
continue;
180+
}
181+
182+
let result = delegate
176183
.evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span)
177184
.0;
178185
self.inspect_evaluated_obligation(infcx, &obligation, &result);

0 commit comments

Comments
 (0)