diff --git a/collects/tests/typed-racket/fail/plambda-dup-tvar.rkt b/collects/tests/typed-racket/fail/plambda-dup-tvar.rkt new file mode 100644 index 00000000..9cf2889d --- /dev/null +++ b/collects/tests/typed-racket/fail/plambda-dup-tvar.rkt @@ -0,0 +1,9 @@ +#; +(exn-pred exn:fail:syntax?) +#lang typed/racket + +;; don't allow duplicate type variable names + +(plambda: (a a a) ([x : a]) x) +(popt-lambda: (a a a) ([x : a]) x) +(pcase-lambda: (a a a) ([x : a]) x) diff --git a/collects/tests/typed-racket/fail/poly-dup-name.rkt b/collects/tests/typed-racket/fail/poly-dup-name.rkt new file mode 100644 index 00000000..e88d8937 --- /dev/null +++ b/collects/tests/typed-racket/fail/poly-dup-name.rkt @@ -0,0 +1,8 @@ +#; +(exn:pred (lambda (e) (regexp-match? "duplicate type variable" e))) +#lang typed/racket + +;; don't allow duplicate type variable names + +(: f (All (A A) (A -> (List A)))) +(define (f a) (list a)) diff --git a/collects/tests/typed-racket/fail/polydots-dup-name.rkt b/collects/tests/typed-racket/fail/polydots-dup-name.rkt new file mode 100644 index 00000000..5fa6e21b --- /dev/null +++ b/collects/tests/typed-racket/fail/polydots-dup-name.rkt @@ -0,0 +1,10 @@ +#; +(exn:pred (lambda (e) (regexp-match? "duplicate type variable or index" e))) +#lang typed/racket + +;; don't allow duplicate names in indexes and tvars + +(: f (All (A A ...) (A A ... A -> (List A ... A)))) + +(define (f a . xs) + (map (λ: ([x : A]) a) xs)) diff --git a/collects/typed-racket/base-env/prims.rkt b/collects/typed-racket/base-env/prims.rkt index 3a61b1f5..1dc141a0 100644 --- a/collects/typed-racket/base-env/prims.rkt +++ b/collects/typed-racket/base-env/prims.rkt @@ -311,6 +311,8 @@ This file defines two sorts of primitives. All of them are provided into any mod (define-syntax (plambda: stx) (syntax-parse stx [(plambda: (tvars:id ...) formals . body) + #:fail-when (check-duplicate-identifier (syntax->list #'(tvars ...))) + "duplicate type variable declaration" (quasisyntax/loc stx (#%expression #,(syntax-property (syntax/loc stx (lambda: formals . body)) @@ -320,6 +322,8 @@ This file defines two sorts of primitives. All of them are provided into any mod (define-syntax (pcase-lambda: stx) (syntax-parse stx [(pcase-lambda: (tvars:id ...) cl ...) + #:fail-when (check-duplicate-identifier (syntax->list #'(tvars ...))) + "duplicate type variable declaration" (quasisyntax/loc stx (#%expression #,(syntax-property (syntax/loc stx (case-lambda: cl ...)) @@ -329,6 +333,8 @@ This file defines two sorts of primitives. All of them are provided into any mod (define-syntax (popt-lambda: stx) (syntax-parse stx [(popt-lambda: (tvars:id ...) formals . body) + #:fail-when (check-duplicate-identifier (syntax->list #'(tvars ...))) + "duplicate type variable declaration" (quasisyntax/loc stx (#%expression #,(syntax-property (syntax/loc stx (opt-lambda: formals . body)) diff --git a/collects/typed-racket/private/parse-type.rkt b/collects/typed-racket/private/parse-type.rkt index 036d5cb1..bb1326e2 100644 --- a/collects/typed-racket/private/parse-type.rkt +++ b/collects/typed-racket/private/parse-type.rkt @@ -51,6 +51,8 @@ ;(printf "parse-all-type: ~a \n" (syntax->datum stx)) (syntax-parse stx #:literals (t:All) [((~and kw t:All) (vars:id ... v:id dd:ddd) . t) + (when (check-duplicate-identifier (syntax->list #'(vars ... v))) + (tc-error "All: duplicate type variable or index")) (let* ([vars (map syntax-e (syntax->list #'(vars ...)))] [v (syntax-e #'v)]) (add-disappeared-use #'kw) @@ -58,6 +60,8 @@ (extend-tvars vars (make-PolyDots (append vars (list v)) (parse-all-body #'t)))))] [((~and kw t:All) (vars:id ...) . t) + (when (check-duplicate-identifier (syntax->list #'(vars ...))) + (tc-error "All: duplicate type variable")) (let* ([vars (map syntax-e (syntax->list #'(vars ...)))]) (add-disappeared-use #'kw) (extend-tvars vars