diff --git a/collects/racket/contract/private/arr-i.rkt b/collects/racket/contract/private/arr-i.rkt index 96bc288e6d..d2a75bf453 100644 --- a/collects/racket/contract/private/arr-i.rkt +++ b/collects/racket/contract/private/arr-i.rkt @@ -183,14 +183,21 @@ kwd-id ...)]) (with-syntax ([((rng-params ...) rng-ctcs) (syntax-case range (any values) - [(values [id ctc/no-prop] ...) - (with-syntax ([(ctc ...) (map (λ (x) (add-indy-prop (syntax-property x 'racket/contract:positive-position this->i))) - (syntax->list #'(ctc/no-prop ...)))]) - #'((id ...) (ctc ...)))] - [(values [id ctc] ... x . y) (raise-syntax-error #f "expected binding pair" stx #'x)] + [(values ctc-pr ...) + (with-syntax ([((id ctc/no-prop) ...) + (map (lambda (x) (syntax-case x () + [[id ctc/no-prop] #'[id ctc/no-prop]] + [[id (id2 ...) ctc/no-prop] #'[id ctc/no-prop]] + [x (raise-syntax-error #f "expected binding pair" stx #'x)])) + (syntax->list #'(ctc-pr ...)))]) + (with-syntax ([(ctc ...) (map (λ (x) (add-indy-prop (syntax-property x 'racket/contract:positive-position this->i))) + (syntax->list #'(ctc/no-prop ...)))]) + #'((id ...) (ctc ...))))] [any #'(() #f)] [[id ctc] #`((id) (#,(add-indy-prop (syntax-property #'ctc 'racket/contract:positive-position this->i))))] + [[id (id2 ...) ctc] + #`((id) (#,(add-indy-prop (syntax-property #'ctc 'racket/contract:positive-position this->i))))] [x (raise-syntax-error #f "expected binding pair or any" stx #'x)])] [mtd? (and (syntax-parameter-value #'making-a-method) #t)]) (let ([rng-underscores? diff --git a/collects/tests/racket/contract-test.rktl b/collects/tests/racket/contract-test.rktl index 100f2d4995..1935a7ac8f 100644 --- a/collects/tests/racket/contract-test.rktl +++ b/collects/tests/racket/contract-test.rktl @@ -182,11 +182,18 @@ (test/no-error '(->d ([x integer?] #:z [z integer?]) ([y integer?] #:w [w integer?]) #:rest rest any/c (range boolean?))) (test/no-error '(->d ([x integer?] #:z [z integer?]) #:rest rest any/c (range boolean?))) + (test/no-error '(->i ([x integer?]) ([y integer?]) any)) + (test/no-error '(->i ([x integer?]) ([y integer?]) (values [a number?] [b boolean?]))) + (test/no-error '(->i ([x integer?] #:z [z integer?]) ([y integer?] #:w [w integer?]) (range boolean?))) + (test/no-error '(->i ([x integer?] #:z [z integer?]) ([y integer?] #:w [w integer?]) #:rest rest any/c (range boolean?))) + (test/no-error '(->i ([x integer?] #:z [z integer?]) #:rest rest any/c (range boolean?))) + (test/no-error '(unconstrained-domain-> number?)) (test/no-error '(unconstrained-domain-> (flat-contract number?))) (test/no-error '(listof any/c)) (test/no-error '(listof (lambda (x) #t))) + (test/no-error '(((lambda (x) x) listof) #t)) (test/no-error '(non-empty-listof any/c)) (test/no-error '(non-empty-listof (lambda (x) #t))) @@ -1736,6 +1743,774 @@ 1 2 3 4 5) '(1 2 3 4 5)) + +; +; +; +; +; ;; +; ; ;; +; ; +; ;; ;; +; ;;;; ;; ;; +; ;;; ;; +; ;;; ;; +; ;; ;; +; ; ;; +; +; +; + + (test/spec-passed + '->i1 + '((contract (->i () () [x number?]) (lambda () 1) 'pos 'neg))) + + (test/spec-passed + '->i2 + '((contract (->i ([x number?]) () (values [r number?])) (lambda (x) (+ x 1)) 'pos 'neg) 1)) + + (test/pos-blame + '->i3 + '((contract (->i () () [r number?]) 1 'pos 'neg))) + + (test/pos-blame + '->i4 + '((contract (->i () () [r number?]) (lambda (x) x) 'pos 'neg))) + + (test/neg-blame + '->i5 + '((contract (->i ([x number?]) () any) (lambda (x) (+ x 1)) 'pos 'neg) #f)) + + (test/pos-blame + '->i6 + '((contract (->i ([x number?]) () [r (x) (<=/c x)]) (lambda (x) (+ x 1)) 'pos 'neg) 1)) + + (test/spec-passed + '->i7 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () [r (x) (<=/c x)]) (lambda (x y) (- x 1)) 'pos 'neg) 1 0)) + + (test/neg-blame + '->i8 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () [r (x) (<=/c x)]) (lambda (x y) (+ x 1)) 'pos 'neg) 1 2)) + + (test/spec-passed + '->i9 + '((contract (->i ([y (<=/c x)] [x (x) number?]) () [r (x) (<=/c x)]) (lambda (y x) (- x 1)) 'pos 'neg) 1 2)) + + (test/neg-blame + '->i10 + '((contract (->i ([y (<=/c x)] [x (x) number?]) () [r (x) (<=/c x)]) (lambda (y x) (+ x 1)) 'pos 'neg) 1 0)) + + (test/spec-passed + '->i11 + '((contract (->i () () #:rest rest any/c [r number?]) (lambda x 1) 'pos 'neg))) + + (test/spec-passed + '->i12 + '((contract (->i ([x number?]) () #:rest rest any/c [r number?]) (lambda (x . y) (+ x 1)) 'pos 'neg) 1)) + + (test/pos-blame + '->i13 + '((contract (->i () () #:rest rest any/c [r number?]) 1 'pos 'neg))) + + (test/pos-blame + '->i14 + '((contract (->i () () #:rest rest any/c [r number?]) (lambda (x) x) 'pos 'neg))) + + (test/neg-blame + '->i15 + '((contract (->i ([x number?]) () #:rest rest any/c any) (lambda (x . y) (+ x 1)) 'pos 'neg) #f)) + + (test/pos-blame + '->i16 + '((contract (->i ([x number?]) () #:rest rest any/c [r (x) (<=/c x)]) (lambda (x . y) (+ x 1)) 'pos 'neg) 1)) + + (test/spec-passed + '->i17 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () #:rest rest any/c [r (x) (<=/c x)]) (lambda (x y . z) (- x 1)) 'pos 'neg) 1 0)) + + (test/neg-blame + '->i18 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () #:rest rest any/c [r (x) (<=/c x)]) (lambda (x y . z) (+ x 1)) 'pos 'neg) 1 2)) + + (test/spec-passed + '->i19 + '((contract (->i ([y (x) (<=/c x)] [x number?]) () #:rest rest any/c [r (x) (<=/c x)]) (lambda (y x . z) (- x 1)) 'pos 'neg) 1 2)) + + (test/neg-blame + '->i20 + '((contract (->i ([y (x) (<=/c x)] [x number?]) () #:rest rest any/c [r (x) (<=/c x)]) (lambda (y x . z) (+ x 1)) 'pos 'neg) 1 0)) + + (test/spec-passed + '->i21 + '((contract (->i () () #:rest rst (listof number?) [r any/c]) (lambda w 1) 'pos 'neg) 1)) + + (test/neg-blame + '->i22 + '((contract (->i () () #:rest rst (listof number?) [r any/c]) (lambda w 1) 'pos 'neg) #f)) + + (test/spec-passed + '->i-any1 + '((contract (->i () () any) (lambda () 1) 'pos 'neg))) + + (test/spec-passed + '->i-any2 + '((contract (->i ([x number?]) () any) (lambda (x) (+ x 1)) 'pos 'neg) 1)) + + (test/pos-blame + '->i-any3 + '((contract (->i () () any) 1 'pos 'neg))) + + (test/pos-blame + '->i-any4 + '((contract (->i () () any) (lambda (x) x) 'pos 'neg))) + + (test/neg-blame + '->i-any5 + '((contract (->i ([x number?]) () any) (lambda (x) (+ x 1)) 'pos 'neg) #f)) + + (test/spec-passed + '->i-any6 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () any) (lambda (x y) (- x 1)) 'pos 'neg) 1 0)) + + (test/neg-blame + '->i-any7 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () any) (lambda (x y) (+ x 1)) 'pos 'neg) 1 2)) + + (test/spec-passed + '->i-any8 + '((contract (->i ([y (x) (<=/c x)] [x number?]) () any) (lambda (y x) (- x 1)) 'pos 'neg) 1 2)) + + (test/neg-blame + '->i-any9 + '((contract (->i ([y (x) (<=/c x)] [x number?]) () any) (lambda (y x) (+ x 1)) 'pos 'neg) 1 0)) + + (test/spec-passed + '->i-any10 + '((contract (->i () () #:rest rest any/c any) (lambda x 1) 'pos 'neg))) + + (test/spec-passed + '->i-any11 + '((contract (->i ([x number?]) () #:rest rest any/c any) (lambda (x . y) (+ x 1)) 'pos 'neg) 1)) + + (test/pos-blame + '->i-any12 + '((contract (->i () () #:rest rest any/c any) 1 'pos 'neg))) + + (test/pos-blame + '->i-any13 + '((contract (->i () () #:rest rest any/c any) (lambda (x) x) 'pos 'neg))) + + (test/neg-blame + '->i-any14 + '((contract (->i ([x number?]) () #:rest rest any/c any) (lambda (x . y) (+ x 1)) 'pos 'neg) #f)) + + (test/spec-passed + '->i-any15 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () #:rest rest any/c any) (lambda (x y . z) (- x 1)) 'pos 'neg) 1 0)) + + (test/neg-blame + '->i-any16 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () #:rest rest any/c any) (lambda (x y . z) (+ x 1)) 'pos 'neg) 1 2)) + + (test/spec-passed + '->i-any17 + '((contract (->i ([y (x) (<=/c x)] [x number?]) () #:rest rest any/c any) (lambda (y x . z) (- x 1)) 'pos 'neg) 1 2)) + + (test/neg-blame + '->i-any18 + '((contract (->i ([y (x) (<=/c x)] [x number?]) () #:rest rest any/c any) (lambda (y x . z) (+ x 1)) 'pos 'neg) 1 0)) + + (test/spec-passed + '->i-any19 + '((contract (->i () () #:rest rst (listof number?) any) (lambda w 1) 'pos 'neg) 1)) + + (test/neg-blame + '->i-any20 + '((contract (->i () () #:rest rst (listof number?) any) (lambda w 1) 'pos 'neg) #f)) + + (test/spec-passed + '->i-values1 + '((contract (->i () () (values [x boolean?] [y number?])) (lambda () (values #t 1)) 'pos 'neg))) + + (test/spec-passed + '->i-values2 + '((contract (->i ([x number?]) () (values [z boolean?] [y number?])) (lambda (x) (values #t (+ x 1))) 'pos 'neg) 1)) + + (test/pos-blame + '->i-values3 + '((contract (->i () () (values [x boolean?] [y number?])) 1 'pos 'neg))) + + (test/pos-blame + '->i-values4 + '((contract (->i () () (values [x boolean?] [y number?])) (lambda (x) x) 'pos 'neg))) + + (test/neg-blame + '->i-values5 + '((contract (->i ([x number?]) () (values [y boolean?] [z (x) (<=/c x)])) (lambda (x) (+ x 1)) 'pos 'neg) #f)) + + (test/pos-blame + '->i-values6 + '((contract (->i ([x number?]) () (values [y boolean?] [z (x) (<=/c x)])) (lambda (x) (values #t (+ x 1))) 'pos 'neg) 1)) + + (test/spec-passed + '->i-values7 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () (values [z boolean?] [w (<=/c x)])) + (lambda (x y) (values #t (- x 1))) + 'pos + 'neg) + 1 + 0)) + + (test/neg-blame + '->i-values8 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () (values [z boolean?] [w (x) (<=/c x)])) + (lambda (x y) (values #f (+ x 1))) + 'pos + 'neg) + 1 + 2)) + + (test/spec-passed + '->i-values9 + '((contract (->i ([y (x) (<=/c x)] [x number?]) () (values [z boolean?] [w (x) (<=/c x)])) + (lambda (y x) (values #f (- x 1))) + 'pos + 'neg) + 1 + 2)) + + (test/neg-blame + '->i-values10 + '((contract (->i ([y (x) (<=/c x)] [x number?]) () (values [z boolean?] [w (x) (<=/c x)])) + (lambda (y x) (values #f (+ x 1))) 'pos 'neg) + 1 0)) + + (test/spec-passed + '->i-values11 + '((contract (->i () () #:rest rest any/c (values [z boolean?] [w number?])) (lambda x (values #f 1)) 'pos 'neg))) + + (test/spec-passed + '->i-values12 + '((contract (->i ([x number?]) () #:rest rest any/c (values [z boolean?] [w number?])) + (lambda (x . y) (values #f (+ x 1))) + 'pos + 'neg) + 1)) + + (test/pos-blame + '->i-values13 + '((contract (->i () () #:rest rest any/c (values [z boolean?] [w number?])) 1 'pos 'neg))) + + (test/pos-blame + '->i-values14 + '((contract (->i () () #:rest rest any/c (values [z boolean?] [w number?])) (lambda (x) x) 'pos 'neg))) + + (test/neg-blame + '->i-values15 + '((contract (->i ([x number?]) () #:rest rest any/c (values [z boolean?] [w (x) (<=/c x)])) + (lambda (x . y) (+ x 1)) 'pos 'neg) + #f)) + + (test/pos-blame + '->i-values16 + '((contract (->i ([x number?]) () #:rest rest any/c (values [z boolean?] [w (x) (<=/c x)])) + (lambda (x . y) (values #f (+ x 1))) 'pos 'neg) + 1)) + + (test/spec-passed + '->i-values17 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () #:rest rest any/c (values [z boolean?] [w (x) (<=/c x)])) + (lambda (x y . z) (values #f (- x 1))) 'pos 'neg) + 1 0)) + + (test/neg-blame + '->i-values18 + '((contract (->i ([x number?] [y (x) (<=/c x)]) () #:rest rest any/c (values [z boolean?] [w (x) (<=/c x)])) + (lambda (x y . z) (values #f (+ x 1))) 'pos 'neg) + 1 2)) + + (test/spec-passed + '->i-values19 + '((contract (->i ([y (x) (<=/c x)] [x number?]) () #:rest rest any/c (values [z boolean?] [w (x) (<=/c x)])) + (lambda (y x . z) (values #f (- x 1))) 'pos 'neg) + 1 2)) + + (test/neg-blame + '->i-values20 + '((contract (->i ([y (x) (<=/c x)] [x number?]) () #:rest rest any/c (values [z boolean?] [w (x) (<=/c x)])) + (lambda (y x . z) (values #f (+ x 1))) 'pos 'neg) + 1 0)) + + (test/spec-passed + '->i-values21 + '((contract (->i () () #:rest rst (listof number?) (values [z boolean?] [w any/c])) (lambda w (values #f 1)) 'pos 'neg) 1)) + + (test/neg-blame + '->i-values22 + '((contract (->i () () #:rest rst (listof number?) (values [z boolean?] [w any/c])) (lambda w (values #f 1)) 'pos 'neg) #f)) + + (test/spec-passed + '->i-values23 + '((contract (->i () () (values [x number?] [y (x) (>=/c x)])) (lambda () (values 1 2)) 'pos 'neg))) + + (test/pos-blame + '->i-values24 + '((contract (->i () () (values [x number?] [y (x) (>=/c x)])) (lambda () (values 2 1)) 'pos 'neg))) + + (test/spec-passed + '->i-values25 + '((contract (->i ([x number?]) () (values [z number?] [y (x) (>=/c x)])) (lambda (x) (values 1 2)) 'pos 'neg) 1)) + + (test/pos-blame + '->i-values26 + '((contract (->i ([x number?]) () (values [z number?] [y (x) (>=/c x)])) (lambda (x) (values 2 1)) 'pos 'neg) 4)) + + (test/spec-passed/result + '->i23 + '((contract (->i ((i number?) (j (and/c number? (>=/c i)))) () [r number?]) + (λ (i j) 1) + 'pos + 'neg) + 1 + 2) + 1) + + (test/spec-passed/result + '->i24 + '((contract (->i ([i number?] [j (i) (and/c number? (>=/c i))]) () any) + (λ (i j) 1) + 'pos + 'neg) + 1 + 2) + 1) + + (test/spec-passed/result + '->i25 + '(call-with-values + (λ () + ((contract (->i ((i number?) (j (i) (and/c number? (>=/c i)))) () (values [x number?] [y number?])) + (λ (i j) (values 1 2)) + 'pos + 'neg) + 1 + 2)) + list) + '(1 2)) + + (test/spec-passed/result + '->i26 + '((contract (->i ((i number?) (j (i) (and/c number? (>=/c i)))) () #:rest rest-args any/c [r number?]) + (λ (i j . z) 1) + 'pos + 'neg) + 1 + 2) + 1) + + (test/spec-passed/result + '->i27 + '((contract (->i ((i number?) (j (i) (and/c number? (>=/c i)))) () #:rest rest-args any/c any) + (λ (i j . z) 1) + 'pos + 'neg) + 1 + 2) + 1) + + (test/spec-passed/result + '->i28 + '(call-with-values + (λ () + ((contract (->i ((i number?) (j (i) (and/c number? (>=/c i)))) () #:rest rest-args any/c (values [x number?] [y number?])) + (λ (i j . z) (values 1 2)) + 'pos + 'neg) + 1 + 2)) + list) + '(1 2)) + + (test/neg-blame + '->i30 + '((contract (->i ([x number?]) () #:rest rst number? any) + (λ (x . rst) (values 4 5)) + 'pos + 'neg) + #f)) + + (test/pos-blame + '->i-arity1 + '(contract (->i ([x number?]) () any) (λ () 1) 'pos 'neg)) + + (test/pos-blame + '->i-arity2 + '(contract (->i ([x number?]) () any) (λ (x #:y y) 1) 'pos 'neg)) + + (test/spec-passed + '->i-arity3 + '(contract (->i ([x number?] #:y [y integer?]) () any) (λ (x #:y y) 1) 'pos 'neg)) + + (test/pos-blame + '->i-arity4 + '(contract (->i () ([x integer?]) any) (λ (x) 1) 'pos 'neg)) + + (test/pos-blame + '->i-arity5 + '(contract (->i () ([x integer?]) any) (λ () 1) 'pos 'neg)) + + (test/spec-passed + '->i-arity6 + '(contract (->i () ([x integer?]) any) (λ ([x 1]) 1) 'pos 'neg)) + + (test/pos-blame + '->i-arity7 + '(contract (->i () (#:x [x integer?]) any) (λ ([x 1]) 1) 'pos 'neg)) + + (test/pos-blame + '->i-arity8 + '(contract (->i () (#:x [x integer?]) any) (λ () 1) 'pos 'neg)) + + (test/pos-blame + '->i-arity8 + '(contract (->i () (#:x [x integer?]) any) (λ (#:x x) 1) 'pos 'neg)) + + (test/spec-passed + '->i-arity10 + '(contract (->i () (#:x [x integer?]) any) (λ (#:x [x 1]) 1) 'pos 'neg)) + + (test/pos-blame + '->i-pp1 + '((contract (->i ([x number?]) () #:pre-cond (= x 1) [result number?] #:post-cond (= x 2)) + (λ (x) x) + 'pos + 'neg) + 1)) + + (test/neg-blame + '->i-pp2 + '((contract (->i ([x number?]) () #:pre-cond (= x 1) [result number?] #:post-cond (= x 2)) + (λ (x) x) + 'pos + 'neg) + 2)) + + (test/pos-blame + '->i-pp3 + '((contract (->i ([x number?]) () #:pre-cond (= x 1) [result number?] #:post-cond (= result 2)) + (λ (x) x) + 'pos + 'neg) + 1)) + + (test/spec-passed + '->i-pp3.5 + '((contract (->i ([x number?]) () #:pre-cond (= x 1) [result number?] #:post-cond (= result 2)) + (λ (x) 2) + 'pos + 'neg) + 1)) + + (test/neg-blame + '->i-pp4 + '((contract (->i ([x number?]) () #:pre-cond (= x 1) any) + (λ (x) x) + 'pos + 'neg) + 2)) + + (test/neg-blame + '->i-pp5 + '((contract (->i ([x number?]) () #:pre-cond (= x 1) (values [z number?] [y number?]) #:post-cond (= x y z 3)) + (λ (x) (values 4 5)) + 'pos + 'neg) + 2)) + + (test/pos-blame + '->i-pp6 + '((contract (->i ([x number?]) () #:pre-cond (= x 1) (values [z number?] [y number?]) #:post-cond (= z y 3)) + (λ (x) (values 4 5)) + 'pos + 'neg) + 1)) + + (test/pos-blame + '->i-pp-r1 + '((contract (->i ([x number?]) () #:rest rst any/c #:pre-cond (= x 1) [result number?] #:post-cond (= x 2)) + (λ (x . rst) x) + 'pos + 'neg) + 1)) + + (test/neg-blame + '->i-pp-r2 + '((contract (->i ([x number?]) () #:rest rst any/c #:pre-cond (= x 1) [result number?] #:post-cond (= x 2)) + (λ (x . rst) x) + 'pos + 'neg) + 2)) + + (test/pos-blame + '->i-pp-r3 + '((contract (->i ([x number?]) () #:rest rst any/c #:pre-cond (= x 1) [result number?] #:post-cond (= result 2)) + (λ (x . rst) x) + 'pos + 'neg) + 1)) + + (test/spec-passed + '->i-pp-r3.5 + '((contract (->i ([x number?]) () #:rest rst any/c #:pre-cond (= x 1) [result number?] #:post-cond (= result 2)) + (λ (x . rst) 2) + 'pos + 'neg) + 1)) + + (test/neg-blame + '->i-pp-r4 + '((contract (->i ([x number?]) () #:rest rst any/c #:pre-cond (= x 1) any) + (λ (x . rst) x) + 'pos + 'neg) + 2)) + + (test/neg-blame + '->i-pp-r5 + '((contract (->i ([x number?]) () #:rest rst any/c #:pre-cond (= x 1) (values [z number?] [y number?]) #:post-cond (= x y z 3)) + (λ (x . rst) (values 4 5)) + 'pos + 'neg) + 2)) + + (test/pos-blame + '->i-pp-r6 + '((contract (->i ([x number?]) () #:rest rst any/c #:pre-cond (= x 1) (values [z number?] [y number?]) #:post-cond (= z x y 3)) + (λ (x . rst) (values 4 5)) + 'pos + 'neg) + 1)) + + (test/neg-blame + '->i-protect-shared-state + '(let ([x 1]) + ((contract (let ([save #f]) + (-> (->i () () #:pre-cond (set! save x) [range any/c] #:post-cond (= save x)) + any)) + (λ (t) (t)) + 'pos + 'neg) + (lambda () (set! x 2))))) + + + (test/spec-passed + '->i-optopt1 + '((contract (->i ([x number?]) any) + (λ (x) x) + 'pos 'neg) + 1)) + + (test/spec-passed + '->i-optopt2 + '((contract (->i ([x number?]) #:rest rst any/c any) + (λ (x . y) x) + 'pos 'neg) + 1)) + + (test/spec-passed + '->i-optopt3 + '((contract (->i ([x number?]) #:pre-cond #t any) + (λ (x) x) + 'pos 'neg) + 1)) + + (test/spec-passed + '->i-optopt4 + '((contract (->i ([x number?]) #:rest rst any/c #:pre-cond #t any) + (λ (x . y) x) + 'pos 'neg) + 1)) + + (test/spec-passed + '->i-optopt5 + '((contract (->i ([x number?]) #:rest rst any/c #:pre-cond #t [res any/c] #:post-cond #t) + (λ (x . y) x) + 'pos 'neg) + 1)) + + (test/spec-passed + '->i-optopt6 + '((contract (->i ([x number?]) #:rest rst any/c [res any/c] #:post-cond #t) + (λ (x . y) x) + 'pos 'neg) + 1)) + + (test/spec-passed + '->i-optopt7 + '((contract (->i ([x number?]) #:pre-cond #t [res any/c] #:post-cond #t) + (λ (x . y) x) + 'pos 'neg) + 1)) + + (test/spec-passed + '->i-optopt8 + '((contract (->i ([x number?]) [res any/c] #:post-cond #t) + (λ (x . y) x) + 'pos 'neg) + 1)) + + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + ;; make sure the variables are all bound properly + ;; + + (test/spec-passed + '->i-binding1 + '((contract (->i ([x number?]) () #:rest rest any/c [range any/c] #:post-cond (equal? rest '(2 3 4))) + (λ (x . y) y) + 'pos + 'neg) + 1 2 3 4)) + + (test/spec-passed + '->i-binding2 + '((contract (->i ([x number?]) () #:rest rest any/c [range any/c] #:post-cond (equal? x 1)) + (λ (x . y) y) + 'pos + 'neg) + 1 2 3 4)) + + (test/spec-passed + '->i-binding3 + '(let ([p 'p] + [q 'q] + [r 'r]) + ((contract (->i ([x number?] [y number?] #:z [z number?] #:w [w number?]) + ([a number?] [b number?] #:c [c number?] #:d [d number?]) + #:rest rest any/c + #:pre-cond (equal? (list x y z w a b c d rest p q r) + (list 1 2 3 4 5 6 7 8 '(z) 'p 'q 'r)) + (values [p number?] [q number?] [r number?])) + (λ (x y #:z z #:w w [a 101] [b 102] #:c [c 103] #:d [d 104] . rest) + (values 11 12 13)) + 'pos + 'neg) + 1 2 #:z 3 #:w 4 5 6 #:c 7 #:d 8 'z))) + + (test/spec-passed + '->i-binding4 + '((contract (->i ([x number?] [y number?] #:z [z number?] #:w [w number?]) + ([a number?] [b number?] #:c [c number?] #:d [d number?]) + #:rest rest any/c + (values [p number?] [q number?] [r number?]) + #:post-cond (equal? (list x y z w a b c d rest p q r) + (list 1 2 3 4 5 6 7 8 '(z) 11 12 13))) + (λ (x y #:z z #:w w [a 101] [b 102] #:c [c 103] #:d [d 104] . rest) + (values 11 12 13)) + 'pos + 'neg) + 1 2 #:z 3 #:w 4 5 6 #:c 7 #:d 8 'z)) + + (test/spec-passed + '->i-binding5 + '(let ([p 'p] + [q 'q] + [r 'r]) + ((contract (->i ([x number?] [y number?] #:z [z number?] #:w [w number?]) + ([a number?] [b number?] #:c [c number?] #:d [d number?]) + #:rest rest any/c + #:pre-cond (equal? (list x y z w a b c d rest p q r) + (list 1 2 3 4 + the-unsupplied-arg the-unsupplied-arg the-unsupplied-arg the-unsupplied-arg + '() 'p 'q 'r)) + (values [p number?] [q number?] [r number?])) + (λ (x y #:z z #:w w [a 101] [b 102] #:c [c 103] #:d [d 104] . rest) + (values 11 12 13)) + 'pos + 'neg) + 1 2 #:z 3 #:w 4))) + + (test/spec-passed + '->i-binding6 + '((contract (->i ([x number?] [y number?] #:z [z number?] #:w [w number?]) + ([a number?] [b number?] #:c [c number?] #:d [d number?]) + #:rest rest any/c + (values [p number?] [q number?] [r number?]) + #:post-cond (equal? (list x y z w a b c d rest p q r) + (list 1 2 3 4 + the-unsupplied-arg the-unsupplied-arg the-unsupplied-arg the-unsupplied-arg + '() 11 12 13))) + (λ (x y #:z z #:w w [a 101] [b 102] #:c [c 103] #:d [d 104] . rest) + (values 11 12 13)) + 'pos + 'neg) + 1 2 #:z 3 #:w 4)) + + ;; test that the rest parameter is right when there aren't enough arguments to even make it to the rest parameter + (test/spec-passed + '->i-binding7 + '((contract (->i () + ([a number?]) + #:rest rest any/c + [_ any/c] + #:post-cond (equal? (list a rest) (list the-unsupplied-arg '()))) + (λ ([a 1] . rest) 1) + 'pos + 'neg))) + + (test/pos-blame + '->i-underscore1 + '((contract (->i ([b (box/c integer?)]) + () + [_ (let ([old (unbox b)]) + (and/c + void? + (λ (new) + (= old (unbox b)))))]) + (λ (b) + (set-box! b (+ (unbox b) 1))) + 'pos + 'neg) + (box 1))) + + (test/spec-passed/result + '->i-underscore2 + '(let ([x '()]) + ((contract (->i () () [_ (begin (set! x (cons 'ctc x)) any/c)]) + (λ () (set! x (cons 'body x))) + 'pos + 'neg)) + x) + '(body ctc)) + + (test/spec-passed/result + '->i-underscore3 + '(let ([x '()]) + ((contract (->i () () [res (begin (set! x (cons 'ctc x)) any/c)]) + (λ () (set! x (cons 'body x))) + 'pos + 'neg)) + x) + '(ctc body)) + + (test/spec-passed/result + '->i-underscore4 + '((contract (->i ([str any/c]) () #:rest rest (listof any/c) [_ any/c]) + (λ (x . y) (cons x y)) + 'pos 'neg) + 1 2 3) + '(1 2 3)) + + (test/spec-passed/result + '->i-underscore5 + '((contract (->i ([str any/c]) () #:rest rest (listof any/c) [_ any/c]) + (λ (x . y) (cons x y)) + 'pos 'neg) + 1 2 3 4 5) + '(1 2 3 4 5)) + ; ; ; @@ -4063,6 +4838,284 @@ 'neg) m)) + (test/spec-passed + 'object-contract-->i1 + '(send (contract (object-contract (m (->i ([x number?]) () [range (x) (<=/c x)]))) + (new (class object% (define/public m (lambda (x) (- x 1))) (super-new))) + 'pos + 'neg) + m + 1)) + + (test/spec-passed + 'object-contract-->i1b + '(send (contract (object-contract (m (->i ([x number?]) () [range (i) (<=/c x)]))) + (new (class object% (define/public m (lambda (x) (- x 1))) (super-new))) + 'pos + 'neg) + m + 1)) + + (test/pos-blame + 'object-contract-->i2 + '(send (contract (object-contract (m (->i ([x number?]) () [range (i) (<=/c x)]))) + (new (class object% (define/public m (lambda (x) (+ x 1))) (super-new))) + 'pos + 'neg) + m + 1)) + + (test/pos-blame + 'object-contract-->i2b + '(send (contract (object-contract (m (->i ([x number?]) () [range (x) (<=/c x)]))) + (new (class object% (define/public m (lambda (x) (+ x 1))) (super-new))) + 'pos + 'neg) + m + 1)) + + (test/spec-passed + 'object-contract-->i3 + '(send (contract (object-contract (m (->i () () #:rest rst (listof number?) [range any/c]))) + (new (class object% (define/public m (lambda w 1)) (super-new))) + 'pos + 'neg) + m + 1)) + + (test/neg-blame + 'object-contract-->i4 + '(send (contract (object-contract (m (->i () () #:rest rst (listof number?) [range any/c]))) + (new (class object% (define/public m (lambda w 1)) (super-new))) + 'pos + 'neg) + m + #f)) + + (test/spec-passed + 'object-contract-->i5 + '(send (contract (object-contract (m (->i () () any))) + (new (class object% (define/public m (lambda () 1)) (super-new))) + 'pos + 'neg) + m)) + + (test/spec-passed + 'object-contract-->i6 + '(send (contract (object-contract (m (->i () () (values [x number?] [y (x) (>=/c x)])))) + (new (class object% (define/public m (lambda () (values 1 2))) (super-new))) + 'pos + 'neg) + m)) + + (test/pos-blame + 'object-contract-->i7 + '(send (contract (object-contract (m (->i () () (values [x number?] [y (x) (>=/c x)])))) + (new (class object% (define/public m (lambda () (values 2 1))) (super-new))) + 'pos + 'neg) + m)) + + (test/neg-blame + 'object-contract-->i/this-1 + '(send (contract (object-contract (m (->i ([x (and/c integer? (lambda (x) (= x (get-field f this))))]) + () + any))) + (new (class object% (field [f 1]) (define/public m (lambda (x) 1)) (super-new))) + 'pos + 'neg) + m + 2)) + + (test/spec-passed + 'object-contract-->i/this-2 + '(send (contract (object-contract (m (->i ([x (and/c integer? (lambda (x) (= x (get-field f this))))]) + () + any))) + (new (class object% (field [f 1]) (define/public m (lambda (x) 1)) (super-new))) + 'pos + 'neg) + m + 1)) + + (test/neg-blame + 'object-contract-->i/this-3 + '(send (contract (object-contract (m (->i ([x (and/c integer? (lambda (x) (= x (get-field f this))))]) + () + #:rest rest-var any/c + any))) + (new (class object% (field [f 1]) (define/public m (lambda (x . rest) 1)) (super-new))) + 'pos + 'neg) + m + 2)) + + (test/spec-passed + 'object-contract-->i/this-4 + '(send (contract (object-contract (m (->i ([x (and/c integer? (lambda (x) (= x (get-field f this))))]) + () + #:rest rest-var any/c + any))) + (new (class object% (field [f 1]) (define/public m (lambda (x . rest) 1)) (super-new))) + 'pos + 'neg) + m + 1)) + + (test/spec-passed + 'object-contract-->i-pp1 + '(send (contract (object-contract (m (->i ([x number?]) () #:pre-cond #t [unused (x) (<=/c x)] #:post-cond #t))) + (new (class object% (define/public m (lambda (x) (- x 1))) (super-new))) + 'pos + 'neg) + m + 1)) + + (test/spec-passed + 'object-contract-->i-pp1b + '(send (contract (object-contract (m (->i ([x number?]) () #:pre-cond #t [unused (x) (<=/c x)] #:post-cond #t))) + (new (class object% + (define/public m (case-lambda [(x) (- x 1)] + [(x y) y])) + (super-new))) + 'pos + 'neg) + m + 1)) + + (test/pos-blame + 'object-contract-->i-pp2 + '(send (contract (object-contract (m (->i ([x number?]) () #:pre-cond #t [unused (x) (<=/c x)] #:post-cond #t))) + (new (class object% (define/public m (lambda (x) (+ x 1))) (super-new))) + 'pos + 'neg) + m + 1)) + + (test/pos-blame + 'object-contract-->i-pp2b + '(send (contract (object-contract (m (->i ([x number?]) () #:pre-cond #t [unused (x) (<=/c x)] #:post-cond #t))) + (new (class object% + (define/public m (case-lambda [(x) (+ x 1)])) + (super-new))) + 'pos + 'neg) + m + 1)) + + (test/spec-passed + 'object-contract-->i-pp3 + '(send (contract (object-contract (m (->i () () #:rest rst (listof number?) #:pre-cond #t [unused any/c] #:post-cond #t))) + (new (class object% (define/public m (lambda w 1)) (super-new))) + 'pos + 'neg) + m + 1)) + + (test/neg-blame + 'object-contract-->i-pp4 + '(send (contract (object-contract (m (->i () () #:rest rst (listof number?) #:pre-cond #t [unused any/c] #:post-cond #t))) + (new (class object% (define/public m (lambda w 1)) (super-new))) + 'pos + 'neg) + m + #f)) + + (test/spec-passed + 'object-contract-->i-pp5 + '(send (contract (object-contract (m (->i () () #:pre-cond #t any))) + (new (class object% (define/public m (lambda () 1)) (super-new))) + 'pos + 'neg) + m)) + + (test/spec-passed + 'object-contract-->i-pp6 + '(send (contract (object-contract (m (->i () () #:pre-cond #t (values [x number?] [y (x) (>=/c x)]) #:post-cond #t))) + (new (class object% (define/public m (lambda () (values 1 2))) (super-new))) + 'pos + 'neg) + m)) + + (test/pos-blame + 'object-contract-->i-pp7 + '(send (contract (object-contract (m (->i () () #:pre-cond #t (values [x number?] [y (>=/c x)]) #:post-cond #t))) + (new (class object% (define/public m (lambda () (values 2 1))) (super-new))) + 'pos + 'neg) + m)) + + (test/neg-blame + 'object-contract-->i-pp/this-1 + '(send (contract (object-contract (m (->i () + () + #:pre-cond (= 1 (get-field f this)) + [result-x any/c] + #:post-cond (= 2 (get-field f this))))) + (new (class object% (field [f 2]) (define/public m (lambda () (set! f 3))) (super-new))) + 'pos + 'neg) + m)) + + (test/pos-blame + 'object-contract-->i-pp/this-2 + '(send (contract (object-contract (m (->i () () + #:pre-cond (= 1 (get-field f this)) + [result-x any/c] + #:post-cond (= 2 (get-field f this))))) + (new (class object% (field [f 1]) (define/public m (lambda () (set! f 3))) (super-new))) + 'pos + 'neg) + m)) + + (test/spec-passed + 'object-contract-->i-pp/this-3 + '(send (contract (object-contract (m (->i () () + #:pre-cond (= 1 (get-field f this)) + [result-x any/c] + #:post-cond (= 2 (get-field f this))))) + (new (class object% (field [f 1]) (define/public m (lambda () (set! f 2))) (super-new))) + 'pos + 'neg) + m)) + + (test/neg-blame + 'object-contract-->i-pp/this-4 + '(send (contract (object-contract (m (->i () () + #:rest rest-id any/c + #:pre-cond (= 1 (get-field f this)) + [result-x any/c] + #:post-cond (= 2 (get-field f this))))) + (new (class object% (field [f 2]) (define/public m (lambda args (set! f 3))) (super-new))) + 'pos + 'neg) + m)) + + (test/pos-blame + 'object-contract-->i-pp/this-5 + '(send (contract (object-contract (m (->i () () + #:rest rest-id any/c + #:pre-cond (= 1 (get-field f this)) + [result-x any/c] + #:post-cond (= 2 (get-field f this))))) + (new (class object% (field [f 1]) (define/public m (lambda args (set! f 3))) (super-new))) + 'pos + 'neg) + m)) + + (test/spec-passed + 'object-contract-->i-pp/this-6 + '(send (contract (object-contract (m (->i () () + #:rest rest-id any/c + #:pre-cond (= 1 (get-field f this)) + [result-x any/c] + #:post-cond (= 2 (get-field f this))))) + (new (class object% (field [f 1]) (define/public m (lambda args (set! f 2))) (super-new))) + 'pos + 'neg) + m)) + + (test/spec-passed/result 'object-contract-drop-method1 '(send (contract (object-contract (m (-> integer? integer?))) @@ -4131,7 +5184,7 @@ (test/spec-passed/result 'object-contract-ho-method3 - '(send (contract (object-contract (m (-> (->d ([x integer?]) () [r integer?]) integer?))) + '(send (contract (object-contract (m (-> (->i ([x integer?]) () [r integer?]) integer?))) (new (class object% (define/public (m f) (f 1)) (super-new))) 'pos 'neg) @@ -7240,6 +8293,9 @@ so that propagation occurs. (define (contract-inferred-name-test4) 7) (provide/contract (contract-inferred-name-test4 (->d () () any))) + (define (contract-inferred-name-test5) 7) + (provide/contract (contract-inferred-name-test5 (->i () () any))) + )) (contract-eval '(require 'contract-test-suite-inferred-name1)) ;; (eval '(test 'contract-inferred-name-test object-name contract-inferred-name-test)) ;; this one can't be made to pass, sadly. @@ -7247,6 +8303,7 @@ so that propagation occurs. (test 'contract-inferred-name-test2b object-name (contract-eval 'contract-inferred-name-test2b)) (test 'contract-inferred-name-test3 object-name (contract-eval 'contract-inferred-name-test3)) (test 'contract-inferred-name-test4 object-name (contract-eval 'contract-inferred-name-test4)) + (test 'contract-inferred-name-test5 object-name (contract-eval 'contract-inferred-name-test5)) @@ -7299,6 +8356,16 @@ so that propagation occurs. (test-name '(->d () () #:pre-cond ... [x ...] #:post-cond ...) (->d () () #:pre-cond #t [q number?] #:post-cond #t)) (test-name '(->d () () [x ...] #:post-cond ...) (->d () () [q number?] #:post-cond #t)) +#| ->i FIXME + (test-name '(->i () () any) (->i () () any)) + (test-name '(->i ([x integer?] #:y [y integer?]) ([z integer?] #:w [w integer?]) any) (->i ([x integer?] #:y [y integer?]) ([z integer?] #:w [w integer?]) any)) + (test-name '(->i () () (values [x ...] [y ...])) (->i () () (values [x number?] [y number?]))) + (test-name '(->i () () [x ...]) (->i () () [q number?])) + (test-name '(->i () () #:pre-cond ... [x ...]) (->i () () #:pre-cond #t [q number?])) + (test-name '(->i () () #:pre-cond ... [x ...] #:post-cond ...) (->i () () #:pre-cond #t [q number?] #:post-cond #t)) + (test-name '(->i () () [x ...] #:post-cond ...) (->i () () [q number?] #:post-cond #t)) +|# + (test-name '(case->) (case->)) (test-name '(case-> (-> integer? any) (-> boolean? boolean? any) (-> char? char? char? any)) (case-> (-> integer? any) (-> boolean? boolean? any) (-> char? char? char? any))) @@ -7458,6 +8525,14 @@ so that propagation occurs. (test-name '(object-contract (m (->d ((x ...) (y ...) (z ...)) () #:rest w ... [x0 ...]))) (object-contract (m (->d ((x number?) (y boolean?) (z pair?)) () #:rest rest-x any/c [result number?])))) +#| ->i FIXME + (test-name '(object-contract (m (->i ((x ...)) () (y ...)))) (object-contract (m (->i ((x number?)) () [result number?])))) + (test-name '(object-contract (m (->i ((x ...) (y ...) (z ...)) () [w ...]))) + (object-contract (m (->i ((x number?) (y boolean?) (z pair?)) () [result number?])))) + (test-name '(object-contract (m (->i ((x ...) (y ...) (z ...)) () #:rest w ... [x0 ...]))) + (object-contract (m (->i ((x number?) (y boolean?) (z pair?)) () #:rest rest-x any/c [result number?])))) +|# + (test-name '(promise/c any/c) (promise/c any/c)) (test-name '(syntax/c any/c) (syntax/c any/c)) (test-name '(struct/c st integer?) @@ -7538,6 +8613,8 @@ so that propagation occurs. (test #t (contract-eval 'contract-stronger?) c c)) (let ([c (contract-eval '(->d () () any))]) (test #t (contract-eval 'contract-stronger?) c c)) + (let ([c (contract-eval '(->i () () any))]) + (test #t (contract-eval 'contract-stronger?) c c)) (ctest #t contract-stronger? (or/c null? any/c) (or/c null? any/c)) (ctest #f contract-stronger? (or/c null? any/c) (or/c boolean? any/c)) @@ -7930,6 +9007,86 @@ so that propagation occurs. 'neg)]) (returns-odd 3) (list odd-count pos-count))) + + ;; this one is not tail recursive, since the contract system + ;; cannot tell that the range contract doesn't depend on 'arg' + (ctest 8 + 'tail-arrow-d1/changing-args + (let ([c (counter)]) + (letrec ([f + (contract (->i ([arg any/c]) () (values [_ (arg) c] [_ (arg) c])) + (λ (x) (if (zero? x) (values x x) (f (- x 1)))) + 'pos + 'neg)]) + (f 3)) + (c))) + + (ctest 2 + 'tail-arrow-i1 + (let ([c (counter)]) + (letrec ([x 5] + [f + (contract (->i ([arg any/c]) () (values [_ (arg) c] [_ (arg) c])) + (λ (_ignored) (if (zero? x) (values x x) (begin (set! x (- x 1)) (f _ignored)))) + 'pos + 'neg)]) + (f 'ignored)) + (c))) + + + ;; this one is just like the one two above. + (ctest 4 + 'tail-arrow-i2/changing-args + (let ([c (counter)]) + (letrec ([f + (contract (->i ([arg any/c]) () [rng (arg) c]) + (λ (x) (if (zero? x) x (f (- x 1)))) + 'pos + 'neg)]) + (f 3)) + (c))) + + (ctest 1 + 'tail-arrow-i2 + (let ([c (counter)]) + (letrec ([x 3] + [f + (contract (->i ([arg any/c]) () [rng (arg) c]) + (λ (ignored) (if (zero? x) x (begin (set! x (- x 1)) (f ignored)))) + 'pos + 'neg)]) + (f 3)) + (c))) + + ;; the tail-call optimization cannot handle two different + ;; contracts on the stack one after the other one, so this + ;; returns '(4 4) instead of '(1 1) (which would indicate + ;; the optimization had happened). + (ctest '(4 4) + 'tail->i-mut-rec + (letrec ([odd-count 0] + [pos-count 0] + [count-odd? + (λ (x) + (set! odd-count (+ odd-count 1)) + (odd? x))] + [count-positive? + (λ (x) + (set! pos-count (+ pos-count 1)) + (positive? x))] + [returns-odd + (contract (->i ([x any/c]) () [_ count-odd?]) + (λ (x) (returns-pos x)) + 'pos + 'neg)] + [returns-pos + (contract (->i ([x any/c]) () [_ count-positive?]) + (λ (x) (if (zero? x) 1 (returns-odd (- x 1)))) + 'pos + 'neg)]) + (returns-odd 3) + (list odd-count pos-count))) + (ctest 2 'case->-regular @@ -7984,7 +9141,7 @@ so that propagation occurs. (test/pos-blame 'free-vars-change-so-cannot-drop-the-check '(let () (define f - (contract (->d ([x number?]) () [_ (i ([x number?]) () [_ (x) (d ([x number?]) ([y number?]) [_ number?])]) (test ctc value-contract (contract ctc (λ (x [y 3]) x) 'pos 'neg))) + (let ([ctc (->i ([x number?]) ([y number?]) [_ number?])]) + (test ctc value-contract (contract ctc (λ (x [y 3]) x) 'pos 'neg))) (let ([ctc (unconstrained-domain-> number?)]) (test ctc value-contract (contract ctc (λ (x) 3) 'pos 'neg))) (let ([ctc (case-> (-> number? number? number?) (-> number? number?))])