[erlang-questions] Dialyzer question

Joe Armstrong erlang@REDACTED
Mon Nov 14 11:58:09 CET 2011


Change export_all to

-export([test/0]).

Then you'll get this:

test.erl:8: Function test/0 has no local return
test.erl:9: The pattern {'rec2', _} can never match the type #rec1{}

With export_all the arguments to do_something are totally unconstrained and
can come from
any wild place - so the inferred types are too permissive.

With export_all typer infers the following:

> typer test.erl
%% File: "test.erl"
%% ----------------
-spec test() -> #rec2{}.
-spec do_something(_,fun((_) -> any())) -> any().
-spec map(_) -> #rec1{}.

The (.... any()) -> any() is because the second argument of do_something
can come from anywhere
so there are no type errors

But with -export([test/0]). we get this:

-spec test() -> none().
-spec do_something(1,fun((_) -> #rec1{})) -> #rec1{}.
-spec map(_) -> #rec1{}.


/Joe




On Mon, Nov 14, 2011 at 11:40 AM, Steve Strong <steve@REDACTED> wrote:

>  Hi All,
>
> I have a question on the behaviour of Dialyzer with higher-order
> functions.  Consider the following trivial code:
>
> -module(test).
>
> -compile(export_all).
>
> -record(rec1, {fred}).
> -record(rec2, {harry}).
>
> test() ->
>     #rec2{} = do_something(1, fun map/1).
>
> do_something(Num, MapFun) ->
>     MapFun(Num).
>
> map(_X) ->
>     #rec1{}.
>
> If I run Dialyzer against it, I get no errors or warnings logged, even
> though it's quite apparent that it will fail.  I would have expected that
> Dialyzer could infer that the return type of do_something was the return
> type of MapFun;  within the context of do_something(), that is clearly
> any(), but within the context of test() I would have thought that it could
> see that do_something() is actually going to return a #rec1{} record, that
> being the return type of map().
>
> If I replace the call to MapFun with a call to map(), as in:
>
> do_something(Num, _MapFun) ->
>     map(Num).
>
> Then everything works as expected - Dialyzer correctly tells me that my
> code is broken.  Is there anything I can do to "teach" dialyzer how to
> interpret the MapFun?  It works as I would like with functions such as
> lists:map():
>
> -module(test).
>
> -compile(export_all).
>
> -record(rec1, {fred}).
> -record(rec2, {harry}).
>
> test() ->
>     [#rec2{}] = lists:map(fun map/1, [1]).
>
> map(_X) ->
>     #rec1{}.
>
> With the above, I get the expected warning.  I've looked at lists.erl, and
> it doesn't look to be doing anything different.  It does have some -spec
> directives, but adding those in my code did not appear to help.
>
> Any hints?
>
> Cheers,
>
> Steve
>
> --
> Steve Strong
> @srstrong
>
> Sent with Sparrow <http://www.sparrowmailapp.com/?sig>
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20111114/6d883657/attachment.htm>


More information about the erlang-questions mailing list