Dialyzer warning when returning a prolist

Paulo Zulato paulozulato@REDACTED
Tue May 18 15:36:19 CEST 2021


Hi, Fred and Stanislav,

Thank you for your replies.
Now I understood why dialyzer is complaining about the underspec return. It
really makes sense.
But I still didn't get why proplists is "working". I've enabled the
*unknown* warning as stated below and I'm using OTP24 and the latest
rebar3. The behaviour is the same with or without the *unknown* warning:

rebar.config:

> {erl_opts, [debug_info]}.
> {deps, []}.
> {dialyzer, [
>    {get_warnings, true},
>    {warnings, [error_handling, underspecs, *unknown*, unmatched_returns]}
> ]}.
>

Source with proplist emulation:

> -module(test).
>
> -export([test/0]).
>
> %% From <https://erlang.org/doc/man/proplists.html>
> -type property() :: atom() | tuple().
> -type proplist() :: [property()].
> -spec test() -> proplist().
> test() ->
>    [
>        {one_test, [a,b,c]},
>        {another_test, [d,e,f]}
>    ].
>

Result:

> ===> Verifying dependencies...
> ===> Analyzing applications...
> ===> Compiling test
> ===> Dialyzer starting, this may take a while...
> ===> Updating plt...
> ===> Resolving files...
> ===> Updating base plt...
> ===> Resolving files...
> ===> Checking 204 files in
> ../../home/pzulato/.cache/rebar3/rebar3_24.0_plt...
> ===> Copying ../../home/pzulato/.cache/rebar3/rebar3_24.0_plt to
> _build/default/rebar3_24.0_plt...
> ===> Checking 204 files in _build/default/rebar3_24.0_plt...
> ===> Doing success typing analysis...
> ===> Resolving files...
> ===> Analyzing 1 files with _build/default/rebar3_24.0_plt...
>
> src/test.erl
> Line 8 Column 2: Type specification test:test() -> proplist() is a
> supertype of the success typing: test:test() -> [{'another_test',['d' |
> 'e' | 'f',...]} | {'one_test',['a' | 'b' | 'c',...]},...]
> ===> Warnings written to _build/default/24.0.dialyzer_warnings
> ===> Warnings occurred running dialyzer: 1
>

Source with real proplist:

> -module(test).
>
> -export([test/0]).
>
> -spec test() -> proplists:proplist().
> test() ->
>    [
>        {one_test, [a,b,c]},
>        {another_test, [d,e,f]}
>    ].
>

Result:

> ===> Verifying dependencies...
> ===> Analyzing applications...
> ===> Compiling test
> ===> Dialyzer starting, this may take a while...
> ===> Updating plt...
> ===> Resolving files...
> ===> Checking 204 files in _build/default/rebar3_24.0_plt...
> ===> Doing success typing analysis...
> ===> Resolving files...
> ===> Analyzing 1 files with _build/default/rebar3_24.0_plt...
>


Do I need to do something else than adding the *unknown* warning into
rebar.config or is it enough?


Best regards,
Paulo Zulato

--
«Quis custodiet ipsos custodes?»


On Tue, 18 May 2021 at 03:50, Stanislav Ledenev <s.ledenev@REDACTED> wrote:

> 1. As I understand underspec and overspec requires precise indication of
> types.
> So for a list of a,b,c atoms you _must_ indicate [a,b,c] but not just a
> list of atoms.
> Because list of atoms implies a list of any size with any atoms not a list
> of 3 specific atoms a,b,c.
>
> 2. The only possible reason why proplists:proplist "works" is that the
> dialyzer
> doesn't know about this type and it is kinda silent in such cases. Try
> -Wunknown option.
>
> пн, 17 мая 2021 г. в 23:25, Paulo Zulato <paulozulato@REDACTED>:
>
>> Hello,
>>
>> I'm trying to figure out why dialyzer is complaining about a function
>> when I don't explicitly declare its return as a proplist.
>> I have this small module which returns a proplist in the form {atom(),
>> [atom()]}:
>>
>>> -module(test).
>>>
>>> -export([test/0]).
>>> test() ->
>>>    [
>>>        {one_test, [a,b,c]},
>>>        {another_test, [d,e,f]}
>>>    ].
>>>
>>
>> For function above, I made the following spec, but dialyzer has
>> complained (as stated below) when I enabled its underspecs warnings.
>>
>>> -spec test() -> [{atom(), [atom()]}].
>>> % src/test.erl
>>> %    Type specification test:test() -> [{atom(),[atom()]}] is a
>>> supertype of the success typing: test:test() -> [{'another_test',['d' | 'e'
>>> | 'f',...]} | {'one_test',['a' | 'b' | 'c',...]},...]
>>>
>>
>> Well... both lists are non-empty lists as stated by dialyzer, so I
>> modified the spec, without success:
>>
>>> -spec test() -> [{atom(), [atom(), ...]}, ...].
>>> %src/test.erl
>>> %   Type specification test:test() -> [{atom(),[atom(),...]},...] is a
>>> supertype of the success typing: test:test() -> [{'another_test',['d' | 'e'
>>> | 'f',...]} | {'one_test',['a' | 'b' | 'c',...]},...]
>>>
>>
>> Then I tried to explicitly declare it as a proplist, and dialyzer has
>> accepted it:
>>
>>> -spec test() -> proplists:proplist().
>>> % OK, no warnings.
>>>
>>
>> As it worked, I tried to do the same as proplists module does and created
>> two types, which I used on my new spec. And, surprisingly, dialyzer has
>> complained about it!
>>
>>> % From <https://erlang.org/doc/man/proplists.html>
>>> -type property() :: atom() | tuple().
>>> -type proplist() :: [property()].
>>>
>>
>>> -spec test() -> proplist().
>>> %src/test.erl
>>>
>> %   Type specification test:test() -> proplist() is a supertype of the
>>> success typing: test:test() -> [{'another_test',['d' | 'e' | 'f',...]} |
>>> {'one_test',['a' | 'b' | 'c',...]},...]
>>>
>>
>> Therefore, I could not understand why declaring the return as
>> "proplists:proplist" is OK while declaring it as lists, nonempty lists or
>> creating the same types as proplists are not OK. Why is dialyzer
>> complaining about the other specs? Is dialyzer handling proplists in a
>> different way? Could someone help me to understand this behaviour?
>>
>>
>> Best Regards,
>> Paulo Zulato
>>
>> --
>> «Quis custodiet ipsos custodes?»
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20210518/60a2af9c/attachment.htm>


More information about the erlang-questions mailing list