Open jhpratt opened 5 months ago
Minimized example, producing the exponential time behavior, albeit apparently at a slower growth.
#![allow(unused_variables, dead_code)]
trait SomeTrait<'a> {
type Output;
}
fn get_some_trait<'a>(_x: impl SomeTrait<'a>) {}
fn wrap<T: SomeTrait<'static, Output = u8>>(x: T) -> Wrapped<T> {
Wrapped(x)
}
struct Thing;
impl SomeTrait<'static> for Thing {
type Output = u8;
}
struct Wrapped<P>(P);
impl<'a, P: SomeTrait<'a, Output = u8>> SomeTrait<'a> for Wrapped<P> {
type Output = P::Output;
}
pub fn parse_week_number() {
let _ =
get_some_trait(
wrap(
wrap(
wrap(
wrap(
wrap(
wrap(
wrap(
wrap(
wrap(
wrap(
wrap(
wrap(
wrap(
wrap(
wrap(
Thing
))))))))))))))));
}
Given this significantly reduced example of real-world code,
compiling with the larger number of chained methods (i.e. with
#[cfg(feature = "slowdown")]
) results in apparent exponential (correlation = 0.992) time complexity forcargo check
. The code as written takes approximately 9-10 seconds to type check on my laptop. Uncommenting two of the three lines that are presently commented out took 7m51s (471 seconds) for the same.Checking with
-Znext-solver
improves the situation quite a bit, but the behavior still seems to be exponential.Removing the equality constraints from
or_unify
avoids the pathological case entirely. I suspect this is a starting point for investigating a possible fix.Difference using
-Zself-profile
(nearly all rows elided for brevity, plus most changes are just noise)Total cpu time: -11.830756846s
Without performing a thorough check, I checked the time to type check on both 1.65 and 1.40 with similar results. Given that, this behavior has been around for 4+ years at a minimum.