Check function depth for parsing object indices
Closes PR 14509
This commit is contained in:
parent
65368108e1
commit
e62f1cb8d9
|
@ -64,6 +64,16 @@
|
|||
;; interp. same as above
|
||||
(define current-referenced-class-parents (make-parameter #f))
|
||||
|
||||
;; current-arities : Parameter<(Listof Natural)>
|
||||
;; Represents the stack of function arities in the potentially
|
||||
;; nested function type being parsed. The stack does not include the
|
||||
;; innermost function (since syntax classes can check that locally)
|
||||
(define current-arities (make-parameter null))
|
||||
|
||||
(define-syntax-rule (with-arity arity e ...)
|
||||
(parameterize ([current-arities (cons arity (current-arities))])
|
||||
e ...))
|
||||
|
||||
(define-literal-syntax-class #:for-label car)
|
||||
(define-literal-syntax-class #:for-label cdr)
|
||||
(define-literal-syntax-class #:for-label colon^ (:))
|
||||
|
@ -263,10 +273,18 @@
|
|||
arg (length doms))
|
||||
#:attr obj (-arg-path arg 0))
|
||||
(pattern (~seq depth-idx:nat idx:nat)
|
||||
#:do [(define arg (syntax-e #'idx))]
|
||||
#:fail-unless (< arg (length doms))
|
||||
#:do [(define arg (syntax-e #'idx))
|
||||
(define depth (syntax-e #'depth-idx))]
|
||||
#:fail-unless (<= depth (length (current-arities)))
|
||||
(format "Index ~a used in a filter, but the use is only within ~a enclosing functions"
|
||||
depth (length (current-arities)))
|
||||
#:do [(define actual-arg
|
||||
(if (zero? depth)
|
||||
(length doms)
|
||||
(list-ref (current-arities) (sub1 depth))))]
|
||||
#:fail-unless (< arg actual-arg)
|
||||
(format "Filter proposition's object index ~a is larger than argument length ~a"
|
||||
arg (length doms))
|
||||
depth actual-arg)
|
||||
#:attr obj (-arg-path arg (syntax-e #'depth-idx))))
|
||||
|
||||
|
||||
|
@ -400,49 +418,55 @@
|
|||
[((~and dom:non-keyword-ty (~not :->^)) ...
|
||||
:->^
|
||||
(~and (~seq rest-dom ...) (~seq (~or _ (~between :->^ 1 +inf.0)) ...)))
|
||||
(let ([doms (for/list ([d (in-syntax #'(dom ...))])
|
||||
(parse-type d))])
|
||||
(make-Function
|
||||
(list (make-arr
|
||||
doms
|
||||
(parse-type (syntax/loc stx (rest-dom ...)))))))]
|
||||
(define doms (syntax->list #'(dom ...)))
|
||||
(with-arity (length doms)
|
||||
(let ([doms (for/list ([d (in-list doms)])
|
||||
(parse-type d))])
|
||||
(make-Function
|
||||
(list (make-arr
|
||||
doms
|
||||
(parse-type (syntax/loc stx (rest-dom ...))))))))]
|
||||
[(~or (:->^ dom rng :colon^ latent:simple-latent-filter)
|
||||
(dom :->^ rng :colon^ latent:simple-latent-filter))
|
||||
;; use parse-type instead of parse-values-type because we need to add the filters from the pred-ty
|
||||
(make-pred-ty (list (parse-type #'dom)) (parse-type #'rng) (attribute latent.type)
|
||||
(-acc-path (attribute latent.path) (-arg-path 0)))]
|
||||
(with-arity 1
|
||||
(make-pred-ty (list (parse-type #'dom)) (parse-type #'rng) (attribute latent.type)
|
||||
(-acc-path (attribute latent.path) (-arg-path 0))))]
|
||||
[(~or (:->^ dom:non-keyword-ty ... kws:keyword-tys ... rest:non-keyword-ty ddd:star rng)
|
||||
(dom:non-keyword-ty ... kws:keyword-tys ... rest:non-keyword-ty ddd:star :->^ rng))
|
||||
(make-Function
|
||||
(list (make-arr
|
||||
(parse-types #'(dom ...))
|
||||
(parse-values-type #'rng)
|
||||
#:rest (parse-type #'rest)
|
||||
#:kws (map force (attribute kws.Keyword)))))]
|
||||
(with-arity (length (syntax->list #'(dom ...)))
|
||||
(make-Function
|
||||
(list (make-arr
|
||||
(parse-types #'(dom ...))
|
||||
(parse-values-type #'rng)
|
||||
#:rest (parse-type #'rest)
|
||||
#:kws (map force (attribute kws.Keyword))))))]
|
||||
[(~or (:->^ dom:non-keyword-ty ... rest:non-keyword-ty :ddd/bound rng)
|
||||
(dom:non-keyword-ty ... rest:non-keyword-ty :ddd/bound :->^ rng))
|
||||
(let* ([bnd (syntax-e #'bound)])
|
||||
(unless (bound-index? bnd)
|
||||
(parse-error
|
||||
#:stx #'bound
|
||||
"used a type variable not bound with ... as a bound on a ..."
|
||||
"variable" bnd))
|
||||
(make-Function
|
||||
(list
|
||||
(make-arr-dots (parse-types #'(dom ...))
|
||||
(parse-values-type #'rng)
|
||||
(extend-tvars (list bnd)
|
||||
(parse-type #'rest))
|
||||
bnd))))]
|
||||
(with-arity (length (syntax->list #'(dom ...)))
|
||||
(let* ([bnd (syntax-e #'bound)])
|
||||
(unless (bound-index? bnd)
|
||||
(parse-error
|
||||
#:stx #'bound
|
||||
"used a type variable not bound with ... as a bound on a ..."
|
||||
"variable" bnd))
|
||||
(make-Function
|
||||
(list
|
||||
(make-arr-dots (parse-types #'(dom ...))
|
||||
(parse-values-type #'rng)
|
||||
(extend-tvars (list bnd)
|
||||
(parse-type #'rest))
|
||||
bnd)))))]
|
||||
[(~or (:->^ dom:non-keyword-ty ... rest:non-keyword-ty _:ddd rng)
|
||||
(dom:non-keyword-ty ... rest:non-keyword-ty _:ddd :->^ rng))
|
||||
(let ([var (infer-index stx)])
|
||||
(make-Function
|
||||
(list
|
||||
(make-arr-dots (parse-types #'(dom ...))
|
||||
(parse-values-type #'rng)
|
||||
(extend-tvars (list var) (parse-type #'rest))
|
||||
var))))]
|
||||
(with-arity (length (syntax->list #'(dom ...)))
|
||||
(let ([var (infer-index stx)])
|
||||
(make-Function
|
||||
(list
|
||||
(make-arr-dots (parse-types #'(dom ...))
|
||||
(parse-values-type #'rng)
|
||||
(extend-tvars (list var) (parse-type #'rest))
|
||||
var)))))]
|
||||
#| ;; has to be below the previous one
|
||||
[(dom:expr ... :->^ rng)
|
||||
(->* (parse-types #'(dom ...))
|
||||
|
@ -450,33 +474,37 @@
|
|||
;; use expr to rule out keywords
|
||||
[(~or (:->^ dom:non-keyword-ty ... kws:keyword-tys ... rng)
|
||||
(dom:non-keyword-ty ... kws:keyword-tys ... :->^ rng))
|
||||
(let ([doms (for/list ([d (in-syntax #'(dom ...))])
|
||||
(parse-type d))])
|
||||
(make-Function
|
||||
(list (make-arr
|
||||
doms
|
||||
(parse-values-type #'rng)
|
||||
#:kws (map force (attribute kws.Keyword))))))]
|
||||
(define doms (syntax->list #'(dom ...)))
|
||||
(with-arity (length doms)
|
||||
(let ([doms (for/list ([d (in-list doms)])
|
||||
(parse-type d))])
|
||||
(make-Function
|
||||
(list (make-arr
|
||||
doms
|
||||
(parse-values-type #'rng)
|
||||
#:kws (map force (attribute kws.Keyword)))))))]
|
||||
;; This case needs to be at the end because it uses cut points to give good error messages.
|
||||
[(~or (:->^ ~! dom:non-keyword-ty ... rng:expr
|
||||
:colon^ (~var latent (full-latent (syntax->list #'(dom ...)))))
|
||||
(dom:non-keyword-ty ... :->^ rng:expr
|
||||
~! :colon^ (~var latent (full-latent (syntax->list #'(dom ...))))))
|
||||
;; use parse-type instead of parse-values-type because we need to add the filters from the pred-ty
|
||||
(->* (parse-types #'(dom ...))
|
||||
(parse-type #'rng)
|
||||
: (-FS (attribute latent.positive) (attribute latent.negative))
|
||||
: (attribute latent.object))]
|
||||
(with-arity (length (syntax->list #'(dom ...)))
|
||||
(->* (parse-types #'(dom ...))
|
||||
(parse-type #'rng)
|
||||
: (-FS (attribute latent.positive) (attribute latent.negative))
|
||||
: (attribute latent.object)))]
|
||||
[(:->*^ mand:->*-mand opt:->*-opt rest:->*-rest rng)
|
||||
(define doms (for/list ([d (attribute mand.doms)])
|
||||
(parse-type d)))
|
||||
(define opt-doms (for/list ([d (attribute opt.doms)])
|
||||
(parse-type d)))
|
||||
(opt-fn doms opt-doms (parse-values-type #'rng)
|
||||
#:rest (and (attribute rest.type)
|
||||
(parse-type (attribute rest.type)))
|
||||
#:kws (map force (append (attribute mand.kws)
|
||||
(attribute opt.kws))))]
|
||||
(with-arity (length (attribute mand.doms))
|
||||
(define doms (for/list ([d (attribute mand.doms)])
|
||||
(parse-type d)))
|
||||
(define opt-doms (for/list ([d (attribute opt.doms)])
|
||||
(parse-type d)))
|
||||
(opt-fn doms opt-doms (parse-values-type #'rng)
|
||||
#:rest (and (attribute rest.type)
|
||||
(parse-type (attribute rest.type)))
|
||||
#:kws (map force (append (attribute mand.kws)
|
||||
(attribute opt.kws)))))]
|
||||
[:->^
|
||||
(parse-error #:delayed? #t "incorrect use of -> type constructor")
|
||||
Err]
|
||||
|
|
|
@ -159,6 +159,15 @@
|
|||
(t:->* (list Univ) -Boolean : (-FS (-not-filter -Number 0) (-filter -Number 0)))]
|
||||
[(-> Any Boolean : #:+ (! Number @ 0) #:- (Number @ 0))
|
||||
(t:->* (list Univ) -Boolean : (-FS (-not-filter -Number 0) (-filter -Number 0)))]
|
||||
[(-> Any (-> Any Boolean : #:+ (Number @ 1 0) #:- (! Number @ 1 0)))
|
||||
(t:-> Univ
|
||||
(t:->* (list Univ) -Boolean : (-FS (-filter -Number '(1 0)) (-not-filter -Number '(1 0)))))]
|
||||
[(-> Any Any (-> Any Boolean : #:+ (Number @ 1 1) #:- (! Number @ 1 1)))
|
||||
(t:-> Univ Univ
|
||||
(t:->* (list Univ) -Boolean : (-FS (-filter -Number '(1 1)) (-not-filter -Number '(1 1)))))]
|
||||
[(-> Any #:foo Any (-> Any Boolean : #:+ (Number @ 1 0) #:- (! Number @ 1 0)))
|
||||
(->key Univ #:foo Univ #t
|
||||
(t:->* (list Univ) -Boolean : (-FS (-filter -Number '(1 0)) (-not-filter -Number '(1 0)))))]
|
||||
[(All (a b) (-> (-> a Any : #:+ b) (Listof a) (Listof b)))
|
||||
(-poly (a b) (t:-> (asym-pred a Univ (-FS (-filter b 0) -top)) (-lst a) (-lst b)))]
|
||||
[(All (a b) (-> (-> a Any : #:+ (! b)) (Listof a) (Listof b)))
|
||||
|
@ -178,6 +187,10 @@
|
|||
[FAIL -> #:msg "incorrect use of -> type constructor"]
|
||||
[FAIL (Any -> Any #:object 0) #:msg "expected the identifier `:'"]
|
||||
[FAIL (-> Any Any #:+ (String @ x)) #:msg "expected the identifier `:'"]
|
||||
[FAIL (-> Any Boolean : #:+ (Number @ 1 0) #:- (! Number @ 1 0))
|
||||
#:msg "Index 1 used in"]
|
||||
[FAIL (-> Any (-> Any Boolean : #:+ (Number @ 1 1) #:- (! Number @ 1 1)))
|
||||
#:msg "larger than argument length"]
|
||||
|
||||
|
||||
[(Any -> Boolean : #:+ (Symbol @ not-mutated-var))
|
||||
|
@ -210,6 +223,11 @@
|
|||
(->optkey -Integer [-String] #:bar -Integer #t -Void)]
|
||||
[(->* (Integer #:bar Integer) (String #:foo Integer) Void)
|
||||
(->optkey -Integer [-String] #:bar -Integer #t #:foo -Integer #f -Void)]
|
||||
[(->* (Any (-> Any Boolean : #:+ (String @ 1 0))) Void)
|
||||
(t:-> Univ (t:->* (list Univ) -Boolean : (-FS (-filter -String '(1 0)) -top))
|
||||
-Void)]
|
||||
[FAIL (->* (Any (-> Any Boolean : #:+ (String @ 2 0))) Void)
|
||||
#:msg "Index 2 used in"]
|
||||
|
||||
[(Opaque foo?) (make-Opaque #'foo?)]
|
||||
;; PR 14122
|
||||
|
|
|
@ -3133,6 +3133,17 @@
|
|||
(define (g x) (f x))
|
||||
(error "foo"))
|
||||
#:msg #rx"Polymorphic function `f' could not be applied"]
|
||||
|
||||
;; PR 14509
|
||||
[tc-e
|
||||
(let ()
|
||||
(: f (-> Any (-> Any Boolean : #:+ (Number @ 1 0))))
|
||||
(define f (λ (x) (λ (y) (number? x))))
|
||||
|
||||
(: g (-> Any (-> Boolean : #:+ (Number @ 1 0))))
|
||||
(define g (λ (x) (λ () (number? x))))
|
||||
(void))
|
||||
-Void]
|
||||
)
|
||||
|
||||
(test-suite
|
||||
|
|
Loading…
Reference in New Issue
Block a user