Implement a new flag -Zdisable-fast-paths in trait solving

This commit is contained in:
Shoyu Vanilla
2026-05-05 13:31:40 +09:00
parent 1d72d7e813
commit 4432f6bf82
11 changed files with 42 additions and 8 deletions
@@ -22,6 +22,10 @@ fn next_trait_solver(&self) -> bool {
self.next_trait_solver
}
fn disable_trait_solver_fast_paths(&self) -> bool {
self.disable_trait_solver_fast_paths()
}
fn typing_mode(&self) -> ty::TypingMode<'tcx> {
self.typing_mode()
}
+5
View File
@@ -640,6 +640,11 @@ pub fn next_trait_solver(&self) -> bool {
self.next_trait_solver
}
#[inline(always)]
pub fn disable_trait_solver_fast_paths(&self) -> bool {
self.tcx.disable_trait_solver_fast_paths()
}
#[inline(always)]
pub fn typing_mode(&self) -> TypingMode<'tcx> {
self.typing_mode
+4
View File
@@ -2657,6 +2657,10 @@ pub fn next_trait_solver_in_coherence(self) -> bool {
self.sess.opts.unstable_opts.next_solver.coherence
}
pub fn disable_trait_solver_fast_paths(self) -> bool {
self.sess.opts.unstable_opts.disable_fast_paths
}
#[allow(rustc::bad_opt_access)]
pub fn use_typing_mode_borrowck(self) -> bool {
self.next_trait_solver_globally() || self.sess.opts.unstable_opts.typing_mode_borrowck
@@ -447,6 +447,7 @@ pub(super) fn evaluate_goal_raw(
ref sub_roots,
stalled_certainty,
}) = stalled_on
&& !self.delegate.disable_trait_solver_fast_paths()
&& !stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value))
&& !sub_roots
.iter()
@@ -666,7 +667,10 @@ fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution>
// If this loop did not result in any progress, what's our final certainty.
let mut unchanged_certainty = Some(Certainty::Yes);
for (source, goal, stalled_on) in mem::take(&mut self.nested_goals) {
if let Some(certainty) = self.delegate.compute_goal_fast_path(goal, self.origin_span) {
if !self.delegate.disable_trait_solver_fast_paths()
&& let Some(certainty) =
self.delegate.compute_goal_fast_path(goal, self.origin_span)
{
match certainty {
Certainty::Yes => {}
Certainty::Maybe { .. } => {
+2
View File
@@ -2269,6 +2269,8 @@ pub(crate) fn parse_assert_incr_state(
themselves (default: no)"),
direct_access_external_data: Option<bool> = (None, parse_opt_bool, [TRACKED],
"Direct or use GOT indirect to reference external data symbols"),
disable_fast_paths: bool = (false, parse_bool, [TRACKED],
"disable various performance optimizations in trait solving"),
dual_proc_macros: bool = (false, parse_bool, [TRACKED],
"load proc macros for both target and host, but only link to the target (default: no)"),
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
@@ -186,8 +186,9 @@ fn try_evaluate_obligations(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
let goal = obligation.as_goal();
let delegate = <&SolverDelegate<'tcx>>::from(infcx);
if let Some(certainty) =
delegate.compute_goal_fast_path(goal, obligation.cause.span)
if !delegate.disable_trait_solver_fast_paths()
&& let Some(certainty) =
delegate.compute_goal_fast_path(goal, obligation.cause.span)
{
match certainty {
// This fast path doesn't depend on region identity so it doesn't
@@ -325,6 +325,10 @@ fn skippable_obligations<'b>(
/// compile-time benchmarks are very sensitive to even small changes.
#[inline(always)]
fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
if self.selcx.infcx.disable_trait_solver_fast_paths() {
return true;
}
// If we were stalled on some unresolved variables, first check whether
// any of them have been resolved; if not, don't bother doing more work
// yet.
@@ -388,7 +392,9 @@ fn process_obligation(
let infcx = self.selcx.infcx;
if sizedness_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) {
if !infcx.disable_trait_solver_fast_paths()
&& sizedness_fast_path(infcx.tcx, obligation.predicate, obligation.param_env)
{
return ProcessResult::Changed(thin_vec![]);
}
@@ -110,7 +110,9 @@ fn fully_perform_into(
),
NoSolution,
> {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
if !infcx.disable_trait_solver_fast_paths()
&& let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key)
{
return Ok((result, None, PredicateObligations::new(), Certainty::Proven));
}
@@ -159,7 +161,9 @@ fn fully_perform(
"query type op",
span,
|ocx| {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &self) {
if !infcx.disable_trait_solver_fast_paths()
&& let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &self)
{
return Ok(result);
}
QueryTypeOp::perform_locally_with_next_solver(ocx, self, span)
@@ -604,7 +604,9 @@ fn evaluate_predicate_recursively<'o>(
None => self.check_recursion_limit(&obligation, &obligation)?,
}
if sizedness_fast_path(self.tcx(), obligation.predicate, obligation.param_env) {
if !self.infcx.disable_trait_solver_fast_paths()
&& sizedness_fast_path(self.tcx(), obligation.predicate, obligation.param_env)
{
return Ok(EvaluatedToOk);
}
@@ -24,7 +24,7 @@ fn evaluate_obligation<'tcx>(
debug!("evaluate_obligation: goal={:#?}", goal);
let ParamEnvAnd { param_env, value: predicate } = goal;
if sizedness_fast_path(tcx, predicate, param_env) {
if !tcx.disable_trait_solver_fast_paths() && sizedness_fast_path(tcx, predicate, param_env) {
return Ok(EvaluationResult::EvaluatedToOk);
}
+2
View File
@@ -230,6 +230,8 @@ fn next_trait_solver(&self) -> bool {
true
}
fn disable_trait_solver_fast_paths(&self) -> bool;
fn typing_mode(&self) -> TypingMode<Self::Interner>;
fn universe(&self) -> ty::UniverseIndex;