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:
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 (89c61a7 2026-07-23)
Disclosure: the investigation and benchmarking was supported by AI
@rustbot label +I-compiletime +WG-trait-system-refactor
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:
To create the test cases:
Run (typeck only, no codegen):
Measurements (wall clock)
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:
cranelift-codegenwith-Z next-solveris very slow #131411 (cranelift-codegen, ISLE-generated functions, 10×, open and undiagnosed)wg-grammaris slow trait-system-refactor-initiative#228 (wg-grammar, closed as "acceptable" after constant-factor fast-path work)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 (89c61a7 2026-07-23)
Disclosure: the investigation and benchmarking was supported by AI
@rustbot label +I-compiletime +WG-trait-system-refactor