<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"><!-- P {margin-top:0;margin-bottom:0;} --></style>
</head>
<body dir="ltr">
<div id="divtagdefaultwrapper" style="font-size:12pt;color:#000000;font-family:Calibri,Arial,Helvetica,sans-serif;" dir="ltr">
<p>Hi all,</p>
<p>I've started using Dialyzer and tried to enable as many warnings as possible.</p>
<p>Two of them that seem especially useful are <span><i>underspecs </i>and <i>overspecs</i>.</span></p>
<p><span>But after struggling with warnings produced by them for a while I've realized that what I really need is a subset of each.</span></p>
<p><span>In the example below (sorry, I'm using Elixir syntax but hope it's still obvious) the 2 warnings I want to enable are <span><b>under_in</b> and <span><b>over_out</b>. They are the ones that will break callers relying on the spec. While
<i>over_in</i> and <i>under_out</i> warnings are more of a hints to the function author about current implementation and are much less serious.</span></span></span></p>
<p><span><span><span>The current Dialyzer options allow me to enable either both over_* warnings or both under_* warnings. But that's not useful.</span></span></span></p>
<p><span><span><span>Is there a way to configure Dialyzer the way I want?</span></span></span></p>
<p><span><span><span><br>
</span></span></span></p>
<p><span><span><span>Here is the demo code:</span></span></span></p>
<p><span><span><span><br>
</span></span></span></p>
<p><span><span><span></span></span></span></p>
<div style="color: rgb(212, 212, 212); background-color: rgb(30, 30, 30); font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px;">
<div>  <span style="color: #608b4e;"># suboptimal implementation, fine for caller</span></div>
<div>  <span style="color: #9cdcfe;">@spec</span> over_in(x :: integer) :: <span style="color: #569cd6;">nil</span></div>
<div>  <span style="color: #c586c0;">def</span> <span style="color: #dcdcaa;">over_in</span>(x) <span style="color: #c586c0;">when</span> is_number(x) <span style="color: #c586c0;">do</span></div>
<div>    <span style="color: #569cd6;">nil</span></div>
<div>  <span style="color: #c586c0;">end</span></div>
<br>
<div>  <span style="color: #608b4e;"># broken caller contract, could return unexpected value</span></div>
<div>  <span style="color: #9cdcfe;">@spec</span> over_out(x :: number) :: integer</div>
<div>  <span style="color: #c586c0;">def</span> <span style="color: #dcdcaa;">over_out</span>(x) <span style="color: #c586c0;">when</span> is_number(x) <span style="color: #c586c0;">do</span></div>
<div>    x</div>
<div>  <span style="color: #c586c0;">end</span></div>
<br>
<div>  <span style="color: #608b4e;"># broken caller contract</span><span style="color: rgb(96, 139, 78);">, rejects input allowed by the spec</span></div>
<div>  <span style="color: #9cdcfe;">@spec</span> under_in(x :: number) :: <span style="color: #569cd6;">nil</span></div>
<div>  <span style="color: #c586c0;">def</span> <span style="color: #dcdcaa;">under_in</span>(x) <span style="color: #c586c0;">when</span> is_integer(x) <span style="color: #c586c0;">do</span></div>
<div>    <span style="color: #569cd6;">nil</span></div>
<div>  <span style="color: #c586c0;">end</span></div>
<br>
<div>  <span style="color: #608b4e;"># current implementation detail, does not concern caller</span></div>
<div>  <span style="color: #9cdcfe;">@spec</span> under_out(x :: integer) :: number</div>
<div>  <span style="color: #c586c0;">def</span> <span style="color: #dcdcaa;">under_out</span>(x) <span style="color: #c586c0;">when</span> is_integer(x) <span style="color: #c586c0;">do</span></div>
<div>    x</div>
<div>  <span style="color: #c586c0;">end</span></div>
</div>
<br>
<p></p>
<p>and here are the warnings:</p>
<p><br>
</p>
<p></p>
<div style="color: rgb(212, 212, 212); background-color: rgb(30, 30, 30); font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px;">
<div>demo.ex:4: Type specification</div>
<div>'Elixir.Virt':over_in(x::integer()) -> 'nil' is a subtype of the success typing: </div>
<div>'Elixir.Virt':over_in(number()) -> 'nil'</div>
<div><br>
</div>
<div>demo.ex:9: Type specification</div>
<div>'Elixir.Virt':over_out(x::number()) -> integer() is a subtype of the success typing:</div>
<div>'Elixir.Virt':over_out(number()) -> number()</div>
<div><br>
</div>
<div>demo.ex:14: Type specification</div>
<div>'Elixir.Virt':under_in(x::number()) -> 'nil' is a supertype of the success typing:</div>
<div>'Elixir.Virt':under_in(integer()) -> 'nil'</div>
<div><br>
</div>
<div>demo.ex:19: The specification for 'Elixir.Virt':under_out/1 states that the function might also return</div>
<div>float() but the inferred return is</div>
<div>integer()</div>
<div></div>
</div>
<br>
<p></p>
<div id="Signature">Thanks, Dmitry.</div>
</div>
</body>
</html>