<div dir="ltr">I was playing a bit with Jesper's example, and I feel Dialyzer behaves very surprisingly and somewhat inconsistently with reporting this kind of problems. Here's my extended test program to illustrate the issues:<div><br><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="monospace">-module(foo).</font></div><div><font face="monospace">-export([foo/0, err/0, errs/0, bar/0, bars/0]).</font></div><div><font face="monospace">-record(foo, {x :: integer()}).</font></div><div><font face="monospace">-record(bar, {x}).</font></div><div><font face="monospace">-type bar() :: #bar{x :: integer()}.</font></div><div><font face="monospace">foo() -></font></div><div><font face="monospace">  [ #foo{x = 0},</font></div><div><font face="monospace">    #foo{x = false} ].</font></div><div><font face="monospace">err() -></font></div><div><font face="monospace">  error(badarg).</font></div><div><font face="monospace">errs() -></font></div><div><font face="monospace">  [ #foo{x = 0},</font></div><div><font face="monospace">    error(badarg) ].</font></div><div><font face="monospace">-spec bar() -> bar().</font></div><div><font face="monospace">bar() -></font></div><div><font face="monospace">  #bar{x = false}.</font></div><div><font face="monospace">-spec bars() -> [bar()].</font></div><div><font face="monospace">bars() -></font></div><div><font face="monospace">  [ #bar{x = 0},</font></div><div><font face="monospace">    #bar{x = false} ].</font></div></blockquote><div><br></div><div>And these are the warnings Dialyzer reports:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="monospace">foo.erl:6: Function foo/0 has no local return</font></div><div><font face="monospace">foo.erl:7: Cons will produce an improper list since its 2nd argument is </font></div><div><font face="monospace">          none()</font></div><div><font face="monospace">foo.erl:8: Record construction </font></div><div><font face="monospace">          #foo{x :: 'false'} violates the declared type of field x ::</font></div><div><font face="monospace">          integer()</font></div><div><font face="monospace">foo.erl:11: Function errs/0 has no local return</font></div><div><font face="monospace">foo.erl:14: Invalid type specification for function foo:bar/0. The success typing is </font></div><div><font face="monospace">          () -> #bar{x :: 'false'}</font></div></blockquote><div><br></div>I find the following things problematic with these warnings:<div><ul><li>"Function foo/0 has no local return": what the message says is not true. There are some type spec issues with foo/0, but it won't crash, because the emulator doesn't care about your type specs at runtime.</li><li>"Cons will produce an improper list": what the message says is not true. If the 2nd argument is none(), that is: evaluating that expression would raise an exception instead of returning a value, cons will not produce anything, the execution will never reach that far.</li><li>There is no "Function err/0 has no local return" warning, even though err/0 has no local return for real. This also feels very inconsistent with the fact that there is such a warning for the errs/0 function, which does basically the same thing (when considering types).</li><li>There is no "Cons will produce an improper list" warning for errs/0, even though it is exactly the same situation as in case of foo/0. Dialyzer feels inconsistent here.</li><li>There is no "Invalid type specification for function foo:bars/0: warning, even though this function clearly violates its spec, and the same problem in bar/0 is properly reported. (Note: this one in particular makes me very sad, because I prefer keeping type specs outside of record declarations precisely to avoid the "Function has no local return" warnings. In my experience Dialyzer produces better warnings this way, but now I found an example where an obvious problem is not detected by Dialyzer due to the field types being declared outside of the record definition.)</li><li>A minor inconsistency, but some warnings refer to the function in which they occur via its local name within the module (foo/0), while others use the qualified name (foo:bar/0).</li></ul><div>Would it be possible to make Dialyzer more consistent and less surprising in these cases?</div></div></div><div><br></div><div>Cheers,</div><div>Daniel</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 14 Feb 2020 at 15:48, Richard Carlsson <<a href="mailto:carlsson.richard@gmail.com">carlsson.richard@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Nice answer, Brujo! I think the only confusion here is the warning about the improper list; without that one, everything should have been clear. The check for improper lists ought to ignore the case when the tail is none(), since it means that the result will also be none() anyway.<br clear="all"><div><div dir="ltr"><br>        /Richard</div></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Den fre 14 feb. 2020 kl 14:05 skrev Jesper Eskilson <<a href="mailto:jesper.eskilson@klarna.com" target="_blank">jesper.eskilson@klarna.com</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Ah, my question wasn't why the error occurs in the first place, but rather an inquiry if dialyzer oughtn't formulate the error a bit differently. :)<br><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Feb 14, 2020 at 1:54 PM Fernando Benavides <<a href="mailto:elbrujohalcon@gmail.com" target="_blank">elbrujohalcon@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif">I think what's happening in this case is this…</div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif">Dialyzer sees your code (using cons for the list) as…</div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif"><br></div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif">main() -> [ #foo{x = 0} | [#foo{x = false} | []] ].</div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif"><br></div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif">It then detects the third warning from your email (namely, that you're using <i>false</i> for something that should be an <i>integer</i>):</div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif"><div style="font-family:Arial,Helvetica,sans-serif"><font face="monospace">foo.erl:9: Record construction</font></div><div style="font-family:Arial,Helvetica,sans-serif"><font face="monospace">          #foo{x :: false} violates the declared type of field x ::</font></div><div style="font-family:Arial,Helvetica,sans-serif"><font face="monospace">          integer()</font></div></div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif">Therefore, the type of that second part of the list ([#foo{x = false} | []]) will be <i>none()</i>.</div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif">And that leads dialyzer to complain with the second warning that you see…</div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif"><div style="font-family:Arial,Helvetica,sans-serif"><font face="monospace">foo.erl:8: Cons will produce an improper list since its 2nd argument is</font></div><div style="font-family:Arial,Helvetica,sans-serif"><font face="monospace">          none()</font></div></div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif">Which, in time, produces the first warning…</div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif"><span style="font-family:monospace">foo.erl:7: Function main/0 has no local return</span><br></div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif"><br></div><div class="gmail_default" style="font-family:"trebuchet ms",sans-serif">Hope this helps. </div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Feb 14, 2020 at 1:45 PM Jesper Eskilson <<a href="mailto:jesper.eskilson@klarna.com" target="_blank">jesper.eskilson@klarna.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Hi,</div><div><br>When dialyzer analyzes this program:<br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><br></div><font face="monospace">-module(foo).<br></font><font face="monospace">-export([main/0]).</font><font face="monospace"><br></font><font face="monospace">-record(foo, {x :: integer()}).</font><font face="monospace"><br></font><font face="monospace">main() -><br></font><font face="monospace">  [ #foo{x = 0},<br></font><font face="monospace">    #foo{x = false} ].</font></blockquote></div><div><br></div><div>it says:<br><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace">foo.erl:7: Function main/0 has no local return</font></div><div><font face="monospace">foo.erl:8: Cons will produce an improper list since its 2nd argument is </font></div><div><font face="monospace">          none()</font></div><div><font face="monospace">foo.erl:9: Record construction </font></div><div><font face="monospace">          #foo{x :: false} violates the declared type of field x ::</font></div><div><font face="monospace">          integer()</font></div></blockquote><div><br>It seems like dialyzer assumes that any cons with second argument not being a list will produce an improper list, but shouldn't it treat "none()" differently?<br><br>Is this a bug in dialyzer, or a feature whose usefulness I am unable to grasp?<br><br></div>-- <br><div dir="ltr"><div dir="ltr"><div><div dir="ltr"><div><p style="font-family:"Helvetica Neue",Helvetica,arial,sans-serif;font-size:9pt;line-height:1.25em;color:rgb(130,130,137);letter-spacing:0.1px;margin:0px 0px 1em;padding:0px 5px"><b>Jesper Eskilson</b><br><span style="display:inline">Senior Software Engineer</span><br><span>Kred Core</span><br><span style="font-size:9pt">+46-72-855-8421</span></p><p style="font-family:"Helvetica Neue",Helvetica,arial,sans-serif;font-size:9pt;line-height:1.25em;color:rgb(130,130,137);letter-spacing:0.1px;margin:0px 0px 1em;padding:0px 5px">Klarna Bank AB<span style="line-height:13.3333px"> (publ)</span><br>Sveavägen 46, 111 34 Stockholm<br>Tel: <a href="tel:+46812012000" style="color:rgb(130,130,137)" target="_blank">+46 8 120 120 00</a><br>Reg no: 556737-0431<br><a href="http://klarna.com/" style="color:rgb(235,111,147)" target="_blank">klarna.com</a></p><p style="font-family:"Klarna Sans",sans-serif;font-size:14px;line-height:1.4em;color:rgb(73,73,74);letter-spacing:0.1px;margin:1em 0px;padding:0px 5px"><img src="https://cdn.klarna.com/1.0/shared/image/generic/logo/sv_se/basic/logo_black.png?width=240" width="120" style="border: 0px; vertical-align: middle; max-width: 120px;"></p></div></div></div></div></div></div>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr"><table border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td align="left" valign="bottom" width="107" style="line-height:0;vertical-align:bottom;padding-right:10px;padding-top:20px;padding-bottom:20px">
                <a href="https://about.me/elbrujohalcon?promo=email_sig&utm_source=product&utm_medium=email_sig&utm_campaign=gmail_api&utm_content=thumb" style="text-decoration:none" target="_blank">
                    <img src="https://thumbs.about.me/thumbnail/users/e/l/b/elbrujohalcon_emailsig.jpg?_1498084031_146" alt="" width="105" height="70" style="margin: 0px; padding: 0px; display: block; border: 1px solid rgb(238, 238, 238);">
                </a>
            </td>
            <td align="left" valign="bottom" style="line-height:1.1;vertical-align:bottom;padding-top:20px;padding-bottom:20px">
                <img src="https://about.me/t/sig?u=elbrujohalcon" width="1" height="1" style="border: 0px; margin: 0px; padding: 0px; overflow: hidden;">
                <div style="font-size:18px;font-weight:bold;color:rgb(51,51,51);font-family:"Proxima Nova",Helvetica,Arial,sans-serif">Brujo Benavides</div>
                <a href="https://about.me/elbrujohalcon?promo=email_sig&utm_source=product&utm_medium=email_sig&utm_campaign=gmail_api&utm_content=thumb" style="text-decoration:none;font-size:12px;color:rgb(43,130,173);font-family:"Proxima Nova",Helvetica,Arial,sans-serif" target="_blank">about.me/elbrujohalcon
                </a>
            </td>
        </tr>
    </tbody>
