diff --git a/collects/tests/typed-scheme/succeed/list-dots.rkt b/collects/tests/typed-scheme/succeed/list-dots.rkt index 83ed511b..1c19fff0 100644 --- a/collects/tests/typed-scheme/succeed/list-dots.rkt +++ b/collects/tests/typed-scheme/succeed/list-dots.rkt @@ -1,5 +1,7 @@ #lang typed/racket +;; tests for the new iteration of ... + (: f (All (a ...) ((List a ...) -> (List a ... a)))) (define (f x) x) @@ -19,3 +21,15 @@ (: h4 (All (a ...) (a ... -> Number))) (define (h4 . x) (length x)) + +(: i (All (a ...) (List a ...) (a ... -> Number) -> Number)) +(define (i xs f) (apply f xs)) + +(: i2 (All (a ...) (List a ...) (Any * -> Number) -> Number)) +(define (i2 xs f) (apply f xs)) + +(: i3 (All (a ...) (List a ...) (List a ...) ((Pairof a a) ... -> Number) -> Number)) +(define (i3 xs ys f) (apply f (map cons xs ys))) + +(: i4 (All (a ...) (List a ...) (Listof Number) ((Pairof a Number) ... -> Number) -> Number)) +(define (i4 xs ys f) (apply f (map cons xs ys))) diff --git a/collects/typed-scheme/typecheck/tc-app.rkt b/collects/typed-scheme/typecheck/tc-app.rkt index e4bc51ec..07a57c68 100644 --- a/collects/typed-scheme/typecheck/tc-app.rkt +++ b/collects/typed-scheme/typecheck/tc-app.rkt @@ -625,21 +625,28 @@ (check-do-make-object #'cl #'args #'() #'())] [(#%plain-app do-make-object cl (#%plain-app list . pos-args) (#%plain-app list (#%plain-app cons 'names named-args) ...)) (check-do-make-object #'cl #'pos-args #'(names ...) #'(named-args ...))] - [(#%plain-app (~literal map) f arg) - (match (single-value #'arg) + [(#%plain-app (~literal map) f arg0 arg ...) + (match* ((single-value #'arg0) (map single-value (syntax->list #'(arg ...)))) ;; if the argument is a ListDots - [(tc-result1: (ListDots: t bound)) - - (match (extend-tvars (list bound) + [((tc-result1: (ListDots: t0 bound0)) + (list (tc-result1: (or (and (ListDots: t bound) (app (λ _ #f) var)) + ;; a devious hack - just generate #f so the test below succeeds + ;; have to explicitly bind `var' since otherwise `var' appears on only one side of the or + ;; NOTE: safe to include these, `map' will error if any list is not the same length as all the others + (and (Listof: t var) (app (λ _ #f) bound)))) + ...)) + (=> fail) + (unless (for/and ([b bound]) (or (not b) (eq? bound0 b))) (fail)) + (match (extend-tvars (list bound0) ;; just check that the function applies successfully to the element type - (tc/funapp #'f #'(arg) (tc-expr #'f) (list (ret t)) expected)) - [(tc-result1: t) (ret (make-ListDots t bound))] + (tc/funapp #'f #'(arg0 arg ...) (tc-expr #'f) (cons (ret t0) (map ret t)) expected)) + [(tc-result1: t) (ret (make-ListDots t bound0))] [(tc-results: ts) (tc-error/expr #:return (ret (Un)) "Expected one value, but got ~a" (-values ts))])] ;; otherwise, if it's not a ListDots, defer to the regular function typechecking - [res - (tc/funapp #'map #'(f arg) (single-value #'map) (list (tc-expr #'f) res) expected)])] + [(res0 res) + (tc/funapp #'map #'(f arg0 arg ...) (single-value #'map) (list* (tc-expr #'f) res0 res) expected)])] ;; ormap/andmap of ... argument [(#%plain-app (~and fun (~or (~literal andmap) (~literal ormap))) f arg) ;; check the arguments