<div dir="ltr"><div>Hi Kostis,</div><div><br></div><div>Thanks for the quick and helpful response! Glad I'm not crazy after all :). That all makes sense, and in my original use case that uncovered this, I'm fine with just commenting out the unused code for now.</div><div><br></div><div>I also just uncovered a related(?) issue, in case anyone is interested: in my example code, I found that changing #b{} to #a{} in the call to add_element actually causes Dialyzer to crash. Here's the error message:</div><div><br></div><div><font face="monospace, monospace">Proceeding with analysis...{"init terminating in do_boot",{function_clause,[{dialyzer,message_to_string,[{opaque_match,["pattern <{'b', Queue}, Key, Value>","<#a{d::dict:dict(_,_)},'my_key','my_value'>"]}],[{file,"dialyzer.erl"},{line,310}]},{dialyzer,format_warning,2,[{file,"dialyzer.erl"},{line,300}]},{dialyzer_cl,'-print_warnings/1-lc$^0/1-0-',2,[{file,"dialyzer_cl.erl"},{line,818}]},{dialyzer_cl,print_warnings,1,[{file,"dialyzer_cl.erl"},{line,818}]},{dialyzer_cl,return_value,2,[{file,"dialyzer_cl.erl"},{line,715}]},{dialyzer_cl,do_analysis,4,[{file,"dialyzer_cl.erl"},{line,405}]},{dialyzer,'-cl/1-fun-0-',1,[{file,"dialyzer.erl"},{line,153}]},{dialyzer,doit,1,[{file,"dialyzer.erl"},{line,243}]}]}}</font></div><div><br></div><div>I'm tempted to try and debug this myself, but I'm not sure I have the necessary skills and background to safely make changes to a tool like Dialyzer. Figured I should leave this one to the experts ;). (Though if anyone with more experience than myself would like to point me in the right direction, I suppose I could take a stab at it - I just don't want to accidentally end up breaking something I don't understand.)</div><div><br></div><div>Anyway, thanks again!</div><div>Nick</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 17, 2017 at 6:07 PM, Kostis Sagonas <span dir="ltr"><<a href="mailto:kostis@cs.ntua.gr" target="_blank">kostis@cs.ntua.gr</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On 01/17/2017 11:18 PM, Nick Marino wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I recently encountered a rather strange, unexpected Dialyzer error. I'm<br>
unsure if this might be considered a Dialyzer bug, or if I'm just<br>
missing some key piece of knowledge that would help me understand what's<br>
going on here.<br>
<br>
I took the code that generated the warning and pruned it down down to this:<br>
<br>
-module(opaque_weirdness).<br>
-export([public_func/0]).<br>
<br>
-record(a, {<br>
d = dict:new() :: dict:dict()<br>
}).<br>
<br>
-record(b, {<br>
q = queue:new() :: queue:queue()<br>
}).<br>
<br>
public_func() -><br>
add_element(#b{}, my_key, my_value).<br>
<br>
add_element(#a{d = Dict}, Key, Value) -><br>
dict:store(Key, Value, Dict);<br>
add_element(#b{q = Queue}, Key, Value) -><br>
queue:in({Key, Value}, Queue).<br>
<br>
Which yields the following warning when I run it through Dialyzer:<br>
<br>
opaque_weirdness.erl:16: The attempt to match a term of type<br>
#b{q::queue:queue(_)} against the pattern {'a', Dict} breaks the<br>
opaqueness of queue:queue(_)<br>
<br>
It seems like this warning is somehow being triggered by the presence of<br>
the unused function clause in add_element. If I modify the code and add<br>
a line to public_func so that we use both clauses, then Dialyzer passes<br>
with no warnings.<br>
</blockquote>
<br></div></div>
Your analysis is pretty correct. The issue is related to dead code and the warning you get is indeed confusing and weird. This should be fixed in dialyzer. Till then, you can suppress it either by commenting the unused first clause, which is dead code in your module, or by exporting function add_element/3.<br>
<br>
<br>
What roughly happens here is that Dialyzer gets confused by the fact that the first clause will not be used and marks its arguments as having the type none(), i.e. not contributing to the inferred success typing. Then the warning pass sees the none() in the first argument of the clause and thinks it has been produced due to the call to add_element being with a record with a different opaque subterm: these opacity violations are also denoted by/resulting in the none() type. But the pattern matching failure is on the #a{} vs. #b{} level, not on their subterms (fields).<br>
<br>
Dialyzer _should_ issue a warning for this line, but the correct warning to issue here is something along the lines of:<br>
<br>
opaque_weirdness.erl:16: The attempt to match a term of type #b{q::queue:queue(_)} against the pattern {'a', Dict} will not succeed<br>
<br>
or that this clause will not be used since the success typing arguments of this function are (#b{}, _, _)<span class="HOEnZb"><font color="#888888"><br>
<br>
Kostis<br>
</font></span></blockquote></div><br></div>