<div dir="ltr">On Fri, Mar 24, 2017 at 11:37 PM Dmitry Kakurin <<a href="mailto:dima_kakurin@hotmail.com">dima_kakurin@hotmail.com</a>> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr" class="gmail_msg">
<div id="m_1104362636394224897divtagdefaultwrapper" style="font-size:12pt;color:#000000;font-family:Calibri,Arial,Helvetica,sans-serif" dir="ltr" class="gmail_msg">Two of them that seem especially useful are <span class="gmail_msg"><i class="gmail_msg">underspecs </i>and <i class="gmail_msg">overspecs</i>.</span>
<p class="gmail_msg"><span class="gmail_msg"></span></p></div></div></blockquote>If you think about it, an overspecification is not really a problem with the code. The dialyzer uses inference analysis and makes a best effort at determining the type of a given function. Your contract specifies your usage of the function. When a overspec happens, it is because your contract is more restrictive than the inference. This is usually not a problem. A small change in your function body might change the inferred type entirely. But unless you want to go change your contract all the time, it may be better to keep it more restrictive. Lots of functions are more general than their intended use. Another problem is when the dialyzer fails to make a precise inference, so falls back to type any(). Enabling overspecs will make the system complain all the time in this situation, but it may not be a problem.<br><br></div><div class="gmail_quote">Underspecs, on the other hand, could spell trouble. Here the inference is more restrictive, and thus there are inputs to the function which is within the contract, but won't make the code terminate as expected according to the inference scheme. If your code never makes use of the extended contract, there is no problem, but as soon as some user tries to do so, things will go bad. The dialyzer will usually catch such a use quickly, but it is nicer to be strict in the contract if possible.<br><br></div><div class="gmail_quote">There are, however, situations where underspecs isn't that desirable as a property either. Suppose you are returning a map, such as #{ a => 37 }. The dialyzer can infer its success type to be #{ a := pos_integer() }[0]. But you may have written a specification where you say a map() is returned. This is more general than the inferred type, and as such it is an underspec violation. Your contract isn't wrong, but on the other hand, it isn't precise either. A common problem that also hits a lot are when you are declaring a binary(), but the dialyzer is able to figure out a more precise type scheme, for instance <<_:64, _:_*24>>. You will perhaps be more happy with just saying "this is a binary".<br><br></div><div class="gmail_quote">My usual recommendation is to start with the default set of warnings. Remove every error there, because the slogan is<br><br></div><div class="gmail_quote"> The dialyzer is never wrong!<br><br></div><div class="gmail_quote">and this is absolutely true. Once you have a dialyzer clean piece of code with the default warnings, you start turning on underspecs, no_return, and so on. But often this is more for understanding if there is anything that sticks out as being too general.<br></div><div class="gmail_quote"><br><br></div><div class="gmail_quote">[0] This is strictly not true. If you *always* return 37, then it figures out the type is exactly the same response every time and tags its type as #{ a := 37 }. But for this exposition, I'm assuming your code returns "some positive integer" where 37 is an example.<br><br></div></div>