From 8755e625568705aa078e46e0407dd87cbbe00d89 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Fri, 20 Jun 2014 12:14:43 -0400 Subject: [PATCH] Check kw functions with optional arguments better In particular, allow the optional kws to be left out in the expected type (a function type with fewer optional kws is a supertype). Closes PR 14583 --- .../typed-racket/types/kw-types.rkt | 11 ++++++----- .../typed-racket/unit-tests/typecheck-tests.rkt | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/pkgs/typed-racket-pkgs/typed-racket-lib/typed-racket/types/kw-types.rkt b/pkgs/typed-racket-pkgs/typed-racket-lib/typed-racket/types/kw-types.rkt index 020e14d5a6..10e87b55e7 100644 --- a/pkgs/typed-racket-pkgs/typed-racket-lib/typed-racket/types/kw-types.rkt +++ b/pkgs/typed-racket-pkgs/typed-racket-lib/typed-racket/types/kw-types.rkt @@ -134,19 +134,20 @@ ;; -> (Listof Keyword) ;; Remove keywords in the given list that aren't in the actual lambda ;; keywords list. This allows the typechecker to check some branches of the -;; type that match the actual kws. Add extra actual mandatory keywords -;; with Bottom type. +;; type that match the actual kws. Add extra actual keywords with Bottom type. (define (handle-extra-or-missing-kws kws actual-kws) (match-define (lambda-kws actual-mands actual-opts) actual-kws) - (define expected-mands (map Keyword-kw (filter Keyword-required? kws))) + (define expected-kws (map Keyword-kw kws)) (define missing-removed (filter (λ (kw) (or (member (Keyword-kw kw) actual-mands) (member (Keyword-kw kw) actual-opts))) kws)) (append missing-removed - (for/list ([kw (in-list (set-subtract actual-mands expected-mands))]) - (make-Keyword kw -Bottom #t)))) + (for/list ([kw (in-list (set-subtract actual-mands expected-kws))]) + (make-Keyword kw -Bottom #t)) + (for/list ([kw (in-list (set-subtract actual-opts expected-kws))]) + (make-Keyword kw -Bottom #f)))) ;; inner-kw-convert : (Listof arr) (Option LambdaKeywords) Boolean -> Type ;; Helper function that converts each arr to a Function type and then diff --git a/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/unit-tests/typecheck-tests.rkt b/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/unit-tests/typecheck-tests.rkt index 0089126e35..c64edf8c5b 100644 --- a/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/unit-tests/typecheck-tests.rkt +++ b/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/unit-tests/typecheck-tests.rkt @@ -3080,6 +3080,20 @@ (tr:define (f #:foo [foo 'foo] #:bar bar) 0) (error "dummy")) #:msg #rx"too many mandatory keyword arguments.*#:foo"] + + ;; PR 14583 + [tc-e + (let () + (: f (-> String)) + (tr:define (f #:foo [foo 'foo]) "foo") + (f)) + -String] + [tc-err + (let () + (: f (-> String)) + (tr:define (f #:foo [foo 'foo]) foo) + (error "dummy")) + #:msg #rx"expected: String.*given: 'foo"] ) (test-suite