-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
checking for structural recursion can cause a stack overflow #84611
Comments
the recursion happens in rust/compiler/rustc_middle/src/ty/util.rs Lines 1001 to 1017 in e188693
Because |
jonas-schievink
added
the
I-crash
Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.
label
Apr 27, 2021
cc #74224 |
Dylan-DPC-zz
pushed a commit
to Dylan-DPC-zz/rust
that referenced
this issue
May 10, 2021
Fix stack overflow when checking for structural recursion This pull request aims to fix rust-lang#74224 and fix rust-lang#84611. The current logic for detecting ADTs with structural recursion is flawed because it only looks at the root type, and then for exact matches. What I mean by this is that for examples such as: ```rust struct A<T> { x: T, y: A<A<T>>, } struct B { z: A<usize> } fn main() {} ``` When checking `A`, the compiler correctly determines that it has an infinite size (because the "root" type is `A`, and `A` occurs, albeit with different type arguments, as a nested type in `A`). However, when checking `B`, it also recurses into `A`, but now `B` is the root type, and it only checks for _exact_ matches of `A`, but since `A` never precisely contains itself (only `A<A<T>>`, `A<A<A<T>>>`, etc.), an endless recursion ensues until the stack overflows. In this PR, I have attempted to fix this behavior by implementing a two-phase checking: When checking `B`, my code first checks `A` _separately_ and stops if `A` already turns out to be infinite. If not (such as for `Option<T>`), the second phase checks whether the root type (`B`) is ever nested inside itself, e.g.: ```rust struct Foo { x: Option<Option<Foo>> } ``` Special care needs to be taken for mutually recursive types, e.g.: ```rust struct A<T> { z: T, x: B<T>, } struct B<T> { y: A<T> } ``` Here, both `A` and `B` both _are_ `SelfRecursive` and _contain_ a recursive type. The current behavior, which I have maintained, is to treat both `A` and `B` as `SelfRecursive`, and accordingly report errors for both.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
has the following output:
the stack overflow should not happen ^^
The text was updated successfully, but these errors were encountered: