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>