[erlang-bugs] Wrong dialyzer spec for erlang:process_info/2
Kostis Sagonas
kostis@REDACTED
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:
> (mynode@REDACTED)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.
Kostis
More information about the erlang-bugs
mailing list