We've recently been getting the upcoming release of Disco to go through the Dialyzer wringer, and it has been a very useful exercise.  Thanks to Kostis' helpful wielding of the cluebat at the SF Erlang Factory!<div>
<br></div>
<div>We are trying to understand the following output (I hope the inline code pasting below comes out readable):</div><div><br></div><div>$ cat dial.erl</div><div><div>-module(dial).</div><div>-export([abort/2, extract/2,</div>

<div>         diskspace/1, monitor_diskspace/2, refresh_tags/1, monitor_launch/0]).</div><div><br></div><div>% We have helper functions like this:</div><div>abort(Msg, Code) -></div><div>    error_logger:warning_report(Msg),</div>

<div>    exit(Code).</div><div>% which give rise to the following dialyzer message:</div><div>%</div><div>%   Function abort/2 only terminates with explicit exception</div><div>% How do we interpret this message?</div><div>

<br></div><div><br></div><div>% Even with a plt that includes stdlib, there is no warning for the</div><div>% following code:</div><div>-spec extract(binary(), nonempty_string()) -> 'ok'.</div><div>extract(Pack, Dir) -></div>

<div>    case zip:extract(Pack, [{cwd, Dir}]) of</div><div>        {ok, Files} -></div><div>            Files;</div><div>        {error, Reason} -></div><div>            exit({error, Reason})</div><div>    end.</div>

<div><br></div><div><br></div><div>% Here, the spawn_link of monitor_diskspace in monitor_launch() gives:</div><div>%   The created fun has no local return</div><div>% whereas the spawn_link of refresh_tags doesn't.  If the spawn_link</div>

<div>% of monitor_diskspace() function is commented out, there is no</div><div>% warning.  It's not clear how to interpret the warning or the</div><div>% inconsistency.</div><div><div>%</div><div>% Converting the nested list comprehension in monitor_diskspace into a</div>

<div>% list:map made the warning go away, at the expense of readability and</div><div>% perhaps even efficiency.</div></div><div><br></div><div>-type diskinfo() :: {non_neg_integer(), non_neg_integer()}.</div><div>-spec diskspace(nonempty_string()) -> {'ok', diskinfo()} | {'error', term()}.</div>

<div>diskspace(Path) -></div><div>    case Path of</div><div>        "a" -> {ok, {0,0}};</div><div>        _ -> {error, error}</div><div>    end.</div><div><br></div><div>-spec monitor_diskspace(nonempty_string(),</div>

<div>                        [{diskinfo(), nonempty_string()}]) -></div><div>                               no_return().</div><div>monitor_diskspace(Root, Vols) -></div><div>    Df = fun(VolName) -></div><div>                 diskspace(filename:join([Root, VolName]))</div>

<div>         end,</div><div>    NewVols = [{Space, VolName}</div><div>               || {VolName, {ok, Space}}</div><div>                      <- [{VolName, Df(VolName)}</div><div>                          || {_OldSpace, VolName} <- Vols]],</div>

<div>    monitor_diskspace(Root, NewVols).</div><div><div><br></div><div>-spec refresh_tags(nonempty_string()) -></div><div>    no_return().</div><div>refresh_tags(Root) -></div><div>    {ok, _} = diskspace(Root),</div>

<div>    refresh_tags(Root).</div><div><br></div><div>monitor_launch() -></div><div>    spawn_link(fun() -> refresh_tags("abc") end),</div><div>    spawn_link(fun() -> monitor_diskspace("root", [{{0,0}, "a"}]) end).</div>

</div></div><div><br></div><div>$ dialyzer --get_warnings -Wunmatched_returns -Werror_handling dial.erl </div><div>  Checking whether the PLT /home/mundkur/.dialyzer_plt is up-to-date... yes</div><div>  Proceeding with analysis...</div>

<div>dial.erl:6: Function abort/2 only terminates with explicit exception</div><div>dial.erl:66: The created fun has no local return</div><div><br></div><div><div>
<div>$ dialyzer -v </div><div>Dialyzer version v2.4.0</div></div><div><br></div><div>$ erl   </div><div>Erlang R14B01 (erts-5.8.2) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]</div></div>