-
Notifications
You must be signed in to change notification settings - Fork 13
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
Consider the following module:
defmodule Test.TypedGenServer.Stage2.Server do
@spec test :: any()
def test do
:ok
end
end
This module, when type checked with the current master branch (60d7d3f) warns about:
iex(62)> recompile(); Gradient.type_check_file(:code.which( Test.TypedGenServer.Stage2.Server ), [:infer])
Compiling 1 file (.ex)
lib/typed_gen_server/stage2.ex: The spec test/0 on line 79 follows another spec, but only one spec per function clause is allowed
The expanded Erlang AST of the test module is:
iex(64)> Gradient.Debug.erlang_ast(Test.TypedGenServer.Stage2.Server)
{:ok,
[
{:attribute, 78, :file, {'lib/typed_gen_server/stage2.ex', 78}},
{:attribute, 78, :module, Test.TypedGenServer.Stage2.Server},
{:attribute, 78, :compile, [:no_auto_import]},
{:attribute, 79, :spec,
{{:test, 0},
[{:type, 79, :fun, [{:type, 79, :product, []}, {:type, 79, :any, []}]}]}},
{:attribute, 78, :export, [__info__: 1, test: 0]},
{:attribute, 78, :spec,
{{:__info__, 1},
[
{:type, 78, :fun,
[
{:type, 78, :product,
[
{:type, 78, :union,
[
{:atom, 78, :attributes},
{:atom, 78, :compile},
{:atom, 78, :functions},
{:atom, 78, :macros},
{:atom, 78, :md5},
{:atom, 78, :exports_md5},
{:atom, 78, :module},
{:atom, 78, :deprecated}
]}
]},
{:type, 78, :any, []}
]}
]}},
{:function, 0, :__info__, 1,
[
{:clause, 0, [{:atom, 0, :module}], [],
[{:atom, 0, Test.TypedGenServer.Stage2.Server}]},
{:clause, 0, [{:atom, 0, :functions}], [],
[
{:cons, 0, {:tuple, 0, [{:atom, 0, :test}, {:integer, 0, 0}]},
{nil, 0}}
]},
{:clause, 0, [{:atom, 0, :macros}], [], [nil: 0]},
{:clause, 0, [{:atom, 0, :exports_md5}], [],
[
{:bin, 0,
[
{:bin_element, 0,
{:string, 0,
[4, 28, 248, 174, 47, 116, 141, 76, 191, 12, 198, 77, 111, 213,
73, 150]}, :default, :default}
]}
]},
{:clause, 0, [{:match, 0, {:var, 0, :Key}, {:atom, 0, :attributes}}], [],
[
{:call, 0,
{:remote, 0, {:atom, 0, :erlang}, {:atom, 0, :get_module_info}},
[{:atom, 0, Test.TypedGenServer.Stage2.Server}, {:var, 0, :Key}]}
]},
{:clause, 0, [{:match, 0, {:var, 0, :Key}, {:atom, 0, :compile}}], [],
[
{:call, 0,
{:remote, 0, {:atom, 0, :erlang}, {:atom, 0, :get_module_info}},
[{:atom, 0, Test.TypedGenServer.Stage2.Server}, {:var, 0, :Key}]}
]},
{:clause, 0, [{:match, 0, {:var, 0, :Key}, {:atom, 0, :md5}}], [],
[
{:call, 0,
{:remote, 0, {:atom, 0, :erlang}, {:atom, 0, :get_module_info}},
[{:atom, 0, Test.TypedGenServer.Stage2.Server}, {:var, 0, :Key}]}
]},
{:clause, 0, [{:atom, 0, :deprecated}], [], [nil: 0]}
]},
{:function, 80, :test, 0, [{:clause, 80, [], [], [{:atom, 0, :ok}]}]}
]}
That is, there are two @spec attributes following after each other, which is not consistent with the new check. This probably stems from the fact that the Elixir compiler injects __info__ and its spec just after all other attributes and before any functions, i.e. exactly after the first explicit spec in the module (which is an attribute), but before the function the spec corresponds to.
We have to find a workaround for the spec check as this is going to be a common problem :|
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working