How to use dialyzer on linux command line (without mix)?

I’m struggling with dialyzer from linux command line, no mix.

First I have to build PLT but I have no idea what are the needed parameters. I have tried (output edited for readability):

$ dialyzer --build_plt --apps kernel
  Creating PLT /home/jani/.dialyzer_plt ...
Unknown functions:
  atomics:info/1 (erl_erts_errors.erl:68:9)
  beam_lib:chunks/2 (code.erl:872:10)
  beam_lib:md5/1 (code.erl:1082:10)
  binary:decode_unsigned/1 (net_kernel.erl:1754:14)
  binary:match/2 (os.erl:385:10)
[..]
  unicode:latin1_chardata/0 (rpc.erl:1377:16)
 done in 0m9.24s
done (passed successfully)

But it reports huge amount of unknown functions and types. Is that ok?

Anyway the following binary file is created:

$ l ~/.dialyzer_plt 
.rw-rw-r-- 359k jani jani 2023-01-20 11:22 /home/jani/.dialyzer_plt

This is my test code:

defmodule TypeSpecExample do
  @spec add(a :: integer, b :: integer) :: integer
  def add(a, b), do: a + b

  @spec sub(a :: integer, b :: integer) :: integer
  def sub(a, b), do: a - b
end

Compiles fine:

$ elixirc TypeSpecExample.ex 
$ l *TypeSpecExample*
.rwxrwx--- 1,6k root vboxsf 2023-01-20 11:30 Elixir.TypeSpecExample.beam*
.rwxrwx---  190 root vboxsf 2023-01-20 11:13 TypeSpecExample.ex*

When I run dialyzer I get this output telling me nothing but that I don’t know how to use it :frowning:

$ dialyzer Elixir.TypeSpecExample.beam
  Checking whether the PLT /home/jani/.dialyzer_plt is up-to-date... yes
  Proceeding with analysis...=ERROR REPORT==== 20-Jan-2023::11:31:59.637815 ===
Error in process <0.82.0> with exit value:
{undef,
    [{elixir_erl,debug_info,
         [core_v1,'Elixir.TypeSpecExample',
          {elixir_v1,
              #{after_verify => [],attributes => [],compile_opts => [],
                definitions =>
                    [{{sub,2},
                      def,
                      [{line,6}],
                      [{[{line,6}],
                        [{a,[{version,0},{line,6}],nil},
                         {b,[{version,1},{line,6}],nil}],
                        [],
                        {{'.',[{line,6}],[erlang,'-']},
                         [{line,6}],
                         [{a,[{version,0},{line,6}],nil},
                          {b,[{version,1},{line,6}],nil}]}}]},
                     {{add,2},
                      def,
                      [{line,3}],
                      [{[{line,3}],
                        [{a,[{version,0},{line,3}],nil},
                         {b,[{version,1},{line,3}],nil}],
                        [],
                        {{'.',[{line,3}],[erlang,'+']},
                         [{line,3}],
                         [{a,[{version,0},{line,3}],nil},
                          {b,[{version,1},{line,3}],nil}]}}]}],
                deprecated => [],
                file =>
                    <<"/media/sf_src/other/elixir-in-action/TypeSpecExample.ex">>,
                is_behaviour => false,line => 1,
                module => 'Elixir.TypeSpecExample',
                relative_file => <<"TypeSpecExample.ex">>,struct => nil,
                unreachable => []},
              [{attribute,5,spec,
                   {{sub,2},
                    [{type,5,'fun',
                         [{type,5,product,
                              [{ann_type,5,[{var,5,a},{type,5,integer,[]}]},
                               {ann_type,5,[{var,5,b},{type,5,integer,[]}]}]},
                          {type,5,integer,[]}]}]}},
               {attribute,2,spec,
                   {{add,2},
                    [{type,2,'fun',
                         [{type,2,product,
                              [{ann_type,2,[{var,2,a},{type,2,integer,[]}]},
                               {ann_type,2,[{var,2,b},{type,2,integer,[]}]}]},
                          {type,2,integer,[]}]}]}}]},
          [no_copt,to_core,binary,return_errors,no_inline,strict_record_tests,
           strict_record_updates,dialyzer,no_spawn_compiler_process]],
         []},
     {dialyzer_utils,get_core_from_beam,2,
         [{file,"dialyzer_utils.erl"},{line,119}]},
     {dialyzer_analysis_callgraph,compile_byte,5,
         [{file,"dialyzer_analysis_callgraph.erl"},{line,419}]},
     {dialyzer_worker,loop,2,[{file,"dialyzer_worker.erl"},{line,90}]}]}


