[racket-dev] Weird bug in Typed Racket predicate for Float 0.0

From: Luke Vilnis (lvilnis at gmail.com)
Date: Thu Sep 8 20:43:02 EDT 2011

Hi all,

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.

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:

#lang typed/racket

(define-type Float-Or-Integer (U Float Integer))
(define-predicate Float-Or-Integer? Float-Or-Integer)
(define-predicate Float? Float)

(define (weird-predicate-behavior)
  (: integer->float (Integer -> Float))
  (define (integer->float int) (exact->inexact int))
  (define x (integer->float 0))
  (printf "eq? 0.0 ~A ~%" (eq? 0.0 x))
  (printf "eqv? 0.0 ~A ~%" (eqv? 0.0 x))
  (printf "Float? ~A ~%" (Float? x))
  (printf "Float-Or-Integer? ~A" (Float-Or-Integer? x)))

Running this produces:

eq? 0.0 #f
eqv? 0.0 #t
Float? #t
Float-Or-Integer? #f

The part of TR that generates the compound contracts for unions containing
Float  types is using eq? instead of eqv? for the 0.0 and -0.0 case (which
started in version 5.1.1), which explains why the predicate fails. Somehow,
in the repro above, a 0.0 is being produced that doesn't eq? with the
literal 0.0. I tried doing this with, say, (eq? 0.0 (- (+ 3.0 1.0)
4.0)) or (eq?
(exact->inexact 0) 0.0), but those both evaluate to #t, so either the
compiler is doing some very clever constant folding here, or eq? is supposed
to do value equality for floats. I'm assuming the former, but especially for
the exact->inexact 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 eq? vs. eqv? issue, I've sent along a patch).

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/dev/archive/attachments/20110908/ce06b5a4/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Fixed-a-bug-where-predicates-would-sometimes-fail-to.patch
Type: application/octet-stream
Size: 1464 bytes
Desc: not available
URL: <http://lists.racket-lang.org/dev/archive/attachments/20110908/ce06b5a4/attachment.obj>

Posted on the dev mailing list.