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

Recursive types cause endless loop #40

Open
turion opened this issue Dec 10, 2020 · 4 comments
Open

Recursive types cause endless loop #40

turion opened this issue Dec 10, 2020 · 4 comments

Comments

@turion
Copy link
Contributor

turion commented Dec 10, 2020

Discovered by @evnu.

defmodule IWantToSeeTheWorldBurn do
  @type a :: a
  @spec foo(a) :: a()
  def foo(a) do
    a
  end

  @type forest :: [tree]
  @type tree :: {integer, forest}
  @spec flatten(forest) :: [integer]
  def flatten(forest) do
    Enum.map(forest, fn {int, subforest} -> [int | flatten(subforest)] end)
    |> Enum.concat()
  end
end

The first example is a minimal example that should type check, but hangs. The second one is an actually useful thing people might do in practice.

Like in #39 , the problem is in the treatment of local types. They are evaluated directly, causing an endless loop of variable lookup. Maybe it's possible to stop this by making references to local types lazy. Instead of evaluating them, insert a closure, and only compute it when you need to compare the type spec to something else.

@turion
Copy link
Contributor Author

turion commented Dec 10, 2020

In fact, this issue needs to be solved before ex_type can check itself, since ExType.Type contains mutual recursion.

@turion
Copy link
Contributor Author

turion commented Dec 10, 2020

Maybe it's possible to stop this by making references to local types lazy. Instead of evaluating them, insert a closure, and only compute it when you need to compare the type spec to something else.

Simpler even, the new named types should be added to the context, and there should be a "context reference type" that points to an entry in the context instead of getting that value. Whenever an already known type is encountered, this reference should be returned by eval_type.

@gyson
Copy link
Owner

gyson commented Dec 10, 2020

@turion thanks for creating issues and pull requests!

I will look into them over weekend.

@turion
Copy link
Contributor Author

turion commented Dec 10, 2020

Glad to hear from you :) I'm trying to solve this issue here, but I'm not so sure yet whether I can.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants