Prevent compiler stack overflow for deeply recursive code
I was unable to write a test that
1. runs in under 1s
2. overflows on my machine without this patch
The following reproduces the issue, but I don't think it's sensible to include a test that takes 30s to compile. We can now easily squash newly appearing overflows by the strategic insertion of calls to `ensure_sufficient_stack`.
```rust
// compile-pass
#![recursion_limit="1000000"]
macro_rules! chain {
(EE $e:expr) => {$e.sin()};
(RECURSE $i:ident $e:expr) => {chain!($i chain!($i chain!($i chain!($i $e))))};
(Z $e:expr) => {chain!(RECURSE EE $e)};
(Y $e:expr) => {chain!(RECURSE Z $e)};
(X $e:expr) => {chain!(RECURSE Y $e)};
(A $e:expr) => {chain!(RECURSE X $e)};
(B $e:expr) => {chain!(RECURSE A $e)};
(C $e:expr) => {chain!(RECURSE B $e)};
// causes overflow on x86_64 linux
// less than 1 second until overflow on test machine
// after overflow has been fixed, takes 30s to compile :/
(D $e:expr) => {chain!(RECURSE C $e)};
(E $e:expr) => {chain!(RECURSE D $e)};
(F $e:expr) => {chain!(RECURSE E $e)};
// more than 10 seconds
(G $e:expr) => {chain!(RECURSE F $e)};
(H $e:expr) => {chain!(RECURSE G $e)};
(I $e:expr) => {chain!(RECURSE H $e)};
(J $e:expr) => {chain!(RECURSE I $e)};
(K $e:expr) => {chain!(RECURSE J $e)};
(L $e:expr) => {chain!(RECURSE L $e)};
}
fn main() {
let x = chain!(D 42.0_f32);
}
```
fixes #55471
fixes #41884
fixes #40161
fixes #34844
fixes #32594
cc @alexcrichton @rust-lang/compiler
I looked at all code that checks the recursion limit and inserted stack growth calls where appropriate.
|
||
|---|---|---|
| .. | ||
| bootstrap | ||
| build_helper | ||
| ci | ||
| doc | ||
| etc | ||
| liballoc | ||
| libarena | ||
| libcore | ||
| libfmt_macros | ||
| libgraphviz | ||
| libpanic_abort | ||
| libpanic_unwind | ||
| libproc_macro | ||
| libprofiler_builtins | ||
| librustc_apfloat | ||
| librustc_ast | ||
| librustc_ast_lowering | ||
| librustc_ast_passes | ||
| librustc_ast_pretty | ||
| librustc_attr | ||
| librustc_builtin_macros | ||
| librustc_codegen_llvm | ||
| librustc_codegen_ssa | ||
| librustc_data_structures | ||
| librustc_driver | ||
| librustc_error_codes | ||
| librustc_errors | ||
| librustc_expand | ||
| librustc_feature | ||
| librustc_fs_util | ||
| librustc_hir | ||
| librustc_hir_pretty | ||
| librustc_incremental | ||
| librustc_index | ||
| librustc_infer | ||
| librustc_interface | ||
| librustc_lexer | ||
| librustc_lint | ||
| librustc_llvm | ||
| librustc_macros | ||
| librustc_metadata | ||
| librustc_middle | ||
| librustc_mir | ||
| librustc_mir_build | ||
| librustc_parse | ||
| librustc_passes | ||
| librustc_plugin_impl | ||
| librustc_privacy | ||
| librustc_query_system | ||
| librustc_resolve | ||
| librustc_save_analysis | ||
| librustc_session | ||
| librustc_span | ||
| librustc_symbol_mangling | ||
| librustc_target | ||
| librustc_trait_selection | ||
| librustc_traits | ||
| librustc_ty | ||
| librustc_typeck | ||
| librustdoc | ||
| libserialize | ||
| libstd | ||
| libterm | ||
| libtest | ||
| libunwind | ||
| llvm-project@3ba91917e5 | ||
| rtstartup | ||
| rustc | ||
| rustllvm | ||
| stdarch@d10eefc622 | ||
| test | ||
| tools | ||
| README.md | ||
| stage0.txt | ||
This directory contains the source code of the rust project, including:
rustcand its testslibstd- Various submodules for tools, like rustdoc, rls, etc.
For more information on how various parts of the compiler work, see the rustc dev guide.