Skip to content

Commit e0a372d

Browse files
capfredfsamth
authored andcommitted
remove type anns for parameters in λs generated from kw/opt plambdas
an optional or keyword lambda is expanded to more than two lambdas where syntax objects for the original paramaters are reused. This is problematic when those parameters are typed with bound type variables in polymorphic functions, because in generated lambdas those variables would become unbound. This patch fixes the problem by throwing the types away before typechecking the generated lambdas. closes #940
1 parent b6b0376 commit e0a372d

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed

typed-racket-lib/typed-racket/base-env/prims.rkt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,22 @@ the typed racket language.
684684
(if (attribute return.type)
685685
#`(ann last-e #,(attribute return.type))
686686
#'last-e))
687-
(define d (syntax/loc stx (λ formals.erased e ... last-e*)))
687+
688+
;; if the lambda form being checked is a polymorphic function, tag its
689+
;; parameters with property `from-lambda'.
690+
(define (maybe-set-from-lambda type-vars formals)
691+
(cond
692+
[(and type-vars (stx-list? formals))
693+
(stx-map (lambda (x)
694+
(from-plambda-property x #t))
695+
formals)]
696+
[type-vars (from-plambda-property formals #t)]
697+
[else formals]))
698+
699+
(define d (with-syntax ([erase-formals (maybe-set-from-lambda
700+
(attribute vars.type-vars)
701+
(attribute formals.erased))])
702+
(syntax/loc stx (λ erase-formals e ... last-e*))))
688703
(define d/prop
689704
(if (attribute formals.kw-property)
690705
(kw-lambda-property d (attribute formals.kw-property))

typed-racket-lib/typed-racket/private/syntax-properties.rkt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@
6969
(struct-info struct-info)
7070
(opt-lambda opt-lambda)
7171
(kw-lambda kw-lambda)
72+
; mark syntax objects for formal parameters in polymorphic lambdas forms.
73+
(from-plambda from-plambda)
7274
(tail-position typechecker:called-in-tail-position #:mark)
7375
(tr:class tr:class #:mark)
7476
(tr:class:top-level tr:class:top-level)

typed-racket-lib/typed-racket/typecheck/tc-lambda-unit.rkt

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,28 @@
4343
;; (i.e. (append positional (or id '())) but syntax)
4444
(struct formals (positional rest syntax) #:transparent)
4545

46-
(define (make-formals stx)
46+
47+
;; When expanding a keyword or optional lambda, Racket adds into the expanded
48+
;; code more lambdas, where syntax objects for the original lambda's parameters
49+
;; are reused. Since Typed Racket stores type information stored in the syntax
50+
;; objects, when the orginal lambda is a polymorphic function, that information
51+
;; might carry out-of-scope type variables. In this case, we need to remove it
52+
;; from parameter syntax objects.
53+
;;
54+
;; not-in-poly is #t if the original TR function is polymorphic.
55+
(define (make-formals stx [not-in-poly #t])
56+
(define (maybe-remove a)
57+
(if (and not-in-poly (from-plambda-property a))
58+
(syntax-property-remove a 'type-label)
59+
a))
60+
4761
(let loop ([s stx] [acc null])
4862
(cond
49-
[(pair? s) (loop (cdr s) (cons (car s) acc))]
63+
[(pair? s) (loop (cdr s) (cons (maybe-remove (car s)) acc))]
5064
[(null? s) (formals (reverse acc) #f stx)]
51-
[(pair? (syntax-e s)) (loop (stx-cdr s) (cons (stx-car s) acc))]
65+
[(pair? (syntax-e s)) (loop (stx-cdr s) (cons (maybe-remove (stx-car s)) acc))]
5266
[(null? (syntax-e s)) (formals (reverse acc) #f stx)]
53-
[else (formals (reverse acc) s stx)])))
67+
[else (formals (reverse acc) (maybe-remove s) stx)])))
5468

5569
;; Currently no support for objects representing the rest argument
5670
(define (formals->objects f)
@@ -621,15 +635,15 @@
621635
(tc-error/expr #:return dep-fun-ty
622636
"Dependent functions must have a single arity.")])))
623637

624-
(define (tc/mono-lambda/type formalss bodies expected)
638+
(define (tc/mono-lambda/type formalss bodies expected [not-in-poly #t])
625639
(match expected
626640
[(tc-result1:(? DepFun? dep-fun-ty))
627641
(tc/dep-lambda formalss bodies dep-fun-ty)]
628642
[_ (make-Fun
629643
(tc/mono-lambda
630644
(for/list ([f (in-syntax formalss)]
631645
[b (in-syntax bodies)])
632-
(cons (make-formals f) b))
646+
(cons (make-formals f not-in-poly) b))
633647
expected))]))
634648

635649
(define (plambda-prop stx)
@@ -678,7 +692,7 @@
678692
[_
679693
(define remaining-layers (remove-poly-layer tvarss-list))
680694
(if (null? remaining-layers)
681-
(tc/mono-lambda/type formals bodies expected)
695+
(tc/mono-lambda/type formals bodies expected #f)
682696
(tc/plambda form remaining-layers formals bodies expected))]))
683697
;; check the bodies appropriately
684698
;; and make both annotated and declared type variables point to the
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#lang typed/racket
2+
(lambda #:forall (A) ([a : A] #:mand mand) 10)
3+
4+
(lambda #:forall (A) ([a : A] #:mand [mand : (Listof A)]) 10)
5+
6+
(define #:forall (A) (bar [a : (Listof A)] #:mand [mand : Integer]) : Integer
7+
0)

0 commit comments

Comments
 (0)