Erlang (Elixir) Dialyzer - confusing supertype error

Viewed 549

I have defined an Elixir behaviour X. A callback start_link is spec'ed as:

@callback start_link(
  args :: producer_args,
  opts :: GenServer.options
) :: GenServer.on_start

where producer_args type is defined as:

@type producer_args :: %{job_queue_name: String.t}

In the client code Y that implements the behaviour, start_link is defined as:

def start_link(args = %{job_queue_name: _job_queue_name, redis_url: _redis_url}, opts) do
  GenStage.start_link(__MODULE__, args, opts)
end

Dialyzer doesn't like it. It says,

(#{'job_queue_name':=_, 'redis_url':=_, _=>_}) 
is not a supertype of 
#{'job_queue_name':=binary()}

Question #1:

In terms of inheritance, subtypes extend supertypes. Therefore, the defined behaviour(X) should be considered supertype. Module implementing the behaviour(Y) should be considered subtype. Apparently Dialyzer should have asked the question:

Is #{'job_queue_name':=binary()} a supertype of (#{'job_queue_name':=_, 'redis_url':=_, _=>_})?

Rather it asks the question the other way around. Why?

Question #2:

Is the definition of supertype in dialyzer the same as in discussion of OOP inheritance? If not, what is it then? I tried to find definition of supertype in the context of dialyzer but found none.

2 Answers
Related