</table>
</div>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr"><div dir="ltr"><div><div dir="ltr"><div><p style="font-family:"Helvetica Neue",Helvetica,arial,sans-serif;font-size:9pt;line-height:1.25em;color:rgb(130,130,137);letter-spacing:0.1px;margin:0px 0px 1em;padding:0px 5px"><b>Jesper Eskilson</b><br><span style="display:inline">Senior Software Engineer</span><br><span>Kred Core</span><br><span style="font-size:9pt">+46-72-855-8421</span></p><p style="font-family:"Helvetica Neue",Helvetica,arial,sans-serif;font-size:9pt;line-height:1.25em;color:rgb(130,130,137);letter-spacing:0.1px;margin:0px 0px 1em;padding:0px 5px">Klarna Bank AB<span style="line-height:13.3333px"> (publ)</span><br>Sveavägen 46, 111 34 Stockholm<br>Tel: <a href="tel:+46812012000" style="color:rgb(130,130,137)" target="_blank">+46 8 120 120 00</a><br>Reg no: 556737-0431<br><a href="http://klarna.com/" style="color:rgb(235,111,147)" target="_blank">klarna.com</a></p><p style="font-family:"Klarna Sans",sans-serif;font-size:14px;line-height:1.4em;color:rgb(73,73,74);letter-spacing:0.1px;margin:1em 0px;padding:0px 5px"><img src="https://cdn.klarna.com/1.0/shared/image/generic/logo/sv_se/basic/logo_black.png?width=240" width="120" style="border: 0px; vertical-align: middle; max-width: 120px;"></p></div></div></div></div></div>
</blockquote></div>
</blockquote></div>