[erlang-bugs] Wrong dialyzer spec for erlang:process_info/2

Kostis Sagonas <>
Fri Oct 19 18:02:47 CEST 2012

On 10/19/2012 05:04 PM, Michał Ptaszek wrote:
> Hey,
> Let's define a function which is supposed to return us a list of links
> for a given process:
> -spec links(pid()) ->  [port() | pid()].
> links(Pid) ->
>      {links, Links} = process_info(Pid, links),
>      Links.
> Now let's run the dialyzer on the beam file:
> dialyzer -Wno_return -Wunderspecs --fullpath --plt .plt pi.beam
>    Checking whether the PLT .plt is up-to-date... yes
>    Proceeding with analysis...
> pi.erl:5: Type specification pi:links(pid()) ->  [port() | pid()] is a
> supertype of the success typing: pi:links(pid()) ->  [pid()]
>   done in 0m1.45s
> done (warnings were emitted)
> However it's clearly not right. For instance:
> ()1>  erlang:process_info(whereis(erl_prim_loader), links).
> {links,[#Port<0.1>,<0.0.0>]}

Ah, the hard-coded type information again. The main problem is that this 
information was obtained by faithfully reading (decrypting?) the 
Erlang/OTP documentation. Sometimes, this documentation specifies only 
half the truth... (Also sometimes, this is done on purpose.)

For example, the published documentation of process_info/2 reads that 
the function returns:
   {links, Pids}
     Pids is a list of pids, with processes to which the process has a link.

(See http://erlang.org/doc/man/erlang.html#process_info-2)

So, it's not so clear whether the fact that it occasionally also returns 
ports as well as pids is to be relied upon in applications or not, 
though most probably it is.

*Aside*: I would suggest to the OTP folks to also correct such 
incomplete inaccurate documentation of the BIFs, not only the specs.

> I wanted to fix it by myself, however could not find the right place
> to apply the patch. Where can I find specs for ERTS BIFs?

In Erlang/OTP R15B02 (and previous) or in 'maint' the hard-coded type 
information is in lib/hipe/cerl/erl_bif_types.erl.  Contrary to what 
Patrik suggested, in most cases it's actually pretty easy to understand 
what's going on.  For example, the relevant line (in 'maint') is 1270. 
It currently reads:

     ['links'] -> t_tuple([InfoItem, t_list(t_pid())]);

Change it to:

     ['links'] -> t_tuple([InfoItem, t_list(t_sup(t_pid(), t_port()))]);

Then on the top-level just issue 'make hipe'.  The next time you try to 
run dialyzer it will automatically find out that the PLT is out of date 
and will rebuild it.


More information about the erlang-bugs mailing list