Dialyzer on external modules

I’m trying to use dialyzer with an external package, however I’m not sure how to specify the external module.

I’ve tried the following:

defmodule Wrapper.FCM do
  @moduledoc """
    Wrapper for Firebase notifications
  """
  use Pigeon.Dispatcher

  @dialyzer {:nowarn_function, {:push, }}

  @spec send_notification(any, any, any) :: any # temporarily ignoring this spec
  def send_notification(token, title, body) do
    n =
      Pigeon.FCM.Notification.new(
        {
          :token,
          token
        },
        %{
          "title" => title,
          "body" => body
        }
      )

    push(n) 
  end
end

When I call push (which comes from Pigeon), dialyzer prints the following error regardless of trying to ignore it:

The call 'Elixir.Wrapper.FCM':push
         (_n@1 ::
              #{'__meta__' :=
                    #{'__struct__' := 'Elixir.Pigeon.Metadata',
                      'on_response' := 'nil'},
                '__struct__' := 'Elixir.Pigeon.FCM.Notification',
                'android' := 'nil',
                'apns' := 'nil',
                'data' := _,
                'error' := 'nil',
                'fcm_options' := 'nil',
                'name' := 'nil',
                'notification' := _,
                'response' := 'nil',
                'target' :=
                    {'condition', _} | {'token', _} | {'topic', _},
                'validate_only' := 'nil',
                'webpush' := 'nil'}) will never return since it differs in the 1st argument from the success typing arguments: 
         ([#{'__meta__' :=
                 #{'__struct__' := 'Elixir.Pigeon.Metadata',
                   'on_response' :=
                       'nil' | fun((_) -> any()) | {_, _} | {_, _, _}}},
           ...] |
          #{'__meta__' :=
                #{'__struct__' := 'Elixir.Pigeon.Metadata',
                  'on_response' :=
                      'nil' |
                      fun((map()) -> no_return()) |
                      {atom(), atom()} |
                      {atom(), atom(), [any()]}}})

This is using the correct struct, so is this just something wrong with the package? I can ignore the method that calls it, but I want to use dialyzer on it.

If the typespecs of your dependency are somehow messed up your only option is to fix it or ignore the error.

1 Like

Is there a way to ignore the external function/module from dialyzer, like

@dialyzer {:nowarn_function, {:module_name, :function, 1}}

Right now, ignoring my function that calls the external function fixes the error, but I want type safety on that method. I guess I could write a wrapper for the function that takes the same params.

This commit seems highly relevant - it doesn’t appear to be in a released version, unfortunately: