elixirdialyzer

How can I suppress dialyzer warning on comparison between module variable and local static variable?


Dialyzer blames the code trying to match against module variable:

defmodule Main do
  # -> :demo
  @env Application.get_env(:myproject, :env)

  def run do
    case @env do
      :production -> 1
      _ -> 2
    end
  end
end
lib/myproject/main.ex:6:pattern_match
The pattern can never match the type.

Pattern:
:production

Type:
:demo

How can I avoid the warning, or should I write as below every time?

  def run do
    env = Application.get_env(:myproject, :env)

    case env do
      ...
    end
  end

Solution

  • should I write as below every time?

    It depends on what are you trying to achieve. dialyzer is smart. Module attributes are compile time beasts, they are computed and replaced everywhere during the compilation time. What gets into BEAM in the snippet above would be:

    defmodule Main do
      def run do
        case :demo do
          :production -> 1
          _ -> 2
        end
      end
    end
    

    That said, dialyzer warns you about an unreachable statement because it analyses the resulting code, with all the macros expanded and module attributes inplaced.

    If you want the different compiled code depending on the environment, you have several approaches.

    1. Explicitly suppress dialyzer warning as described here.
    2. Trick the dialyzer (examples might be found in Elixir core, I would not paste those here because I do not find this solution robust enough.)
    3. Call Application.get_env(:myproject, :env) directly in the case clause (or assign to the local variable as you suggested.)

    The latter approach is IMSO preferrable.