Remove the depth subtype check on #:implements
This check was not really necessary to begin with, but I thought it might be a useful sanity check. In retrospect, calling `subtype` here causes other headaches (such as when registering type aliases) and is confusing when multiple #:implements are provided. Instead, the #:implements clauses are just linearized and the last type for any given method/field is taken. This may also prevent a heisenbug that occurs in the GUI framework types. I still don't know the root cause of that non-determinism though. Closes PR 14669 original commit: 9b4e3befa3605851f1ee30f20f4a38edd06dd8a9
This commit is contained in:
parent
c57db18ec4
commit
99ebb7e51c
|
@ -312,7 +312,9 @@ additional provides all other bindings from @racketmodname[racket/class].
|
|||
and @racket[init-field] clauses.
|
||||
|
||||
Multiple @racket[#:implements] clauses may be provided for a single class
|
||||
type.
|
||||
type. The types for the @racket[#:implements] clauses are merged in order and the
|
||||
last type for a given method name or field is used (the types in the @racket[Class]
|
||||
type itself takes precedence).
|
||||
|
||||
@ex[
|
||||
(define-type Point<%> (Class (field [x Real] [y Real])))
|
||||
|
|
|
@ -628,27 +628,14 @@
|
|||
;; -> Option<Id> FieldDict MethodDict AugmentDict
|
||||
;; Merges #:implements class type and the current class clauses appropriately
|
||||
(define (merge-with-parent-type row-var parent-type parent-stx fields methods augments)
|
||||
;; (Listof Symbol) Dict Dict String -> (Values Dict Dict)
|
||||
;; check for duplicates in a class clause
|
||||
(define (check-duplicate-clause names super-names types super-types err-msg)
|
||||
(define maybe-dup (check-duplicate (append names super-names)))
|
||||
(cond [maybe-dup
|
||||
(define type (car (dict-ref types maybe-dup)))
|
||||
(define super-type (car (dict-ref super-types maybe-dup)))
|
||||
(cond [;; if there is a duplicate, but the type is a subtype,
|
||||
;; then let it through and check for any other duplicates
|
||||
(unless (subtype type super-type)
|
||||
(parse-error "class member type not a subtype of parent member type"
|
||||
"member" maybe-dup
|
||||
"type" type
|
||||
"parent type" super-type))
|
||||
(check-duplicate-clause
|
||||
names (remove maybe-dup super-names)
|
||||
types (dict-remove super-types maybe-dup)
|
||||
err-msg)]
|
||||
[else
|
||||
(parse-error #:stx parent-stx err-msg "name" maybe-dup)])]
|
||||
[else (values types super-types)]))
|
||||
;; merge-clause : Dict Dict -> Dict
|
||||
;; Merge all the non-duplicate entries from the parent types
|
||||
(define (merge-clause parent-clause clause)
|
||||
(for/fold ([clause clause])
|
||||
([(k v) (in-dict parent-clause)])
|
||||
(if (dict-has-key? clause k)
|
||||
clause
|
||||
(dict-set clause k v))))
|
||||
|
||||
(define (match-parent-type parent-type)
|
||||
(define resolved (resolve parent-type))
|
||||
|
@ -668,24 +655,6 @@
|
|||
(match-define (list (list super-method-names _) ...) super-methods)
|
||||
(match-define (list (list super-augment-names _) ...) super-augments)
|
||||
|
||||
;; if any duplicates are found between this class and the superclass
|
||||
;; type, then raise an error
|
||||
(define-values (checked-fields checked-super-fields)
|
||||
(check-duplicate-clause
|
||||
field-names super-field-names
|
||||
fields super-fields
|
||||
"field or init-field name conflicts with #:implements clause"))
|
||||
(define-values (checked-methods checked-super-methods)
|
||||
(check-duplicate-clause
|
||||
method-names super-method-names
|
||||
methods super-methods
|
||||
"method name conflicts with #:implements clause"))
|
||||
(define-values (checked-augments checked-super-augments)
|
||||
(check-duplicate-clause
|
||||
augment-names super-augment-names
|
||||
augments super-augments
|
||||
"augmentable method name conflicts with #:implements clause"))
|
||||
|
||||
;; it is an error for both the extending type and extended type
|
||||
;; to have row variables
|
||||
(when (and row-var super-row-var)
|
||||
|
@ -693,9 +662,9 @@
|
|||
" extend another type that has a row variable")))
|
||||
|
||||
;; then append the super types if there were no errors
|
||||
(define merged-fields (append checked-super-fields checked-fields))
|
||||
(define merged-methods (append checked-super-methods checked-methods))
|
||||
(define merged-augments (append checked-super-augments checked-augments))
|
||||
(define merged-fields (merge-clause super-fields fields))
|
||||
(define merged-methods (merge-clause super-methods methods))
|
||||
(define merged-augments (merge-clause super-augments augments))
|
||||
|
||||
;; make sure augments and methods are disjoint
|
||||
(define maybe-dup-method (check-duplicate (dict-keys merged-methods)))
|
||||
|
@ -773,9 +742,9 @@
|
|||
[fields given-fields]
|
||||
[methods given-methods]
|
||||
[augments given-augments])
|
||||
([parent-type parent-types]
|
||||
[parent-stx (append (or (list parent/init-stx) null)
|
||||
parent-stxs)])
|
||||
([parent-type (reverse parent-types)]
|
||||
[parent-stx (reverse (append (or (list parent/init-stx) null)
|
||||
parent-stxs))])
|
||||
(merge-with-parent-type row-var parent-type parent-stx
|
||||
fields methods augments)))
|
||||
|
||||
|
|
|
@ -1632,4 +1632,23 @@
|
|||
(super-new)
|
||||
(init y x)))
|
||||
(error "foo"))
|
||||
#:msg "type mismatch"]))
|
||||
#:msg "type mismatch"]
|
||||
;; PR 14669 (next two)
|
||||
[tc-e (let ()
|
||||
(define-type-alias A (Class [m (-> Any)]))
|
||||
(define-type-alias B (Class #:implements A [m (-> Void)]))
|
||||
(define-type-alias C (Class #:implements A))
|
||||
(define-type-alias D (Class #:implements C #:implements B))
|
||||
(: d% D)
|
||||
(define d% (class object% (super-new) (define/public (m) (void))))
|
||||
(send (new d%) m))
|
||||
-Void]
|
||||
[tc-e (let ()
|
||||
(define-type-alias A (Class [m (-> Any)]))
|
||||
(define-type-alias B (Class #:implements A [m (-> Void)]))
|
||||
(define-type-alias C (Class #:implements A))
|
||||
(define-type-alias D (Class #:implements B #:implements C))
|
||||
(: d% D)
|
||||
(define d% (class object% (super-new) (define/public (m) (void))))
|
||||
(send (new d%) m))
|
||||
Univ]))
|
||||
|
|
Loading…
Reference in New Issue
Block a user