<div>Hi all,</div><div><br></div><div>I think I've found a bug in Typed Racket's predicates, but investigating it raised a lot of questions, so I was hoping someone wouldn't mind explaining what'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'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="'courier new', monospace">#lang typed/racket</font></div><div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><font class="Apple-style-span" face="'courier new', monospace">(define-type Float-Or-Integer (U Float Integer))</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">(define-predicate Float-Or-Integer? Float-Or-Integer)</font></div><div><font class="Apple-style-span" face="'courier new', monospace">(define-predicate Float? Float)</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><font class="Apple-style-span" face="'courier new', monospace">(define (weird-predicate-behavior) </font></div><div>
<font class="Apple-style-span" face="'courier new', monospace"> (: integer->float (Integer -> Float))</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> (define (integer->float int) (exact->inexact int))</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> (define x (integer->float 0))</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> (printf "eq? 0.0 ~A ~%" (eq? 0.0 x))</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> (printf "eqv? 0.0 ~A ~%" (eqv? 0.0 x))</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> (printf "Float? ~A ~%" (Float? x))</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> (printf "Float-Or-Integer? ~A" (Float-Or-Integer? x)))</font></div><div> </div><div>Running this produces:</div><div><br></div><div>
<font class="Apple-style-span" face="'courier new', monospace">eq? 0.0 #f </font></div><div><font class="Apple-style-span" face="'courier new', monospace">eqv? 0.0 #t </font></div><div><font class="Apple-style-span" face="'courier new', monospace">Float? #t </font></div>
<div><font class="Apple-style-span" face="'courier new', 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="'courier new', monospace">Float</font> types is using <font class="Apple-style-span" face="'courier new', monospace">eq?</font> instead of <font class="Apple-style-span" face="'courier new', monospace">eqv?</font> for the <font class="Apple-style-span" face="'courier new', monospace">0.0</font> and <font class="Apple-style-span" face="'courier new', 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="'courier new', monospace">0.0</font> is being produced that doesn't <font class="Apple-style-span" face="'courier new', monospace">eq?</font> with the literal <font class="Apple-style-span" face="'courier new', monospace">0.0</font>. I tried doing this with, say, <font class="Apple-style-span" face="'courier new', monospace">(eq? 0.0 (- (+ 3.0 1.0) 4.0))</font> or <font class="Apple-style-span" face="'courier new', monospace">(eq? (exact->inexact 0) 0.0)</font>, but those both evaluate to <font class="Apple-style-span" face="'courier new', monospace">#t</font>, so either the compiler is doing some very clever constant folding here, or <font class="Apple-style-span" face="'courier new', monospace">eq?</font> is supposed to do value equality for floats. I'm assuming the former, but especially for the <font class="Apple-style-span" face="'courier new', monospace">exact->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's simply an <font class="Apple-style-span" face="'courier new', monospace">eq?</font> vs. <font class="Apple-style-span" face="'courier new', monospace">eqv?</font> issue, I've sent along a patch).</div>
<div><br></div><div>Thanks,</div><div>Luke</div><div><br></div>