rust-lang / rust-lang/rust

performance regression with -Znext-solver=globally

Open
#159,933 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug I-compiletime needs-triage WG-trait-system-refactor
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

The new solver struggles more than the old one with (somewhat pathologically) large bodies, which happen in generated code quite a bit, I imagine. This is readily reproduced with:

// lib.rs — one function, N repetitions of the push line
pub fn big() {
    let mut v = Vec::new();
    v.push(Default::default());
    // ... repeat N times ...
    v.push(0u8);
}

To create the test cases:

python3 -c "
n = 4000
print('pub fn big() {'); print('    let mut v = Vec::new();')
print('    v.push(Default::default());\n' * n, end='')
print('    v.push(0u8);'); print('}')" > lib.rs

Run (typeck only, no codegen):

rustc +nightly --crate-type=lib --edition=2024 --emit=metadata --out-dir /tmp/out lib.rs
rustc +nightly --crate-type=lib --edition=2024 --emit=metadata --out-dir /tmp/out -Znext-solver=globally lib.rs
Measurements (wall clock)
N (pushes) old solver next solver next/old
500 0.06s 0.74s 12×
1,000 0.15s 2.88s 19×
2,000 0.47s 11.06s 24×
4,000 1.76s 46.85s 27×
8,000 6.97s 216.27s 31×
16,000 28.35s (not measured)

Both are clearly non-linear in behavior, due to the O(n) passes x O(n) pending obligations, but the new solver has a much higher constant factor, it seems. The work done in #158249 has made each handling of a stalled obligation cheaper, but did not remove the scan. My friendly neighborhood AI points to FulfillmentCtxt::try_evaluate_obligations gathering work with drain_pending(|_, _| true) in compiler/rustc_trait_selection/src/solve/fulfill.rs.

The following might well be related:

  • rust-lang/rust#131411 (cranelift-codegen, ISLE-generated functions, 10×, open and undiagnosed)
  • rust-lang/trait-system-refactor-initiative#228 (wg-grammar, closed as "acceptable" after constant-factor fast-path work)
  • rust-lang/trait-system-refactor-initiative#254 (crater perf triage)

I've run into this in rust-analyzer, which shares this code, its inference makes more fulfillment passes per body.

Meta

rustc 1.99.0-nightly (89c61a754 2026-07-23)
Disclosure: the investigation and benchmarking was supported by AI

@rustbot label +I-compiletime +WG-trait-system-refactor

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the supplied generated lib.rs reproducer and the two rustc commands, then inspect compiler/rustc_trait_selection/src/solve/fulfill.rs, especially try_evaluate_obligations and drain_pending. Compare timings across the listed push counts and trace the pending-obligation work; done means identifying and addressing the next-solver regression without changing the reproducer's expected behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.