elixir-lang/elixir

Dynamic module function call leads to compiler warning

Closed this issue · 1 comments

Elixir and Erlang/OTP versions

Tested with two versions:

Erlang/OTP 27 [erts-15.2.7.1] [source] [64-bit] [smp:24:24] [ds:24:24:10] [async-threads:1] [jit:ns]

Elixir 1.18.4 (compiled with Erlang/OTP 27)
Erlang/OTP 27 [erts-15.2.7.1] [source] [64-bit] [smp:24:24] [ds:24:24:10] [async-threads:1] [jit:ns]

Elixir 1.20.0-dev (90e1826) (compiled with Erlang/OTP 27)

Operating system

Debian 13 (Trixie)

Current behavior

Using function calls with a dynamic module name returned by a function and one of the values can be nil, even if you prevent a call of nil.function(), the compiler emits a warning.

Example code:

defmodule Test do
  defmodule Ret do
    def get_data(), do: 4
  end
  
  def call(client) do
    case get_client(client) do
      nil -> :error
      mod -> mod.get_data()
    end
  end
  
  defp get_client("ret"), do: __MODULE__.Ret
  defp get_client(_), do: nil
end

Warning:

warning: nil.get_data/0 is undefined (module nil is not available or is yet to be defined)
└─ iex:9: Test.call/1

The case that get_data/0 will be called with the module nil is impossible and thus no warning should be emitted.

Current workaround to prevent a warning is using a private function to actually call the function using a dynamic module name.

Expected behavior

No warning should be emitted.

Thank you. This is a known bug which will be solved once we make the type system smarter. You can track progress here: #14558.

Another option is to return {:ok, mod} | :error instead of nil.