Skip to content

Built-in type struct is incorrectly defined #4915

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

Closed
margnus1 opened this issue Jun 30, 2016 · 7 comments
Closed

Built-in type struct is incorrectly defined #4915

margnus1 opened this issue Jun 30, 2016 · 7 comments
Assignees

Comments

@margnus1
Copy link
Contributor

The type of the struct built-in type is, as defined in lib/elixir/src/elixir.erl, #{'__struct__' => atom()}. This type does not match any struct values, however, as all structs contain keys that are not :__struct__, and as of OTP 19 Dialyzer is capable of recognising this, causing spurious warnings for Elixir projects that use the struct type.

A correct definition would be #{'__struct__' := atom(), atom() => any()}. If OTP 17&18 compatibility is required, the much weaker variant #{'__struct__' => atom(), atom() => any()} can be used, but I would implore the Elixir team to use version detection in order to get the stronger variant when compiled with OTP 19, as the weaker variant is almost indistinguishable from #{atom() => any()}.

The problematic type seems to have also propagated to Exception.t, causing one of the two test failures in Kernel.DialyzerTest, (number 4 as reported in #4851).

Environment

  • Elixir version (elixir -v): 1.3.1 on OTP 19
  • Operating system: GNU/Linux

Current behavior

Dialyzing the following module yields a dialyzer warning on good/0, but not on bad/0.

defmodule Repro do
    defstruct field: :default

    @spec good() :: struct
    def good() do
        %__MODULE__{}
    end

    @spec bad() :: struct
    def bad() do
        %{}
    end
end

Expected behavior

A dialyzer warning on bad/0, no warnings on good/0.

@whatyouhide
Copy link
Member

I think we can have conditional type for structs based on the Erlang version. If there's agreement on this, I can look into implementing it.

@ericmj
Copy link
Member

ericmj commented Jun 30, 2016

Thanks for the great report @margnus1.

@ericentin
Copy link
Contributor

I'm going to try re-enabling some of those mentioned tests as well now.

@margnus1
Copy link
Contributor Author

@ericmj You're welcome, but I believe you forgot to change the Exception.t type (lib/elixir/lib/exception.ex:18). @antipax will probably find that the particular test still fails.

@ericentin
Copy link
Contributor

Yep, I fixed up that type and re-enabled the test, PR incoming.

@ericmj
Copy link
Member

ericmj commented Jun 30, 2016

Should be fixed in 433ff88.

josevalim pushed a commit that referenced this issue Jun 30, 2016
Closes #4915.

Signed-off-by: José Valim <[email protected]>
@ericmj
Copy link
Member

ericmj commented Jun 30, 2016

@josevalim With the platform specific defines is there a chance an elixir build with OTP 19 will not work on OTP 18? Do we want this guarantee and have we followed it in the past? I think 19 itself is backwards compatible with 18 unless you use 19 specific features.

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

No branches or pull requests

4 participants