Skip to content
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

Gradualizer may fall into infinite loop for recursive types. #322

Closed
ilya-klyuchnikov opened this issue Mar 25, 2021 · 5 comments
Closed

Comments

@ilya-klyuchnikov
Copy link
Collaborator

ilya-klyuchnikov commented Mar 25, 2021

A repro:

-module(recursive_types).

-compile([export_all, nowarn_export_all]).

-type rec1(A) :: A | {rec, rec1(A)}.

-spec unwrap(rec1(rec1(atom()))) -> rec1(atom()).
unwrap({rec, Z}) -> Z.

This goes into loop:

./bin/gradualizer recursive_types.erl
@ilya-klyuchnikov ilya-klyuchnikov changed the title Gradualizer may falls into infinite loop for recursive types. Gradualizer may fall into infinite loop for recursive types. Mar 25, 2021
@gomoripeti
Copy link
Collaborator

very nice minimal example
This reminds me of #135, apparently the cache did not solve all cases :(

@ilya-klyuchnikov ilya-klyuchnikov linked a pull request Mar 27, 2021 that will close this issue
josefs added a commit that referenced this issue Mar 29, 2021
Given a recursive type, typechecker:normalize() can recurse forever if
we don't take care to stop the recursion. This patch adds a set to
keep track of the types that `normalize` has unfolded so far and stops
unfolding if asked to normalize a type that has already been unfolded.

Ilya identified the problem with recursives types in #322 and offered
a nice example program to demonstrate the problem.

Fixes #322 although the program is still not accepted as it should be
so I'm adding it to the known problems.
@mheiber
Copy link

mheiber commented Apr 12, 2021

Not sure if a similar example has been covered already, but I'm seeing an infinite loop with the following code:

-module(sample).
-compile([export_all]).

-type t() :: t().

-spec main() -> t().
main() -> ok.

tested with 208f5816b0157f282212fc036ba7560f0822f9fc (master)

@zuiderkwast
Copy link
Collaborator

zuiderkwast commented Apr 12, 2021

@mheiber thanks for this example. I think it's a different issue. Types can refer to itself inside a tuple etc. but it's not allowed to be recursive on the top level, so we should detect it and give an error for this.

@zuiderkwast
Copy link
Collaborator

Separate please (unless you think it will be solved by the same fix??)

@mheiber
Copy link

mheiber commented Apr 12, 2021

Separate please (unless you think it will be solved by the same fix??)

I think both issues have to do with checking subtype or type equivalence for recursive types–I suspect they will have a common solution.

erszcz pushed a commit to erszcz/Gradualizer that referenced this issue Oct 15, 2021
Given a recursive type, typechecker:normalize() can recurse forever if
we don't take care to stop the recursion. This patch adds a set to
keep track of the types that `normalize` has unfolded so far and stops
unfolding if asked to normalize a type that has already been unfolded.

Ilya identified the problem with recursives types in josefs#322 and offered
a nice example program to demonstrate the problem.

Fixes josefs#322 although the program is still not accepted as it should be
so I'm adding it to the known problems.
erszcz pushed a commit to erszcz/Gradualizer that referenced this issue Nov 5, 2021
Given a recursive type, typechecker:normalize() can recurse forever if
we don't take care to stop the recursion. This patch adds a set to
keep track of the types that `normalize` has unfolded so far and stops
unfolding if asked to normalize a type that has already been unfolded.

Ilya identified the problem with recursives types in josefs#322 and offered
a nice example program to demonstrate the problem.

Fixes josefs#322 although the program is still not accepted as it should be
so I'm adding it to the known problems.
erszcz pushed a commit to erszcz/Gradualizer that referenced this issue Nov 14, 2021
Given a recursive type, typechecker:normalize() can recurse forever if
we don't take care to stop the recursion. This patch adds a set to
keep track of the types that `normalize` has unfolded so far and stops
unfolding if asked to normalize a type that has already been unfolded.

Ilya identified the problem with recursives types in josefs#322 and offered
a nice example program to demonstrate the problem.

Fixes josefs#322 although the program is still not accepted as it should be
so I'm adding it to the known problems.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants