don't make new foralls for under-constrained function applications
Fixes the unsoundness mentioned in https://bitbucket.org/stchang/macrotypes/issues/16/allow-under-constrained-function#comment-27692493 by disallowing under-constrained function calls entirely. This re-opens issue #16, which will have to be solved in a sound way later.
This commit is contained in:
parent
1e68e32ecc
commit
c9110ccf73
|
@ -756,11 +756,7 @@
|
|||
#'(τ_in ...)))
|
||||
#:with τ_out* (if (stx-null? #'(unsolved-X ...))
|
||||
#'τ_out
|
||||
(syntax-parse #'τ_out
|
||||
[(~?∀ (Y ...) τ_out)
|
||||
(unless (→? #'τ_out)
|
||||
(raise-app-poly-infer-error stx #'(τ_in ...) #'(τ_arg ...) #'e_fn))
|
||||
#'(∀ (unsolved-X ... Y ...) τ_out)]))
|
||||
(raise-app-poly-infer-error stx #'(τ_in ...) #'(τ_arg ...) #'e_fn))
|
||||
(⊢ (#%app e_fn- e_arg- ...) : τ_out*)])])]
|
||||
[(_ e_fn . e_args) ; err case; e_fn is not a function
|
||||
#:with [e_fn- τ_fn] (infer+erase #'e_fn)
|
||||
|
|
|
@ -365,18 +365,20 @@
|
|||
|
||||
(define (nn [x : X] -> (→ (× X (→ Y Y))))
|
||||
(λ () (tup x (λ ([x : Y]) x))))
|
||||
(define nn-1 (nn 1))
|
||||
(check-type (nn-1) : (× Int (→ String String)))
|
||||
(check-type (nn-1) : (× Int (→ (List Int) (List Int))))
|
||||
(typecheck-fail (nn 1) #:with-msg "Could not infer instantiation of polymorphic function nn.")
|
||||
(check-type (nn 1) : (→ (× Int (→ String String))))
|
||||
(check-type (nn 1) : (→ (× Int (→ (List Int) (List Int)))))
|
||||
|
||||
(define (nn2 [x : X] -> (→ (× X (→ Y Y) (List Z))))
|
||||
(λ () (tup x (λ ([x : Y]) x) Nil)))
|
||||
(define nn2-1 (nn2 1))
|
||||
(check-type (nn2-1) : (× Int (→ String String) (List (List Int))))
|
||||
(check-type (nn2-1) : (× Int (→ (List Int) (List Int)) (List String)))
|
||||
(typecheck-fail (nn2 1) #:with-msg "Could not infer instantiation of polymorphic function nn2.")
|
||||
(check-type (nn2 1) : (→ (× Int (→ String String) (List (List Int)))))
|
||||
(check-type (nn2 1) : (→ (× Int (→ (List Int) (List Int)) (List String))))
|
||||
;; test inst order
|
||||
(check-type ((inst nn2-1 String (List Int))) : (× Int (→ String String) (List (List Int))))
|
||||
(check-type ((inst nn2-1 (List Int) String)) : (× Int (→ (List Int) (List Int)) (List String)))
|
||||
(check-type ((inst nn2 Int String (List Int)) 1)
|
||||
: (→ (× Int (→ String String) (List (List Int)))))
|
||||
(check-type ((inst nn2 Int (List Int) String) 1)
|
||||
: (→ (× Int (→ (List Int) (List Int)) (List String))))
|
||||
|
||||
(define-type (Result A B)
|
||||
(Ok A)
|
||||
|
@ -409,20 +411,20 @@
|
|||
(check-type result-if-1
|
||||
: (→/test (Result A1 B1) (→ (→ A1 (Result A2 B2)) (→ B1 (Result A2 B2))
|
||||
(Result A2 B2))))
|
||||
(check-type (inst (result-if-1 (Ok {Int String} 1)) (List Int) (List String))
|
||||
(check-type ((inst result-if-1 Int String (List Int) (List String)) (Ok 1))
|
||||
: (→ (→ Int (Result (List Int) (List String)))
|
||||
(→ String (Result (List Int) (List String)))
|
||||
(Result (List Int) (List String))))
|
||||
(check-type (inst (result-if-1 (Error {Int String} "bad")) (List Int) (List String))
|
||||
(check-type ((inst result-if-1 Int String (List Int) (List String)) (Error "bad"))
|
||||
: (→ (→ Int (Result (List Int) (List String)))
|
||||
(→ String (Result (List Int) (List String)))
|
||||
(Result (List Int) (List String))))
|
||||
(check-type ((result-if-1 (Ok {Int String} 1))
|
||||
(check-type (((inst result-if-1 Int String (List Int) (List String)) (Ok 1))
|
||||
(λ ([a : Int]) (ok (Cons a Nil)))
|
||||
(λ ([b : String]) (error (Cons b Nil))))
|
||||
: (Result (List Int) (List String)))
|
||||
;; same thing, but without the lambda annotations:
|
||||
(check-type ((result-if-1 (Ok {Int String} 1))
|
||||
(check-type (((inst result-if-1 Int String (List Int) (List String)) (Ok 1))
|
||||
(λ (a) (ok (Cons a Nil)))
|
||||
(λ (b) (error (Cons b Nil))))
|
||||
: (Result (List Int) (List String)))
|
||||
|
@ -438,18 +440,16 @@
|
|||
: (→/test (Result A1 B1) (→ (→ A1 (Result A2 B2))
|
||||
(→ (→ B1 (Result A2 B2))
|
||||
(Result A2 B2)))))
|
||||
(check-type (inst (result-if-2 (Ok {Int String} 1)) (List Int) (List String))
|
||||
(check-type ((inst result-if-2 Int String (List Int) (List String)) (Ok 1))
|
||||
: (→/test (→ Int (Result (List Int) (List String)))
|
||||
(→ (→ String (Result (List Int) (List String)))
|
||||
(Result (List Int) (List String)))))
|
||||
(check-type ((result-if-2 (Ok {Int String} 1))
|
||||
(λ ([a : Int]) (Ok {(List Int) (List String)} (Cons a Nil))))
|
||||
(check-type (((inst result-if-2 Int String (List Int) (List String)) (Ok 1))
|
||||
(λ (a) (Ok (Cons a Nil))))
|
||||
: (→/test (→ String (Result (List Int) (List String)))
|
||||
(Result (List Int) (List String))))
|
||||
(check-type (((result-if-2 (Ok {Int String} 1))
|
||||
; type annotations are necessary here:
|
||||
(λ ([a : Int]) (Ok {(List Int) (List String)} (Cons a Nil))))
|
||||
; but not here:
|
||||
(check-type ((((inst result-if-2 Int String (List Int) (List String)) (Ok 1))
|
||||
(λ (a) (Ok (Cons a Nil))))
|
||||
(λ (b) (Error (Cons b Nil))))
|
||||
: (Result (List Int) (List String)))
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user