If the code during compile phase conditionally relies on some config, the typing validation would yell at us while compiling. Consider the following code
defmodule TypeTest do
foo = Application.compile_env(:my_app, :param, true)
defp fun(arg) do
case unquote(foo) do
false -> {:error, arg}
true -> {:ok, arg}
end
end
end
the compilation warns out with
warning: the following clause will never match:
false
because it attempts to match on the result of:
true
which has type:
true
Unfortunately, the famous trick to fool dialyzer does not obviously work here.
case :erlang.phash2(1, 1) do
0 -> …
end
Any idea of how I could have this warning suppressed? In my opinion, the above is more or less common usecase and the warning there is unlikely helpful.
Apparently, at the time being this shuts the type checker up:
defmodule TypeTest do
foo = Application.compile_env(:my_app, :param, true)
defp fun(arg) do
case [unquote(foo), not unquote(foo)] do
[false, true] -> {:error, arg}
[true, false] -> {:ok, arg}
end
end
end
This happens, because the list in the question becomes non_empty_list(boolean()). Just matching [foo] won’t work because the latter has a type non_empty_list(true).
You can also not generate the unreachable branches to begin with.
defmodule TypeTest do
foo = Application.compile_env(:my_app, :param, true)
if foo do
defp fun(arg), do: {:error, arg}
else
defp fun(arg), do: {:ok, arg}
end
end
I ran into this today, and the way I solved it was to move the logic from a module attribute using compile_env to an inner-function call using Application.get_env.
# Old way
defmodule MyApp.SomeModule do
@debug Application.compile_env(:my_app, [__MODULE__, :debug], false)
def debug?, do: @debug
end
# New way
defmodule MyApp.SomeModule do
def debug? do
Application.get_env(:my_app, [__MODULE__, :debug], false)
end
end
Yeah, but that’s not the isomorphic approach, because in the not-so-contrived example the code might rely on @debug value during compile time all the turtles down.