17.0 : dialyzer issue on boolean type in record.

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

17.0 : dialyzer issue on boolean type in record.

PAILLEAU Eric
Hi,
please considere below minimal module :
---8<----------------------------------------------------
-module(test).

-export([test/0]).

-record(test, { bool   = 'true' :: boolean()} ).

test() -> test(#test{}).

test(R) -> case R#test.bool of
                 true  -> ok ;
                 false -> ok
            end.
---8<----------------------------------------------------
dialyzer raise an error :

test.erl:11: The pattern 'false' can never match the type 'true'.

Looks like dialyzer considere #test.bool to be of type 'true' while it
is of type boolean() and default value to 'true'.

Documentation says :
"In the presence of initial values for fields, the type must be declared
after the initialization as in the following:

   -record(rec, {field1 = [] :: Type1, field2, field3 = 42 :: Type3}).

Naturally, the initial values for fields should be compatible with (i.e.
a member of) the corresponding types. "


A bug, isn't it ?

Regards.

_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Reply | Threaded
Open this post in threaded view
|

Re: 17.0 : dialyzer issue on boolean type in record.

Steve Vinoski-2



On Mon, Jul 28, 2014 at 5:56 PM, PAILLEAU Eric <[hidden email]> wrote:
Hi,
please considere below minimal module :
---8<----------------------------------------------------
-module(test).

-export([test/0]).

-record(test, { bool   = 'true' :: boolean()} ).

test() -> test(#test{}).

test(R) -> case R#test.bool of
                true  -> ok ;
                false -> ok
           end.
---8<----------------------------------------------------
dialyzer raise an error :

test.erl:11: The pattern 'false' can never match the type 'true'.

Looks like dialyzer considere #test.bool to be of type 'true' while it is of type boolean() and default value to 'true'.

Documentation says :
"In the presence of initial values for fields, the type must be declared after the initialization as in the following:

  -record(rec, {field1 = [] :: Type1, field2, field3 = 42 :: Type3}).

Naturally, the initial values for fields should be compatible with (i.e. a member of) the corresponding types. "


A bug, isn't it ?

I don't think it's a bug since the only way test/1 can be called is via test/0, and the latter passes a #test{} record instance containing only default values. In this case, the default value of the bool field is true, so dialyzer is correct that false can never match.

--steve

_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Reply | Threaded
Open this post in threaded view
|

Re: 17.0 : dialyzer issue on boolean type in record.

PAILLEAU Eric
In reply to this post by PAILLEAU Eric
Hi Steve,

dialyzer is right, yes, in a sens, because the default value is not
dynamically set, but what about below code ?

dialyzer raise an error, because too smart, probably,
while code is valid...

This indeed imply to only set the type and not default value...
Regards.

---8<----------------------------------------------------
-module(test).

-export([test/0]).

-ifdef(TEST).
-record(test, { bool   = 'true' :: boolean()} ).
-else.
-record(test, { bool   = 'false' :: boolean()} ).
-endif.

test() -> test(#test{}).

test(R) -> case R#test.bool of
                 true  -> true ;
                 false -> false
            end.
---8<----------------------------------------------------
_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Reply | Threaded
Open this post in threaded view
|

Re: 17.0 : dialyzer issue on boolean type in record.

Ulf Wiger-6

Dialyzer doesn’t consider ifdef alternatives in its analysis. The default mode is to analyze (debug-)compiled code, in which the ifdefs have already been resolved. You can tell dialyzer to start from the source code, but then, you need to provide values for the defines, using the -D flag*. See the dialyzer man page for details.

BR,
Ulf W

* For it to work otherwise, dialyzer would have to use its own preprocessor. As it is, dialyzer uses the standard compiler (using the undocumented option combo [to_pp, binary | _] to compile:file/2), and thus never sees the defines.

On 29 Jul 2014, at 00:34, PAILLEAU Eric <[hidden email]> wrote:

> Hi Steve,
>
> dialyzer is right, yes, in a sens, because the default value is not dynamically set, but what about below code ?
>
> dialyzer raise an error, because too smart, probably,
> while code is valid...
>
> This indeed imply to only set the type and not default value...
> Regards.
>
> ---8<----------------------------------------------------
> -module(test).
>
> -export([test/0]).
>
> -ifdef(TEST).
> -record(test, { bool   = 'true' :: boolean()} ).
> -else.
> -record(test, { bool   = 'false' :: boolean()} ).
> -endif.
>
> test() -> test(#test{}).
>
> test(R) -> case R#test.bool of
>                true  -> true ;
>                false -> false
>           end.
> ---8<----------------------------------------------------
> _______________________________________________
> erlang-bugs mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-bugs

Ulf Wiger, Co-founder & Developer Advocate, Feuerlabs Inc.
http://feuerlabs.com



_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Reply | Threaded
Open this post in threaded view
|

Re: 17.0 : dialyzer issue on boolean type in record.

Kostis Sagonas-2
In reply to this post by PAILLEAU Eric
On 07/29/2014 01:34 AM, PAILLEAU Eric wrote:
> Hi Steve,
>
> dialyzer is right, yes, in a sens, because the default value is not
> dynamically set, but what about below code ?
>
> dialyzer raise an error, because too smart, probably,
> while code is valid...

What you are experiencing (in your previous example) is due to your
test/1 function being module local, which allows dialyzer to infer that
all calls to it will be with a particular boolean value, not both.
Simply export it and the warning will disappear.  If you want to have it
module local then what dialyzer tells you is that you can simplify its
code by taking out one clause of the case statement.

In the program you show below, dialyzer is also right. The ifdefs are
handled by the preprocessor and ONLY ONE branch is part of the code at
any dialyzer run, not both.

Kostis

> ---8<----------------------------------------------------
> -module(test).
>
> -export([test/0]).
>
> -ifdef(TEST).
> -record(test, { bool   = 'true' :: boolean()} ).
> -else.
> -record(test, { bool   = 'false' :: boolean()} ).
> -endif.
>
> test() -> test(#test{}).
>
> test(R) -> case R#test.bool of
>                  true  -> true ;
>                  false -> false
>             end.
> ---8<----------------------------------------------------
> _______________________________________________
> erlang-bugs mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-bugs

_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs