Change object-contract to use find-method/who (already exported for Typed
Scheme) to look for the appropriate method to wrap, which makes Robby's object-contracts appropriately translucent during contract wrapping. svn: r18102
This commit is contained in:
parent
520b4feedc
commit
35afebaea3
|
@ -72,20 +72,18 @@
|
|||
(unless (object? val)
|
||||
(raise-blame-error blame val "expected an object, got ~e" val))
|
||||
|
||||
(let ([objs-mtds (interface->method-names (object-interface val))]
|
||||
[vtable (extract-vtable val)]
|
||||
[method-ht (extract-method-ht val)])
|
||||
(for-each (λ (m proj)
|
||||
(let ([index (hash-ref method-ht m #f)])
|
||||
(unless index
|
||||
(raise-blame-error blame val "expected an object with method ~s" m))
|
||||
;; verify the first-order properties by apply the projection and
|
||||
;; throwing the result away. Without this, the contract wrappers
|
||||
;; just check the first-order properties of the wrappers, which is
|
||||
;; the wrong thing.
|
||||
(proj (vector-ref vtable index))))
|
||||
meth-names
|
||||
meth-projs))
|
||||
(for-each (λ (m proj)
|
||||
(let-values ([(method unwrapper)
|
||||
(find-method/who 'object-contract val m #:error? #f)])
|
||||
(unless method
|
||||
(raise-blame-error blame val "expected an object with method ~s" m))
|
||||
;; verify the first-order properties by apply the projection and
|
||||
;; throwing the result away. Without this, the contract wrappers
|
||||
;; just check the first-order properties of the wrappers, which is
|
||||
;; the wrong thing.
|
||||
(proj method)))
|
||||
meth-names
|
||||
meth-projs)
|
||||
|
||||
(let ([fields (field-names val)])
|
||||
(for-each (λ (f)
|
||||
|
|
|
@ -2944,10 +2944,12 @@
|
|||
;; -> (values method-proc object)
|
||||
;; returns the method's procedure and a function to unwrap `this' in the case
|
||||
;; that this is a wrapper object that is just "falling thru".
|
||||
(define (find-method/who who in-object name)
|
||||
(define (find-method/who who in-object name #:error? [error? #t])
|
||||
(unless (object? in-object)
|
||||
(obj-error who "target is not an object: ~e for method: ~a"
|
||||
in-object name))
|
||||
(if error?
|
||||
(obj-error who "target is not an object: ~e for method: ~a"
|
||||
in-object name)
|
||||
(values #f values)))
|
||||
|
||||
(let-syntax ([loop-body
|
||||
(lambda (stx)
|
||||
|
@ -2961,9 +2963,11 @@
|
|||
[pos (values (vector-ref (class-methods c) pos) abs-object)]
|
||||
[(wrapper-object? abs-object) wrapper-case]
|
||||
[else
|
||||
(obj-error who "no such method: ~a~a"
|
||||
name
|
||||
(for-class (class-name c)))])))]))])
|
||||
(if error?
|
||||
(obj-error who "no such method: ~a~a"
|
||||
name
|
||||
(for-class (class-name c)))
|
||||
(values #f values))])))]))])
|
||||
(loop-body
|
||||
in-object
|
||||
(let loop ([loop-object in-object])
|
||||
|
@ -3677,12 +3681,6 @@
|
|||
|
||||
cls)))
|
||||
|
||||
; extract-vtable : object -> (vectorof method-proc[this args ... -> res])
|
||||
(define (extract-vtable o) (class-methods (object-ref o)))
|
||||
|
||||
; extract-method-ht : object -> hash-table[sym -> number]
|
||||
(define (extract-method-ht o) (class-method-ht (object-ref o)))
|
||||
|
||||
;;--------------------------------------------------------------------
|
||||
;; misc utils
|
||||
;;--------------------------------------------------------------------
|
||||
|
@ -3871,8 +3869,6 @@
|
|||
;; Providing normal functionality:
|
||||
(provide (protect-out make-wrapper-class
|
||||
wrapper-object-wrapped
|
||||
extract-vtable
|
||||
extract-method-ht
|
||||
get-field/proc)
|
||||
|
||||
(rename-out [_class class]) class* class/derived
|
||||
|
|
|
@ -3959,6 +3959,32 @@
|
|||
(λ (x) x))
|
||||
1)
|
||||
|
||||
(test/spec-passed/result
|
||||
'object-contract-layered1
|
||||
'(send (contract (object-contract (m (-> number? number?)))
|
||||
(contract (object-contract)
|
||||
(new (class object% (super-new) (define/public (m x) x)))
|
||||
'pos
|
||||
'neg)
|
||||
'pos
|
||||
'neg)
|
||||
m
|
||||
5)
|
||||
5)
|
||||
|
||||
;; Make sure we're not dropping projections on the floor.
|
||||
(test/neg-blame
|
||||
'object-contract-layered2
|
||||
'(send (contract (object-contract (m (-> number? number?)))
|
||||
(contract (object-contract (m (-> string? string?)))
|
||||
(new (class object% (super-new) (define/public (m x) x)))
|
||||
'pos
|
||||
'neg)
|
||||
'pos
|
||||
'neg)
|
||||
m
|
||||
5))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; test error message has right format
|
||||
|
|
Loading…
Reference in New Issue
Block a user