typed-racket
typed-racket copied to clipboard
class field subtyping + set-field! leads to segfault
What version of Racket are you using?
8.8
What program did you run?
#lang typed/racket
(: example% (Class (field [id String])
[get-id (-> String)]))
(define example%
(class object%
(super-new)
(field [id ""])
(: get-id (-> String))
(define/public (get-id)
id)))
(: a (Object (field (id (Union String Number)))
[get-id (-> String)]))
(define a (new example%))
; either this should fail
(set-field! id a 42)
; or this should not segfault
(string-length (send a get-id))
What should have happened?
Either set-field! or string-length should have triggered a contract violation. Another option could be to reject the upcast in (define a (new example%))?
If you got an error message, please include it here.
invalid memory reference. Some debugging context lost
/Applications/Racket v8.8/share/pkgs/typed-racket-lib/typed-racket/optimizer/string.rkt:20:17
/Applications/Racket v8.8/share/pkgs/typed-racket-lib/typed-racket/typecheck/toplevel-trampoline.rkt:165:23
It's almost like the type assertion on a should re-check the example% body (where it would catch that get-id is ill-typed), but that is unlikely to be generally possible or desirable?
Re-playing my other thoughts: mutation seems like the problem here, since there's nothing obvious about the types that says that A shouldn't be an allowably sub-type of (U A B); that is, that generalizing the type should be wrong. Perhaps we should know that generalizing fields is wrong because they are mutable? I'm not sure. Either way, the crash is probably because unsafe string operations are used in the compile code, since the result of get-id is "definitely" a string…
Hopefully this is helpful to typed/racket core team 😅
I think that's not an upcast in the (define a (new example%)) precisely because the a field is mutable.