Description
Elixir and Erlang/OTP versions
Erlang/OTP 26 [erts-14.2.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]
Elixir 1.17.1 (compiled with Erlang/OTP 26)
Operating system
MacOS
Current behavior
Given the code below:
defmodule Test do
def tester do
list = [:a]
if is_list(list) do
hd(list)
else
list.()
end
end
end
I get the following type warning even though the block that would trigger it cannot be hit given the if
clause:
warning: incompatible types in expression:
list
expected type:
fun()
but got type:
non_empty_list()
where "list" was given the type:
# type: non_empty_list()
# from: lib/assertions.ex:7
list = [:a]
typing violation found at:
│
11 │ list.()
│ ~
│
└─ lib/assertions.ex:11:7: Assertions.tester/0
I know the probable solution to this simple reproduction is "don't do that" since in this simple case there's no need for the check and it's functionally warning about an unused branch of logic, but this reproduction stems from the type errors I'm getting with Elixir 1.17.1 in my assertions
library where I use a similar check to see which of the two supported APIs is being used.
This seems like a pretty narrow issue due only to the fact that this is a macro expansion, and so the "unused" branch of the if/else
condition is being inlined and the type checker sees this as "unused" in each test in which the macro is being used and raising the type warning.
Is there a way to make the type checker happy here? I can assume that I would need to check the type of the argument passed to the macro before returning the quoted AST so I can return only the correct AST for the given type, but I also don't think that is possible now, is it?
Expected behavior
No warning is given from "unreachable" code paths for a given data type.