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
I’m also encountering a similar issue in my ExUnit tests.
For example, I have tests like this:
defmodule MyApp.MyTest do
use ExUnit.Case, async: true
setup do
foo = produce_test_data(1, 2, 3)
bar = produce_test_data(4, 5, 6)
refute match?(^foo, bar)
end
test "..." do
# use foo and bar in interesting ways
end
end
It fails on that refute with:
warning: the following clause will never match:
^foo
because it attempts to match on the result of:
right
which has type:
dynamic(%MyStruct{...omitted...})
where "foo" was given the type:
dynamic(%MyStruct{...omitted...})
Now, I know that that refute line is useless. I’m setting up foo and bar to be the same type but with different values, I know that. But the refute is living documentation. It basically tells readers of the code “hey, these two things are meant to be different, that’s important”.
I guess I wish that there was support for magic comments to disable these warnings.
My solution, at the moment, is to pull that bit of test setup verification out of setup and into its own test:
test "verify test setup", %{foo: foo, bar: bar} do
refute match? ^foo, bar
end