make parameter/c return impersonator contracts by default (but have an option to

return chaperones if the arguments are chaperones)

possibly related to racket/racket#3852
This commit is contained in:
Robby Findler 2021-05-27 10:13:22 -05:00
parent a7a1f526a1
commit 114a4f89a1
3 changed files with 48 additions and 19 deletions

View File

@ -797,13 +797,22 @@ inspect the entire tree.
@history[#:changed "6.0.1.6" @elem{Added @racket[#:inv].}]
}
@defproc[(parameter/c [in contract?] [out contract? in])
@defproc[(parameter/c [in contract?]
[out contract? in]
[#:impersonator? impersonator? any/c #t])
contract?]{
Produces a contract on parameters whose values must match
@racket[_out]. When the value in the contracted parameter
is set, it must match @racket[_in].
If @racket[impersonator?] is a true value, then
@racket[parameter/c] always returns an @tech{impersonator
contract}. If it is @racket[#f], then the result will be a
@tech{chaperone contract} when both @racket[in] and
@racket[out] are @tech{chaperone contracts}, and an @tech{
impersonator contract} otherwise.
@examples[#:eval (contract-eval) #:once
(define/contract current-snack
(parameter/c string?)

View File

@ -80,12 +80,26 @@
'parameter/c11
'(chaperone-contract?
(parameter/c integer?))
#f)
(test/spec-passed/result
'parameter/c11b
'(chaperone-contract?
(parameter/c integer?
#:impersonator? #f))
#t)
(test/spec-passed/result
'parameter/c12
'(chaperone-contract?
(parameter/c (-> integer? integer?)))
#f)
(test/spec-passed/result
'parameter/c12b
'(chaperone-contract?
(parameter/c (-> integer? integer?)
#:impersonator? #f))
#t)
(test/spec-passed/result
@ -111,7 +125,15 @@
(test/spec-passed/result
'parameter/c16
'(chaperone-contract?
(parameter/c integer?
(-> integer? integer?)
#:impersonator? #f))
#t)
(test/spec-passed/result
'parameter/c16b
'(chaperone-contract?
(parameter/c integer?
(-> integer? integer?)))
#t))
#f))

View File

@ -464,23 +464,21 @@
;; (parameter/c in/out-ctc)
;; (parameter/c in-ctc out-ctc)
(define/subexpression-pos-prop parameter/c
(case-lambda
[(in-ctc)
(define ctc (coerce-contract 'parameter/c in-ctc))
(define unsupplied (gensym))
(define/subexpression-pos-prop (parameter/c in [out unsupplied] #:impersonator? [impersonator? #t])
(define ctc (coerce-contract 'parameter/c in))
(define in-ctc (coerce-contract 'parameter/c in))
(define out-ctc/f
(if (equal? out unsupplied)
#f
(coerce-contract 'parameter/c out)))
(cond
[(chaperone-contract? ctc)
(chaperone-parameter/c ctc #f)]
[(and (not impersonator?)
(chaperone-contract? in-ctc)
(or (not out-ctc/f) (chaperone-contract? out-ctc/f)))
(chaperone-parameter/c in-ctc out-ctc/f)]
[else
(impersonator-parameter/c ctc #f)])]
[(in-ctc out-ctc)
(define in (coerce-contract 'parameter/c in-ctc))
(define out (coerce-contract 'parameter/c out-ctc))
(cond
[(and (chaperone-contract? in) (chaperone-contract? out))
(chaperone-parameter/c in out)]
[else
(impersonator-parameter/c in out)])]))
(impersonator-parameter/c in-ctc out-ctc/f)]))
(define (parameter/c-lnp ctc)
(define in-proc (get/build-late-neg-projection (base-parameter/c-in ctc)))