Allow send
to union of objects
Also fix TR `send` for multiple/any values as receiver Now emits a real type error instead of crashing with an internal match error. Closes PR 14547 original commit: 7743386eec4f5d752f5f87dab52e2da43bd11926
This commit is contained in:
parent
64a4fd6e1d
commit
e03538a1ac
|
@ -4,7 +4,7 @@
|
|||
|
||||
(require "../utils/utils.rkt"
|
||||
racket/match syntax/stx
|
||||
(typecheck signatures tc-funapp)
|
||||
(typecheck signatures tc-funapp tc-metafunctions)
|
||||
(types base-abbrev resolve utils type-table)
|
||||
(rep type-rep)
|
||||
(utils tc-utils))
|
||||
|
@ -13,13 +13,14 @@
|
|||
(export tc-send^)
|
||||
|
||||
(define (tc/send form rcvr method args [expected #f])
|
||||
;; do-check : Type/c -> tc-results/c
|
||||
(define (do-check rcvr-type)
|
||||
(match rcvr-type
|
||||
[(tc-result1: (Instance: (? needs-resolving? type)))
|
||||
(do-check (ret (make-Instance (resolve type))))]
|
||||
[(tc-result1: (and obj (Instance: (Class: _ _ _ methods _ _))))
|
||||
(match (tc-expr method)
|
||||
[(tc-result1: (Value: (? symbol? s)))
|
||||
[(Instance: (? needs-resolving? type))
|
||||
(do-check (make-Instance (resolve type)))]
|
||||
[(and obj (Instance: (Class: _ _ _ methods _ _)))
|
||||
(match (tc-expr/t method)
|
||||
[(Value: (? symbol? s))
|
||||
(define ftype
|
||||
(cond [(assq s methods) => cadr]
|
||||
[else (tc-error/expr/fields
|
||||
|
@ -27,14 +28,18 @@
|
|||
"method name" s
|
||||
"object type" obj
|
||||
#:return -Bottom)]))
|
||||
(define retval
|
||||
(tc/funapp rcvr args (ret ftype) (stx-map tc-expr args) expected))
|
||||
(add-typeof-expr form retval)
|
||||
retval]
|
||||
[(tc-result1: t)
|
||||
(int-err "non-symbol methods not supported by Typed Racket: ~a" t)])]
|
||||
[(tc-result1: t) (tc-error/expr/fields
|
||||
"send: type mismatch"
|
||||
"expected" "an object"
|
||||
"given" t)]))
|
||||
(do-check (tc-expr rcvr)))
|
||||
(tc/funapp rcvr args (ret ftype) (stx-map tc-expr args) expected)]
|
||||
[_ (int-err "non-symbol methods not supported by Typed Racket: ~a"
|
||||
rcvr-type)])]
|
||||
;; union of objects, check pointwise and union the results
|
||||
[(Union: (list (and objs (Instance: _)) ...))
|
||||
(merge-tc-results
|
||||
(for/list ([obj (in-list objs)])
|
||||
(do-check obj)))]
|
||||
[_ (tc-error/expr/fields
|
||||
"send: type mismatch"
|
||||
"expected" "an object"
|
||||
"given" rcvr-type)]))
|
||||
(define final-ret (do-check (tc-expr/t rcvr)))
|
||||
(add-typeof-expr form final-ret)
|
||||
final-ret)
|
||||
|
|
|
@ -109,6 +109,39 @@
|
|||
[tc-err (send 4 m 3)
|
||||
#:ret (ret (-val 5) -bot-filter)
|
||||
#:expected (ret (-val 5) -no-filter -no-obj)]
|
||||
;; Fails, sending to multiple/unknown values
|
||||
[tc-err (send (values 'a 'b) m 'c)
|
||||
#:msg #rx"expected single value"]
|
||||
[tc-err (send (eval "3") m 'c)
|
||||
#:msg #rx"expected single value"]
|
||||
;; Send to a union of objects in various ways
|
||||
[tc-e (let ()
|
||||
(: f (-> (U (Object [m (-> String)])
|
||||
(Object [m (-> Symbol)]
|
||||
[n (-> Void)]))
|
||||
(U Symbol String)))
|
||||
(define (f o) (send o m))
|
||||
(f (new (class object% (super-new) (define/public (m) "foo")))))
|
||||
(t:Un -String -Symbol)]
|
||||
[tc-e (let ()
|
||||
(: f (-> (U (Object [m (-> (values String Symbol))])
|
||||
(Object [m (-> (values Symbol String))]
|
||||
[n (-> Void)]))
|
||||
(values (U Symbol String) (U Symbol String))))
|
||||
(define (f o) (send o m))
|
||||
(f (new (class object% (super-new)
|
||||
(define/public (m) (values "foo" 'bar))))))
|
||||
#:ret (ret (list (t:Un -String -Symbol) (t:Un -String -Symbol)))]
|
||||
[tc-err
|
||||
(let ()
|
||||
(define obj
|
||||
(if (> (random) 0.5)
|
||||
(new (class object% (super-new)
|
||||
(define/public (m) "foo")))
|
||||
(new (class object% (super-new)
|
||||
(define/public (m) (values "foo" "bar"))))))
|
||||
(send obj m))
|
||||
#:msg #rx"Expected the same number of values.*got 1 and 2"]
|
||||
;; Field access via get-field
|
||||
[tc-e (let ()
|
||||
(: j% (Class (field [n Integer])
|
||||
|
|
Loading…
Reference in New Issue
Block a user