(Edit: Apologies everyone. I had forgot to make the repository public before posting. The repository is public now, and so the links should now work correctly.)
I am implementing code from the book Functional Web Development with Elixir, OTP, and Phoenix by Lance Halvorsen, which is really good by the way. I am fully typespeccing the project, and I have come across a Dialyzer error that I just can’t figure out. Here is the repository.
The function that it is complaining about is:
def handle_call({:position_island, player_role, island_type, row, column}, _from, state) do
board = player_board(state, player_role)
with {:ok, rules} <- Rules.check(state.rules, {:position_islands, player_role}),
{:ok, coordinate} <- Coordinate.new(row, column),
{:ok, island} <- Island.new(island_type, coordinate),
board <- Board.position_island(board, island_type, island) do
state
|> update_board(player_role, board)
|> update_rules(rules)
|> reply_success(:ok)
else
:error = check_error ->
{:reply, check_error, state}
{:error, :invalid_coordinate} = coordinate_new_error ->
{:reply, coordinate_new_error, state}
{:error, :invalid_island_type} = coordinate_or_island_new_error ->
{:reply, coordinate_or_island_new_error, state}
{:error, :overlapping_island} = position_island_error ->
{:reply, position_island_error, state}
end
end
and the specific line is:
{:ok, island} <- Island.new(island_type, coordinate),
The error reported by Dialyzer is:
lib/islands_engine/game.ex:130:pattern_match
The pattern can never match the type.
Pattern:
{:ok, _island}
Type:
{:error, :invalid_coordinate | :invalid_island_type}
This error is a common one in Dialyzer, and a commonly confusing one. In this context, the error makes zero sense because the entire point of the with
form pattern match clause is to not match the error types Dialyzer is complaining, which are additionally caught below in the else
section.
In my searching to try and figure this out, the consensus seemed to be that the problem wasn’t necessarily here but somewhere else in the call stack. I have tried tracing things down and ensuring that the typespecs made sense, and I haven’t been able to find any issues. I have toggled some things to try and see a different error but with no luck.
This was previously additionally confusing because Dialyzer was complaining about the update_board
function never being called, which was false. It is clearly called above, and this code works and is tested decently. However, that Dialyzer went away at some point. The error I have described above is the only Dialyzer error reported.
Can someone help me debug this or provide any pointers? The code has been developed on Elixir 1.13 and has no dependencies outside of Hex packages. This has me quite confused.