Skip to content

add a FCW for overflow errors with the next solver#159224

Open
adwinwhite wants to merge 1 commit into
rust-lang:mainfrom
adwinwhite:cache-depth-fcw
Open

add a FCW for overflow errors with the next solver#159224
adwinwhite wants to merge 1 commit into
rust-lang:mainfrom
adwinwhite:cache-depth-fcw

Conversation

@adwinwhite

@adwinwhite adwinwhite commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

The old solver doesn't check cache entry's depth requirement when looking up cache while the next solver correctly does so. It's necessary to behave correctly with respect to incremental compilation.
As a result, the next solver is more likely to run into overflow errors.

We try to catch such breakages by rerun the evaluation with doubled recursion limit and if that succeeds we emit a FCW.

This PR is being discussed on zulip

r? @lcnr

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Jul 13, 2026
@adwinwhite

Copy link
Copy Markdown
Contributor Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 13, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Jul 13, 2026
[WIP] add FCW for overflow with the next solver
@rust-log-analyzer

This comment has been minimized.

@rust-bors

rust-bors Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 6eb68d9 (6eb68d9057fb9a60e047c7c7dcc9b67b9cedc1a7)
Base parent: 5503df8 (5503df87342a73d0c29126a7e08dc9c1255c46ad)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (6eb68d9): comparison URL.

Overall result: ❌ regressions - please read:

Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf.

Next, please: If you can, justify the regressions found in this try perf run in writing along with @rustbot label: +perf-regression-triaged. If not, fix the regressions and do another perf run. Neutral or positive results will clear the label automatically.

@bors rollup=never rustc-perf
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.3% [0.3%, 4.5%] 9
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (primary -2.1%, secondary -0.9%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
1.4% [0.8%, 2.5%] 3
Improvements ✅
(primary)
-2.1% [-2.1%, -2.1%] 1
Improvements ✅
(secondary)
-4.5% [-4.7%, -4.3%] 2
All ❌✅ (primary) -2.1% [-2.1%, -2.1%] 1

Cycles

Results (secondary -4.2%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-4.2% [-5.7%, -2.7%] 2
All ❌✅ (primary) - - 0

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 487.42s -> 490.943s (0.72%)
Artifact size: 389.91 MiB -> 389.35 MiB (-0.15%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Jul 13, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@adwinwhite adwinwhite changed the title [WIP] add FCW for overflow with the next solver add a FCW for overflow errors with the next solver Jul 16, 2026
@rust-log-analyzer

This comment has been minimized.

@adwinwhite
adwinwhite marked this pull request as ready for review July 16, 2026 13:54
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 16, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot

rustbot commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@lcnr lcnr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like next_trait_solver_overflow as a lint name 🤔 it feels too tied to the implementation. exceeded_recursion_limit or sth feels better

I think we should also mention the predicate that caused overflow, to allow the user to fix the overflow by e.g. manually implementing Send for one of their types

View changes since this review

self.evaluate_root_goal_for_proof_tree_raw((canonical_goal, root_depth))
}

fn emit_next_solver_overflow_fcw(self, span: Option<Span>) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

take a Span and supply a DUMMY_SP in the caller where necessary

fn emit_next_solver_overflow_fcw(self, span: Option<Span>) {
self.emit_node_span_lint(
rustc_session::lint::builtin::NEXT_TRAIT_SOLVER_OVERFLOW,
CRATE_HIR_ID,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yeah, I guess that works 👍

we should somehow adjust the error message to say that this lint is always attached to the whole crate and can't be disabled on a per function basis

Comment on lines +249 to +282
let eval_with_recursion_limit = |limit| {
EvalCtxt::enter_root(self, limit, span, |ecx| {
ecx.evaluate_goal_no_fast_paths(GoalSource::Misc, goal)
})
};
let is_overflow_and_has_no_stalled_infers = |eval_result: &Result<GoalEvaluation<I>, _>| {
let predicate = match eval_result {
Err(_) => return false,
Ok(goal_evaluation) if !goal_evaluation.certainty.is_overflow() => return false,
Ok(goal_evaluation) => goal_evaluation.goal.predicate,
};

let has_no_stalled_infers = match predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection)) => {
!projection.projection_term.has_non_region_infer()
}
_ => !predicate.has_non_region_infer(),
};
has_no_stalled_infers
};

// The old solver doesn't check depth requirement when looking up cache
// while the next solver does so. Thus the next solver is more prone to
// overflow. We emit a FCW for this.
let mut result = eval_with_recursion_limit(self.cx().recursion_limit());
if is_overflow_and_has_no_stalled_infers(&result) {
let new_result = eval_with_recursion_limit(self.cx().recursion_limit() * 2);
if let Ok(goal_evaluation) = &new_result
&& goal_evaluation.certainty.is_yes()
{
self.cx().emit_next_solver_overflow_fcw(Some(span));
result = new_result;
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you move this into a separate functions, e.g. is_overflow_and_has_no_stalled_infer can probably be shared between the call sites

can you do the reevaluation in a commit_if_ok so that we don't apply the inference etc constraints of the reevaluation while ignoring its result?


// The old solver doesn't check depth requirement when looking up cache
// while the next solver does so. Thus the next solver is more prone to
// overflow. We emit a FCW for this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

link to an issue/the lint track issue/somewhere here

@lcnr lcnr added the I-types-nominated Nominated for discussion during a types team meeting. label Jul 17, 2026
@lcnr

lcnr commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

ah, and please limit this to not apply in TypingMode::Coherence 😁 that way we don't get spurious errors in coherence checking

we should do a next solver crater run with this to see how many crates are impacted by this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

I-types-nominated Nominated for discussion during a types team meeting. perf-regression Performance regression. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants