Dialyzer warning about nil missing from spec

Hi,

i have these functions

  @spec ai_random_move(board_t()) :: integer()
  def ai_random_move(board) do
    Enum.random(empty_spots(board))
  end

  @spec try_win_move(board_t(), String.t()) :: integer() | nil
  def try_win_move(board, player) do
    Enum.find(empty_spots(board), &winner?(make_move(board, &1, player), player))
  end

  @spec ai_win_move(board_t(), String.t()) :: integer()
  def ai_win_move(board, player) do
    try_win_move(board, player) || ai_random_move(board)
  end

and i am getting a warning from dialyzer

lib/tictactoe_elixir.ex:154:missing_range
The type specification is missing types returned by function.

Function:
TictactoeElixir.ai_win_move/2

Type specification return types:
integer()

Missing from spec:
nil

This does not seem correct to me, as the nil can never actually be returned due to the ||. Is this a shortcoming of dialyzer or am i doing something wrong here?

Cheers
Jan-Eric

If the winner?/2 function returns a truthy value for none of the elements the Enum.find will enumerate, then the Enum.find will return the default value, which is nil by default.

https://hexdocs.pm/elixir/Enum.html#find/2

1 Like

That i get. Thats why the try_win_move function returns integer() | nil.

But that should never make it out of ai_win_move/2 due to the || ai_random_move(board)

Ah, you are right. I misread the function names. Sorry. I don’t know in that case.

I have now asked directly on the otp repo: Dialyzer warning about nil missing from spec · Issue #8717 · erlang/otp · GitHub
But they would need to know what erlang code is produced here. Does anyone know how i can get the transpiled erlang code?

GitHub - michalmuskala/decompile can convert between various representations

Thanks. Confirmed with the otp guys that this is an issue with dialyzer that cant easily be fixed.

3 Likes