Change export_all to<br><br>-export([test/0]).<br><br>Then you'll get this:<br><br>test.erl:8: Function test/0 has no local return<br>test.erl:9: The pattern {'rec2', _} can never match the type #rec1{}<br><br>
With export_all the arguments to do_something are totally unconstrained and can come from<br>any wild place - so the inferred types are too permissive.<br><br>With export_all typer infers the following:<br><br>> typer test.erl<br>
%% File: "test.erl"<br>%% ----------------<br>-spec test() -> #rec2{}.<br>-spec do_something(_,fun((_) -> any())) -> any().<br>-spec map(_) -> #rec1{}.<br><br>The (.... any()) -> any() is because the second argument of do_something can come from anywhere<br>
so there are no type errors<br><br>But with -export([test/0]). we get this:<br><br>-spec test() -> none().<br>-spec do_something(1,fun((_) -> #rec1{})) -> #rec1{}.<br>-spec map(_) -> #rec1{}.<br><br><br>/Joe<br>
<br><br><br><br><div class="gmail_quote">On Mon, Nov 14, 2011 at 11:40 AM, Steve Strong <span dir="ltr"><<a href="mailto:steve@srstrong.com">steve@srstrong.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

                <div>
                    Hi All, 
                </div><div><br></div><div>I have a question on the behaviour of Dialyzer with higher-order functions.  Consider the following trivial code:</div><div><br></div><div><div><font style="font-size: 12px;" face="'Courier New'">-module(test).</font></div>
<div><font style="font-size: 12px;" face="'Courier New'"><br></font></div><div><font style="font-size: 12px;" face="'Courier New'">-compile(export_all).</font></div><div><font style="font-size: 12px;" face="'Courier New'"><br>
</font></div><div><font style="font-size: 12px;" face="'Courier New'">-record(rec1, {fred}).</font></div><div><font style="font-size: 12px;" face="'Courier New'">-record(rec2, {harry}).</font></div><div><font style="font-size: 12px;" face="'Courier New'"><br>
</font></div><div><font style="font-size: 12px;" face="'Courier New'">test() -></font></div><div><font style="font-size: 12px;" face="'Courier New'">    #rec2{} = do_something(1, fun map/1).</font></div>
<div><font style="font-size: 12px;" face="'Courier New'"><br></font></div><div><font style="font-size: 12px;" face="'Courier New'">do_something(Num, MapFun) -></font></div><div><font style="font-size: 12px;" face="'Courier New'">    MapFun(Num).</font></div>
<div><font style="font-size: 12px;" face="'Courier New'"><br></font></div><div><font style="font-size: 12px;" face="'Courier New'">map(_X) -></font></div><div><font style="font-size: 12px;" face="'Courier New'">    #rec1{}.</font></div>
<div><font face="'Courier New'"><span style="font-size: 12px;"><br></span></font></div></div>
                <div><div>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().</div>
<div><br></div><div>If I replace the call to MapFun with a call to map(), as in:</div><div><br></div><div><div><font style="font-size: 12px;" face="'Courier New'">do_something(Num, _MapFun) -></font></div><div>
<font style="font-size: 12px;" face="'Courier New'">    map(Num).</font></div></div><div><font style="font-size: 12px;" face="'Courier New'"><br></font></div><div>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():</div>
<div><br></div><div><div><font style="font-size: 12px;" face="'Courier New'">-module(test).</font></div><div><font style="font-size: 12px;" face="'Courier New'"><br></font></div><div><font style="font-size: 12px;" face="'Courier New'">-compile(export_all).</font></div>
<div><font style="font-size: 12px;" face="'Courier New'"><br></font></div><div><font style="font-size: 12px;" face="'Courier New'">-record(rec1, {fred}).</font></div><div><font style="font-size: 12px;" face="'Courier New'">-record(rec2, {harry}).</font></div>
<div><font style="font-size: 12px;" face="'Courier New'"><br></font></div><div><font style="font-size: 12px;" face="'Courier New'">test() -></font></div><div><font style="font-size: 12px;" face="'Courier New'">    [#rec2{}] = lists:map(fun map/1, [1]).</font></div>
<div><font style="font-size: 12px;" face="'Courier New'"><br></font></div><div><font style="font-size: 12px;" face="'Courier New'">map(_X) -></font></div><div><font style="font-size: 12px;" face="'Courier New'">    #rec1{}.</font></div>
</div><div><br></div><div>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.</div>
<div><br></div><div>Any hints?</div><div><br></div><div>Cheers,</div><div><br></div><div>Steve</div><div><br></div><font color="#888888"><div>-- </div>Steve Strong<div>@srstrong</div><div><br>Sent with <a href="http://www.sparrowmailapp.com/?sig" target="_blank">Sparrow</a></div>
<div><br></div></font></div>
            <br>_______________________________________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br>
<br></blockquote></div><br>