-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rustc hangs in infinite loop with recursive unboxed closures #33502
Comments
Most common non-terminating cases will reach the recursion limit in linear time, but some take an exponential amount of time. For example (verified in rust 1.8):
I'm pretty sure that it's not decidable whether monomorphization will terminate, so we're probably stuck with some cases like this. In addition, the compiler probably just guarantees that non-terminating cases won't compile, not what happens when you try to compile them. |
Is it possible for the recursion limit to take more than exponential time to reach? |
It seems unlikely. When monomorphizing a function, the compiler will monomorphize a bounded number of other functions. Assuming recursion depth actually increases with each call, the number of distinct monomorphized functions should be at most exponential in the recursion limit. However, you should be able to use #[inline(always)] to generate functions with exponential size in the recursion depth. If the compiler uses any optimizations that are exponential in code size, and these optimizations occur during monomorphization, then it would take a superexponential amount of time to reach the recursion limit. In all likelihood, such optimizations turn off once code reaches a certain size. I haven't had any luck understanding what happens with the original code. |
Not sure what is the best way to resolve this. Maybe we could add a polymorphic monomorphization recursion checker that detects cases of Maybe limit the amount of monomorphizations per function to a million or something? Testing shows this would take too much (10s on this trivial example, so worse on bigger ones). 64k sounds too small. Maybe limit polymorphically recursive functions to |
I believe this is fixed with #48296. Playground: https://play.rust-lang.org/?gist=e8a4ee3a198c6c8c543cce18e6eb8bbb&version=nightly |
I have been trying to write a generic tree diff, but during that I seem to have accidentally proved that something in rustc is Turing-complete.
Here is the minimal code I have been able to reproduce the issue with. If this is fed to rustc then it hangs itself in an infinite loop:
If generic
F
is replaced with anFn
reference then the snippet (obviously) compiles and runs just fine.If
fun
is not used inprocess
or theiter().map().collect()
chain is rewritten into a for-loop then rustc fails (as expected, I believe) withMemory usage is constant when this happens, rustc just eats up all available CPU.
I have reproduced this on 64-bit Linux and Windows (GNU) versions, with current stable (1.8), beta, and nightly (d91f8ab) builds. The behavior is identical for all of them.
Here is an example stacktrace of the nightly rustc during the hang. It does not grow infinitely, just fluctuates around 160 calls when I break into gdb.
The text was updated successfully, but these errors were encountered: