Unsettling dialyzer errors

Kostis Sagonas kostis@REDACTED
Sun Feb 28 16:51:47 CET 2021


On 2/28/21 11:39 AM, Josef Svenningsson wrote:
> FWIW, here's what Gradualizer returns for your program:
> 
>     dialyzer_issue.erl: The clause on line 11 at column 1 cannot be reached
>     dialyzer_issue.erl: The clause on line 16 at column 1 cannot be reached
>     dialyzer_issue.erl: The variable on line 20 at column 11 is expected
>     to have type t1() but it has type a | b | x | y
>     -spec foo(t1() | t2()) -> integer().
>     foo(V) ->
>        case f1(V) of
>                ^
>     nok

And the rationale for Gradualizer "expecting" foo/1 to have type t1() as 
argument is what exactly?  Simply that it calls f1/1 ?

Note that expecting/insisting the above is inconsistent both with

  - what the programmer has explicitly declared (i.e., that it has type 
t1() | t2())

and

  - the (erroneous) "expectation" on how the code should work (i.e. that 
[foo(N) || N <- [a, b, c, x, y, z]] evaluates to [1,2,0,3,4,0]) as 
explicitly mentioned below.

Just curious on how one decides that the error is in foo's type spec and 
not in f1/1's or f2/1 (or in both/all, as it is clearly the case here).


Kostis

> 
> On Sat, Feb 27, 2021 at 9:50 AM Nicolas Martyanoff <khaelin@REDACTED 
> <mailto:khaelin@REDACTED>> wrote:
> 
> 
>     Hi,
> 
>     I have come across Dialyzer errors which feel incorrect to me. I
>     managed to reproduce the problem with a minimal example:
> 
>          -module(dialyzer_issue).
> 
>          -export([foo/1]).
> 
>          -type t1() :: a | b.
>          -type t2() :: x | y.
> 
>          -spec f1(t1()) -> {ok, integer()} | error.
>          f1(a) -> {ok, 1};
>          f1(b) -> {ok, 2};
>          f1(_) -> error.
> 
>          -spec f2(t2()) -> {ok, integer()} | error.
>          f2(x) -> {ok, 3};
>          f2(y) -> {ok, 4};
>          f2(_) -> error.
> 
>          -spec foo(t1() | t2()) -> integer().
>          foo(V) ->
>            case f1(V) of
>              {ok, N1} ->
>                N1;
>              error ->
>                case f2(V) of
>                  {ok, N2} ->
>                    N2;
>                  error ->
>                    0
>                end
>            end.
> 
>     The code works as expected:
>     [dialyzer_issue:foo(N) || N <- [a, b, c, x, y, z]] evaluates to
>     [1,2,0,3,4,0].



More information about the erlang-questions mailing list