diff --git a/typed-racket-lib/typed-racket/private/type-contract.rkt b/typed-racket-lib/typed-racket/private/type-contract.rkt index dba033a7..d5516575 100644 --- a/typed-racket-lib/typed-racket/private/type-contract.rkt +++ b/typed-racket-lib/typed-racket/private/type-contract.rkt @@ -284,7 +284,10 @@ [else (define sc (match type match-clause ...)) (define fvs (fv type)) - (unless (or (ormap (λ (n) (member n fvs)) (bound-names)) + ;; Only cache closed terms, otherwise open terms may show up + ;; out of context. + ;; TODO this used `bound-names`, get rid of it + (unless (or (not (null? fv)) ;; Don't cache types with applications of Name types because ;; it does the wrong thing for recursive references (has-name-app? type)) diff --git a/typed-racket-test/succeed/pr15144.rkt b/typed-racket-test/succeed/pr15144.rkt new file mode 100644 index 00000000..7ba2bf2b --- /dev/null +++ b/typed-racket-test/succeed/pr15144.rkt @@ -0,0 +1,28 @@ +#lang typed/racket + +;; Caching in the type->sc translation was causing open sc terms to appear in +;; the contract for `bar`. + +(define-type (Base-Shape R) + (U (foo-shape R) + (bar-shape R))) + +(define-syntax (def-base-shape stx) + (syntax-case stx () + [(_ (R (func-name shape-name) [param-name : param-type] ...)) + (syntax/loc stx + (begin + (struct (R) shape-name ([param-name : param-type] ...)) + (define #:forall (R) (func-name [param-name : param-type] ...) + (shape-name param-name ...))))])) + +(def-base-shape (R (foo-func foo-shape) [s : (Base-Shape R)])) +(def-base-shape (R (bar-func bar-shape) [s : R])) + +(provide foo) +(define (foo [shapes : (Base-Shape String)]) + (foo-func shapes)) + +(provide bar) +(define (bar [shapes : (Base-Shape String)]) + (bar-func shapes))