<div>Hi all,</div><div><br></div><div>I think I&#39;ve found a bug in Typed Racket&#39;s predicates, but investigating it raised a lot of questions, so I was hoping someone wouldn&#39;t mind explaining what&#39;s going on here.</div>
<div><br></div><div>A couple weeks ago I wrote a TR program using version 5.1 (like a bonehead, my shortcut to DrRacket was running it out of the wrong directory so I wasn&#39;t using the version that I thought I was.) When I recently converted it to 5.1.3, I started noticing intermittent pattern matching failures. I managed to isolate it to the following standalone:</div>
<div><br></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">#lang typed/racket</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define-type Float-Or-Integer (U Float Integer))</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define-predicate Float-Or-Integer? Float-Or-Integer)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define-predicate Float? Float)</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define (weird-predicate-behavior) </font></div><div>
<font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (: integer-&gt;float (Integer -&gt; Float))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (define (integer-&gt;float int) (exact-&gt;inexact int))</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (define x (integer-&gt;float 0))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (printf &quot;eq? 0.0 ~A ~%&quot; (eq? 0.0 x))</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (printf &quot;eqv? 0.0 ~A ~%&quot; (eqv? 0.0 x))</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (printf &quot;Float? ~A ~%&quot; (Float? x))</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (printf &quot;Float-Or-Integer? ~A&quot; (Float-Or-Integer? x)))</font></div><div>  </div><div>Running this produces:</div><div><br></div><div>
<font class="Apple-style-span" face="&#39;courier new&#39;, monospace">eq? 0.0 #f </font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">eqv? 0.0 #t </font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">Float? #t </font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">Float-Or-Integer? #f</font></div><div><br></div><div>The part of TR that generates the compound contracts for unions containing <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">Float</font>  types is using <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">eq?</font> instead of <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">eqv?</font> for the <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">0.0</font> and <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">-0.0</font> case (which started in version 5.1.1), which explains why the predicate fails. Somehow, in the repro above, a <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">0.0</font> is being produced that doesn&#39;t <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">eq?</font> with the literal <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">0.0</font>. I tried doing this with, say, <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(eq? 0.0 (- (+ 3.0 1.0) 4.0))</font> or <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(eq? (exact-&gt;inexact 0) 0.0)</font>, but those both evaluate to <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">#t</font>, so either the compiler is doing some very clever constant folding here, or <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">eq?</font> is supposed to do value equality for floats. I&#39;m assuming the former, but especially for the <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">exact-&gt;inexact</font> case that seems pretty darn clever. Anyhow, I was hoping someone could confirm my suspicion that this bug was so hard to reproduce because of crazy compiler magic (also, assuming this is right and it&#39;s simply an <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">eq?</font> vs. <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">eqv?</font> issue, I&#39;ve sent along a patch).</div>
<div><br></div><div>Thanks,</div><div>Luke</div><div><br></div>