You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Some time ago I did a deep dive into the racket/draw contracts. Here is an observation that led me to some bugs: class contracts do not provide a guarantee on objects that are created from within the contract boundary.
Example 1
The numbers given to in-region? are expected to be real?. If you give imaginary numbers
(define reg (new region%))
(send reg in-region? 0+i0+i)
the correct error from the region% class contract is raised:
; in-region?: contract violation
; expected: real?
; given: 0+1i
; in: the 1st argument of
; the in-region? method in
; region%/c
However, regions can be created indirectly via the clipping region
; get-argb-pixels: contract violation
; expected: bytes?
; given: #f
; in: an and/c case of
; the 5th argument of
; the get-argb-pixels method in
; the range of ...
But bitmaps can be created through the make-bitmap method of canvases
(define sn (new snip%))
(send sn blink-caret #f#f#f)
and the contract gives this error
; blink-caret: contract violation
; expected: (is-a?/c dc<%>)
; given: #f
; in: the 1st argument of
; the blink-caret method in
; the 2nd conjunct of ...
However, cloning the snip constructs a new object that is not protected
(define sn (new snip%))
(define sn2 (send sn copy))
(send sn2 blink-caret #f#f#f)
and gives this different error
; blink-caret method of snip%: expected argument of type <dc<%> instance>; given: #f; other arguments: #f #f
which doesn't come from a contract check, but is a (usually redundant) defensive check that is present in the blink-caret method.
Summary
These are just a few instances I found in racket/draw—there are probably quite a few more. I'm not sure what the takeaway is. My thought is that using (is-a?/c my-class%) and then subsequently assuming that objects satisfy the class contract on my-class% is dangerous since it assumes that my-class% objects are only constructed through the protected constructor. Using object/c contracts everywhere instead of is-a?/c isn't a panacea either because, as far as I know, they will not get collapsed and wrappers might quickly accumulate. So while these bugs that I mentioned can be fixed individually, I feel as though there is a deeper concern here with respect to class contracts in general.
The text was updated successfully, but these errors were encountered:
Some time ago I did a deep dive into the
racket/draw
contracts. Here is an observation that led me to some bugs: class contracts do not provide a guarantee on objects that are created from within the contract boundary.Example 1
The numbers given to
in-region?
are expected to bereal?
. If you give imaginary numbersthe correct error from the
region%
class contract is raised:However, regions can be created indirectly via the clipping region
and such will give an internal error since the region was not created through the protected
region%
class:Example 2
The fifth argument to
get-argb-pixels
is expected to bebytes?
and gives an error as such
But bitmaps can be created through the
make-bitmap
method of canvasesand in such a case an internal error is raised because it's unprotected
Example 3
The
blink-caret
method of snips expects adc<%>
and the contract gives this error
However, cloning the snip constructs a new object that is not protected
and gives this different error
which doesn't come from a contract check, but is a (usually redundant) defensive check that is present in the
blink-caret
method.Summary
These are just a few instances I found in
racket/draw
—there are probably quite a few more. I'm not sure what the takeaway is. My thought is that using(is-a?/c my-class%)
and then subsequently assuming that objects satisfy the class contract onmy-class%
is dangerous since it assumes thatmy-class%
objects are only constructed through the protected constructor. Usingobject/c
contracts everywhere instead ofis-a?/c
isn't a panacea either because, as far as I know, they will not get collapsed and wrappers might quickly accumulate. So while these bugs that I mentioned can be fixed individually, I feel as though there is a deeper concern here with respect to class contracts in general.The text was updated successfully, but these errors were encountered: