"The guard clause can never succeed" - Dialyzer warning

I have two functions like this:

defp do_rate_match(%{team_count: 2} = match) do
defp do_rate_match(%{team_count: team_count} = match) do

I want to add opts to these functions so I modified them as follows:

defp do_rate_match(%{team_count: 2} = match, opts) do
defp do_rate_match(%{team_count: team_count} = match, opts) do

I want to handle the case where opts is not given so then made another function

  defp do_rate_match(match) do
    if(Map.has_key?(match, :team_count)) do
      do_rate_match(match, [])
    else
      :ok
    end
  end

The check for “if” statement line generates the warning: “The guard clause can never succeed”.

If it helps you can see the files here Pull Request Draft

What can I do to remove the warning?

Looking at the full code, it seems like match is a Match struct which will always have :team_count as a key. Presumably Dialyzer is telling you that the if statement will always be true. If statements are just macros which are expanded into a case statement with a guard, hence the warning.

I’m not sure I understand what the purpose of the has_key? check is. It seems like it would always be true? The function is typed to accept Match.t, but I couldn’t find the definition for the type anywhere (but it matches one of your schemas, which has the key in question).

2 Likes

Dialyzer can infer that do_rate_match is only ever called with a Match - which will always have a team_count key - so Dialyzer is complaining that the else is unreachable.

A cleaner way to handle this would be to use Elixir’s default argument syntax:

defp do_rate_match(match, opts \\ [])
defp do_rate_match(%{team_count: ...etc...}, opts)

The first defp head has no body, but only defines the default for opts.

2 Likes