Skip to content

reduce needed recursion limit to avoid next-solver FCW - #172

Merged
novacrazy merged 1 commit into
fizyk20:masterfrom
lcnr:master
Aug 7, 2026
Merged

reduce needed recursion limit to avoid next-solver FCW#172
novacrazy merged 1 commit into
fizyk20:masterfrom
lcnr:master

Conversation

@lcnr

@lcnr lcnr commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Hi there 👋 we're going to be stabilizing the next-generation trait solver soon. You can test it on nightly with -Znext-solver.

Unfortunately, generic-array currently encounters overflow errors when computing MaxArrayLengthP1 when used with the new solver. While we are weakening them to a FCW - future compatibility warning - for the initial stabilization, that lint isn't ideal as it also affects dependencies using generic-array. We currently get ~5000 warnings in some dependencies. I've been spending some time looking into that and this is a way to reduce the recursion limit:

#![recursion_limit = "73"]
pub fn main() {
    let x: <typenum::U256 as typenum::Pow<typenum::U<{ std::mem::size_of::<usize>() }>>>::Output;
}

vs

#![recursion_limit = "130"]
pub fn main() {
    let x: typenum::Shleft<
        typenum::U1,
        typenum::Shleft<typenum::U<{ std::mem::size_of::<usize>() }>, typenum::U3>,
    >;
}

The overflow issue is described in rust-lang/rust#159228. The core issue is that the old solver did not track the required depth in its cache. This meant that evaluating something which requires a depth of 100 and then using its cache entry at a depth of 50 didn't fail with an overflow error, even though if the cache entry wasn't present, we'd have needed a total depth of 150. This can break incremental compilation, so we're now properly tracking this with the new implementation.

Using Shleft<N, M> requires a recursion depth of log_2(N) + 2M because of this impl https://github.com/paholg/typenum/blob/0db9a0f731981f29266b63586c29fa07e4477b1a/src/uint.rs#L1005.

Shleft<N, M> is implemented as Shleft<UInt<N, B0>, M - 1> and needs to prove that its self type is Unsigned at every step. This means after recursing for M steps the final use of this Shl impl now need to also check that a N << M is Unsigned, which requires log_2(N) + M steps as it's linear in the number of bits.

I feel like ideally we'd also change Shl in typenum to not require 2M recursion steps, but I don't fully know how to do this and there's also the question of the compile time performance impact. That one will also be affected by the new trait solver and its performance and caching behavior is quite different from the existing implementation. Going to open a separate issue in typenum about this.

I would deeply appreciate if you could publish new minor versions of generic-array. Certainly 1.0 and looking at https://crates.io/crates/generic-array/reverse_dependencies also 0.14. Older versions would be appreciated, but feel less necessary to me.

Thank you so much and I am open for any questions you may have :>

@novacrazy
novacrazy merged commit 27e85da into fizyk20:master Aug 7, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants