Open SuzanneSoy opened 8 years ago
I managed to construct an unsound example based on this:
#lang typed/racket
(define v ((λ #:∀ (A ...) [rest : A ... A]
(let ([p (pair? rest)])
(if p p p)))
1))
(ann v #f) ; => #t
And for extra fun, we can cause a run-time error:
#lang typed/racket
(define v ((λ #:∀ (A ...) [rest : A ... A]
(let ([p (pair? rest)])
(if p p p)))
1))
(: fn (case→ (→ #f Integer)
(→ #t String)))
(define (fn b)
(if b "oops" 1))
(+ (fn v) 2)
; => +: contract violation
; expected: number?
; given: "oops"
FWIW, the bad optimization is just a symptom. The underlying cause is highly likely to be a bug in TR's unreachable code detection, which has historically been pretty brittle.
This issue has been mentioned on Racket Discourse. There might be relevant details there:
What version of Racket are you using?
6.6.0.1
What program did you run?
What should have happened?
The result should be
#t
, but the program outputs#f
. When typing this expression at the REPL, we can see racket incorrectly inferred the return type isFalse
.Without the
(if … #t #f)
, the program outputs#t
as expected:Also, when using a regular
Any *
rest argument instead of the polymorphicA ... A
, the result is correct:I couldn't find a way to turn this into unsafe behaviour, so the problem is "just" incorrect results.