dialyzer: Analysis failed with error:
{undef,
    [{elixir_erl,debug_info,
         [core_v1,'Elixir.TypeSpecExample',
          {elixir_v1,
              #{after_verify => [],attributes => [],compile_opts => [],
                definitions =>
                    [{{sub,2},
                      def,
                      [{line,6}],
                      [{[{line,6}],
                        [{a,[{version,0},{line,6}],nil},
                         {b,[{version,1},{line,6}],nil}],
                        [],
                        {{'.',[{line,6}],[erlang,'-']},
                         [{line,6}],
                         [{a,[{version,0},{line,6}],nil},
                          {b,[{version,1},{line,6}],nil}]}}]},
                     {{add,2},
                      def,
                      [{line,3}],
                      [{[{line,3}],
                        [{a,[{version,0},{line,3}],nil},
                         {b,[{version,1},{line,3}],nil}],
                        [],
                        {{'.',[{line,3}],[erlang,'+']},
                         [{line,3}],
                         [{a,[{version,0},{line,3}],nil},
                          {b,[{version,1},{line,3}],nil}]}}]}],
                deprecated => [],
                file =>
                    <<"/media/sf_src/other/elixir-in-action/TypeSpecExample.ex">>,
                is_behaviour => false,line => 1,
                module => 'Elixir.TypeSpecExample',
                relative_file => <<"TypeSpecExample.ex">>,struct => nil,
                unreachable => []},
              [{attribute,5,spec,
                   {{sub,2},
                    [{type,5,'fun',
                         [{type,5,product,
                              [{ann_type,5,[{var,5,a},{type,5,integer,[]}]},
                               {ann_type,5,[{var,5,b},{type,5,integer,[]}]}]},
                          {type,5,integer,[]}]}]}},
               {attribute,2,spec,
                   {{add,2},
                    [{type,2,'fun',
                         [{type,2,product,
                              [{ann_type,2,[{var,2,a},{type,2,integer,[]}]},
                               {ann_type,2,[{var,2,b},{type,2,integer,[]}]}]},
                          {type,2,integer,[]}]}]}}]},
          [no_copt,to_core,binary,return_errors,no_inline,strict_record_tests,
           strict_record_updates,dialyzer,no_spawn_compiler_process]],
         []},
     {dialyzer_utils,get_core_from_beam,2,
         [{file,"dialyzer_utils.erl"},{line,119}]},
     {dialyzer_analysis_callgraph,compile_byte,5,
         [{file,"dialyzer_analysis_callgraph.erl"},{line,419}]},
     {dialyzer_worker,loop,2,[{file,"dialyzer_worker.erl"},{line,90}]}]}
Last messages in the log cache:
  Reading files and computing callgraph...

You should not worry about such things. I would recommend to use dialyxir package instead. It contains a mix task, so that with one call everything is done for you. Also if you do not understand something there is a separate mix task to explain specific error. Unfortunately I have no idea about using it in iex. Maybe check it’s documentation.

If this is the reality I guess I’ll have to postpone studying typespecs after I have some idea how to use mix. I’m currently just compiling my Elixir-in-Action code snippets with elixirc (with a help of make) and running code in iex.

Is there a reason to avoid using mix? I believe you can run mix tasks within an iex session, though I’m not able to double check this at the moment.
You can try this: From the root directory of your application run iex -S mix. If you have dialyxir in your dependencies you should then be able to run Mix.Task.run "dialyzer" to see the analysis.

For fun I asked chatGPT:

2 Likes

No, there is no reason to avoid mix - this is just about the learning path. I just thought one could use dialyzer in the similar fashion than I can use elixirc for small code snippets but that seems not to be the case. I have now rescheduled introduction to dialyzer after mix.

I guess this was a XY problem - Wikipedia.

I get the sentiment but hear it from us: mix is very much expected and is the trodden path when working with Elixir. Don’t piss against the wind and you will make your learning much smoother.

1 Like

Just wanted to follow up that I did test out running dialyzer in iex with mix and it works. Slow on my machine the first time I ran it but it works.