Typing violation because of `Application.compile_env/2`

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.

1 Like

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
3 Likes

Indeed, thanks!

1 Like