Why does dialyzer not recognize functions in dependencies?

In my application I have external dependencies from hex (e.g. UUID) and internal dependencies (from within an umbrella application).

In both instances Dialyzer seems to claim that it cannot find functions that very obviously exist (cause I use them successfully) in any dependency. Umbrella wide dependencies can be found by running dialyzer from the root of the project, but this is still not optimal.

I’m assuming this is because my _build/dev/lib/<app>/ebin folder does not have any beam files outside of my library application (and thus does not have the beam files for dependencies to analyze) but is there any way around this? I would like to have dialyzer make sure I am using libraries correctly.

Depending on how you use dialyzer, dependencies should be picked up automatically. The packages :dialyxir and :dialyze both are able to, while using dialyzer from command line can’t know of any dependencies. It does not even know about the _build-folders-structure. Historically dialyzer does only know about a single ebin folder. For more you have to specifiy additional directorys with -pa (IIRC).

I’ve been using the dialyxer dependency, and running dialyzer by typing mix dialyzer. Is there some more proper way to run it?

Looking at that wiki page again, I noticed there’s a way to add a new folder for search path, but it seems odd that I would have to manually specify every dependency’s folder for each subproject (both umbrella and non-umbrella application) just to get full dialyzer coverage.

Please see https://github.com/jeremyjh/dialyxir#paths.

dialyxir seems currently not able to “see” your deps automatically.

Dialyxir will add your dependencies to the PLT if you tell it to.

In your mix.exs, set plt_add_deps: true.

e.g.

def project do
 [ app: :my_app,
   version: "0.0.1",
   deps: deps,
   dialyzer: [plt_add_deps: true]
 ]
end

Then rebuild your PLT with mix dialyzer.plt

2 Likes

Hello. I am in an umbrella project, and I have the following mix.exs file:

defmodule SpecialApp.Mixfile do
  use Mix.Project

  def project do
    [apps_path: "apps",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps,
     dialyzer: [plt_add_deps: true]
   ]
  end

  defp deps do
    []
  end
end

I’ve added the plt_add_deps: true option, but I still have many, many errors like such as:

Unknown Functions: 'Elixir.Plug.Conn':fetch_session/2
Unknown Types: 'Elixir.Ecto.Changset':t/0

P.S. I’ve installed dialyxir globally.

I got it working by using dialyzer: [plt_add_deps: :transitive] in my root mix.exs and running mix dialyzer.plt on the root umbrella project.

1 Like

Hi @KallDrexx,

I tried your suggestion, and I’m getting warnings / errors that I don’t expect. I’ve put some examples below. I wonder if other folks are getting these errors, or if my configuration is wrong somehow. If it is my configuration, I was wondering what I need to do to get rid of the noise. Is the solution simply to ignore the stuff I didn’t write?

Thanks for any help folks.

Unknown types:
  'Elixir.Ecto.Changset':t/0
  'Elixir.Ecto.Query':t/0

Unknown functions:
  'Elixir.Ecto.Adapters.Postgres':'in_transaction?'/1
  'Elixir.Ecto.Adapters.Postgres':rollback/2
  'Elixir.Ecto.Adapters.SQL':query/4
  'Elixir.Ecto.Adapters.SQL':'query!'/4

endpoint.ex:1: The variable _ can never match since previous clauses completely covered the type #{'__struct__':='El...

Hi, this is what we use, add application name for each dependency:

dialyzer: [
        plt_add_deps: :apps_direct,
        plt_add_apps: [
          :ecto,
          :phoenix_pubsub,
          :plug,
          :phoenix_view,
          :timex,
          :decimal,
          :aspire,
          :telemetry,
          :ua_inspector,
          :mix,
          :ex_unit,
          :httpoison,
          :public_key,
          :spandex_phoenix,
          :spandex
        ],
        plt_core_path: "plts",
        plt_local_path: "plts"
      ]

and then:

mix dialyzer --plt