diff --git a/collects/mzlib/private/contract-ds-helpers.ss b/collects/mzlib/private/contract-ds-helpers.ss index 7cdac85ae7..8c353e95a7 100644 --- a/collects/mzlib/private/contract-ds-helpers.ss +++ b/collects/mzlib/private/contract-ds-helpers.ss @@ -29,7 +29,7 @@ expands into procedures & structs like this: which are then called when the contract's fields are explored |# - + (define (build-clauses name coerce-contract stx clauses) (let* ([field-names (map (λ (clause) @@ -40,7 +40,15 @@ which are then called when the contract's fields are explored stx clause)])) (syntax->list clauses))] - [all-ac-ids (generate-temporaries field-names)]) + [all-ac-ids (generate-temporaries field-names)] + [defeat-inlining + ;; makes the procedure "big enough" so + ;; that inlining doesn't consider it. + (λ (e) + (let loop ([i 16]) + (cond + [(zero? i) e] + [else #`(values #,(loop (- i 1)))])))]) (let loop ([clauses (syntax->list clauses)] [ac-ids all-ac-ids] [prior-ac-ids '()] @@ -58,7 +66,8 @@ which are then called when the contract's fields are explored (let ([maker-arg #`(λ #,(match-up (reverse prior-ac-ids) (syntax (x ...)) field-names) - (#,coerce-contract #,name ctc-exp))]) + #,(defeat-inlining + #`(#,coerce-contract #,name ctc-exp)))]) (loop (cdr clauses) (cdr ac-ids) (cons (car ac-ids) prior-ac-ids) diff --git a/collects/mzlib/private/contract-ds.ss b/collects/mzlib/private/contract-ds.ss index f1d712d8b0..1170f20c71 100644 --- a/collects/mzlib/private/contract-ds.ss +++ b/collects/mzlib/private/contract-ds.ss @@ -48,6 +48,15 @@ [wrap-name (string->symbol (format "~a/lazy-contract" (syntax-e (syntax name))))]) #` (begin + + ;; `declare' future bindings for the top-level (so that everyone picks them up) + #,@(if (eq? (syntax-local-context) 'top-level) + (list + (syntax + (define-syntaxes (contract-type contract-maker contract-predicate contract-get contract-set) + (values)))) + (list)) + (define-values (wrap-type wrap-maker wrap-predicate wrap-get wrap-set) (make-struct-type 'wrap-name #f ;; super struct diff --git a/collects/tests/mzscheme/contract-test.ss b/collects/tests/mzscheme/contract-test.ss index 6bf98efd62..e87a30f869 100644 --- a/collects/tests/mzscheme/contract-test.ss +++ b/collects/tests/mzscheme/contract-test.ss @@ -3521,6 +3521,19 @@ (couple-hd (contract c1 y 'pos 'neg)))) 1) + ;; make sure that define-contract-struct contracts can go at the top level + (test/spec-passed + 'd-c-s37 + '(parameterize ([current-namespace (make-namespace)]) + (eval '(require (lib "contract.ss"))) + (eval '(define-contract-struct couple (hd tl))) + (eval '(contract-stronger? + (couple/dc [hd any/c] + [tl (hd) any/c]) + (couple/dc [hd any/c] + [tl (hd) any/c]))))) + + ;; test the predicate (let () (define-contract-struct couple (hd tl)) @@ -3926,6 +3939,10 @@ (test #f contract-stronger? (couple/c (>=/c 2) (>=/c 3)) (couple/c (>=/c 4) (>=/c 5))) (test #t contract-stronger? (couple/c (>=/c 4) (>=/c 5)) (couple/c (>=/c 2) (>=/c 3))) (test #f contract-stronger? (couple/c (>=/c 1) (>=/c 5)) (couple/c (>=/c 5) (>=/c 1))) + (let ([ctc (couple/dc [hd any/c] [tl (hd) any/c])]) + (test #t contract-stronger? ctc ctc)) + (let ([ctc (couple/dc [hd any/c] [tl (hd) (<=/c hd)])]) + (test #t contract-stronger? ctc ctc)) (test #t contract-stronger? list-of-numbers list-of-numbers) (test #t contract-stronger? (short-list/less-than 4) (short-list/less-than 5)) (test #f contract-stronger? (short-list/less-than 5) (short-list/less-than 4))