From b3f66a49739ffd66a5770a30d2da83db6ddc5f39 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Wed, 15 May 2019 10:32:06 -0600 Subject: [PATCH] repair `prop:impersonator-of` interaction with `{impersonator,chaperone}-of?` Relevant to #2644 --- .../scribblings/reference/chaperones.scrbl | 20 +++++++++++-------- .../tests/racket/chaperone.rktl | 2 ++ racket/src/cs/rumble/equal.ss | 5 +++++ racket/src/racket/src/bool.c | 8 ++++++++ 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/pkgs/racket-doc/scribblings/reference/chaperones.scrbl b/pkgs/racket-doc/scribblings/reference/chaperones.scrbl index 61d5b9ac8b..4980bfebea 100644 --- a/pkgs/racket-doc/scribblings/reference/chaperones.scrbl +++ b/pkgs/racket-doc/scribblings/reference/chaperones.scrbl @@ -129,15 +129,19 @@ proceeds by comparing @racket[_v1] and @racket[_v2] recursively (as with Indicates whether @racket[v1] can be considered equivalent modulo chaperones to @racket[v2]. -For values that include no chaperones, @racket[v1] and @racket[v2] can -be considered chaperones of each other if they are @racket[equal?], -except that mutable vectors, boxes, strings, byte strings, and mutable -structures within @racket[v1] and @racket[v2] must be @racket[eq?]. +For values that include no chaperones or other impersonators, +@racket[v1] and @racket[v2] can be considered chaperones of each other +if they are @racket[equal?], except that corresponding mutable +vectors, boxes, strings, byte strings, and mutable structures within +@racket[v1] and @racket[v2] must be @racket[eq?]. -Otherwise, chaperones within @racket[v2] must be intact within -@racket[v1] analogous to way that @racket[impersonator-of?] requires -that impersonators are preserved, except that @racket[prop:impersonator-of] -has no analog for @racket[chaperone-of?].} +Otherwise, chaperones and other impersonators within @racket[v2] must +be intact within @racket[v1] analogous to way that +@racket[impersonator-of?] requires that impersonators are preserved. +Furthermore, @racket[v1] must not have any non-chaperone impersonators +whose corresponding value in @racket[v2] is not the same impersonator. +Note that @racket[chaperone-of?] implies @racket[impersonator-of?], +but not vice-versa.} @defproc[(impersonator-ephemeron [v any/c]) ephemeron?]{ diff --git a/pkgs/racket-test-core/tests/racket/chaperone.rktl b/pkgs/racket-test-core/tests/racket/chaperone.rktl index 03c19ddb3f..124967bd76 100644 --- a/pkgs/racket-test-core/tests/racket/chaperone.rktl +++ b/pkgs/racket-test-core/tests/racket/chaperone.rktl @@ -2680,6 +2680,8 @@ (test #t impersonator-of? (make-a #f 2) a1) (test #t chaperone-of? (make-a #f 2) a1) (test #t impersonator-of? (make-a a1 3) a1) + (test #f impersonator-of? a1 (make-a a1 2)) + (test #f chaperone-of? a1 (make-a a1 2)) (test #t impersonator-of? (make-a-more a1 3 8) a1) (test #f chaperone-of? (make-a a1 3) a1) (test #t equal? (make-a a1 3) a1) diff --git a/racket/src/cs/rumble/equal.ss b/racket/src/cs/rumble/equal.ss index ecd4da07f5..f1d11b068a 100644 --- a/racket/src/cs/rumble/equal.ss +++ b/racket/src/cs/rumble/equal.ss @@ -101,6 +101,11 @@ (or (check-union-find ctx a b) (let ([ctx (deeper-context ctx)]) (equal? (or a2 a) (or b2 b) ctx)))] + [(and (not (eq? mode 'equal?)) + (extract-impersonator-of mode b)) + ;; Second argument is an impersonator, so + ;; `impersonator-of?` or `chaperone-of?` fails + #f] [else ;; No `prop:impersonator-of`, so check for ;; `prop:equal+hash` or transparency diff --git a/racket/src/racket/src/bool.c b/racket/src/racket/src/bool.c index 97534ed109..b855bf7967 100644 --- a/racket/src/racket/src/bool.c +++ b/racket/src/racket/src/bool.c @@ -726,6 +726,14 @@ int is_equal (Scheme_Object *obj1, Scheme_Object *obj2, Equal_Info *eql) if (procs2) { obj2 = procs2; orig_obj2 = obj2; } goto top_after_next; } else { + /* don't discard `prop:impersonator-of` if checking for `impersonator-of?` + or `chaperone-of?` */ + if (eql->for_chaperone) { + procs2 = scheme_struct_type_property_ref(scheme_impersonator_of_property, (Scheme_Object *)st2); + if (procs2 && scheme_apply_impersonator_of(eql->for_chaperone, procs2, obj2)) + return 0; + } + procs1 = scheme_struct_type_property_ref(scheme_equal_property, (Scheme_Object *)st1); if (procs1 && (st1 != st2)) { procs2 = scheme_struct_type_property_ref(scheme_equal_property, (Scheme_Object *)st2);