Elixir V 1.18 behaviours and different builds warnings

Hello all,

Where I work, we like to inject module dependencies during compile time.
So for example, I can have MyModule for dev and prod builds, but for test I might have MyModuleStub.

So let’s say I have a code like this:

# ...
@the_module Application.compile_env!(:my_app, :the_module)
#...
case @the_module.execute() do
  {:ok, response} -> do_something(response)
  :error -> do_something_else()
end

It works fine in dev and prod, however in test the module is a simplified version:

defmodule MyModuleStub do
# ...
  def execute, do: {:ok, fixture()}
end

Then, when compiling in test, we get the following warning:

     warning: the following clause will never match:

         :error

     because it attempts to match on the result of:

        MyModuleStub.execute()

     which has type:

         none()

     typing violation found at:
     │
     │       :error ->
     │       ~~~~~~~~~~~~~~~~

It seems the compiler warning is right…however, the situation is less than an ideal. Ideally, we should have a way to tell the compiler that we’re talking about a behaviour, or it should understand alone. Is there any way of suppressing this warning? Have you used modules this way? How did you work around for Elixir v1.18 warnings?

I’m not sure how to solve this with the current capabilities, but I think it’s funny that the main complaint about the type system is that it is too smart :grinning:

1 Like
1 Like

Thank you. It is what we ended up doing.

Another option, if Process.get(...) is too magical, is to pretend that you can return something else:

if :rand.uniform() >= 0 do
  # always true
  {:ok, ...}
else
  :error
end

Once we add behaviours to the type system, this warning will disappear, but for now we need to rely on one of the following approaches.

3 Likes