Yes the above version contains types that the size of it is also growing exponentially. But here is another example that have linear size
#![feature(core_intrinsics)]
use std::mem::size_of;
enum When<T1,T2>
where T1:Sync, T2:Sync
{
Either(T1),
Or(T2)
}
use When::{Either,Or};
fn roll(a:impl Sync) -> impl Sync {
if true {Either(a)} else { Or(a) }
}
fn roll1(a:impl Sync) -> impl Sync {
roll(roll(a))
}
fn roll2(a:impl Sync) -> impl Sync {
roll1(roll1(a))
}
fn print_type_of<T>(_: T) {
let s = format!("{}", unsafe { std::intrinsics::type_name::<T>() });
println!("{}\nsize={}\ntype name length={}", s, size_of::<T>(), s.len());
}
fn main() {
print_type_of(roll2(roll2(roll2(11))));
}
Output:
When<When<....
size=52
type name length=45048
I believe this is what I was experiencing: I have an enum that works like When above called EitherFuture, and I use it to wrap different Futures returned from different arms of match statements. Each of such attempt, like the above, doubles or almost doubles the size of the type name length, and so eventially exceeded the length limit of the compiler.
By the way, if you want to look at the work I did, check out this. Look at the function serve and image you have replaced all box (it calls mybox function in the code though) with something similar to When above.
(The refactoring and EitherFuture are not submitted yet so you won’t see it now, I may commit tonight once I found a way to use closure to hide concrete type components from type names.)