Skip to content

Commit 8d9cb49

Browse files
authored
Improves performance and error reporting for checking (list ....) (#1030)
The commit contains the following changes: 1. When the expected type is `(Listof t)`, we use `t` to check the arguments to `list` 2. In a more complexed situation, when some arguments `(list arg ...)` are ill-typed, the typechecker reports the error without checking if the result type of the function application matches the expected type. closes #995 and #958
1 parent 47a5ab3 commit 8d9cb49

File tree

4 files changed

+37
-3
lines changed

4 files changed

+37
-3
lines changed

typed-racket-lib/typed-racket/typecheck/signatures.rkt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
[cond-contracted tc-expr/check/t? (syntax? (or/c tc-results/c #f) . -> . (or/c Type? #f))]
1414
[cond-contracted tc-body/check (syntax? (or/c tc-results/c #f) . -> . full-tc-results/c)]
1515
[cond-contracted tc-expr/t (syntax? . -> . Type?)]
16+
[cond-contracted tc-expr/t* (syntax? . -> . (values Type? boolean?))]
1617
[cond-contracted single-value ((syntax?) ((or/c tc-results/c #f)) . ->* . full-tc-results/c)]
1718
[cond-contracted tc-dep-fun-arg ((syntax?) ((or/c tc-results/c #f)) . ->* . full-tc-results/c)]))
1819

typed-racket-lib/typed-racket/typecheck/tc-app/tc-app-list.rkt

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
(require "../../utils/utils.rkt"
55
"signatures.rkt"
66
"utils.rkt"
7-
syntax/parse syntax/stx racket/match racket/sequence
7+
syntax/parse syntax/stx racket/match
88
(typecheck signatures tc-funapp error-message)
99
(types abbrev type-table utils substitute)
1010
(rep type-rep)
@@ -95,12 +95,18 @@
9595
[else
9696
(expected-but-got t (-Tuple (map tc-expr/t args-list)))
9797
(ret t)])]
98+
[(Listof: t*)
99+
(for ([arg (in-list args-list)])
100+
(tc-expr/check arg (ret t*)))
101+
(add-typeof-expr #'op-name (ret (->* '() t* t)))
102+
(ret t)]
98103
[_
99104
(define vs (map (λ (_) (gensym)) args-list))
100105
(define l-type (-Tuple (map make-F vs)))
101106
;; We want to infer the largest vs that are still under the element types
102107
(define substs (i:infer vs null (list l-type) (list t) (-values (list (-> l-type Univ)))
103108
#:multiple? #t))
109+
104110
(cond
105111
[substs
106112
(define result
@@ -113,8 +119,17 @@
113119
(add-typeof-expr #'op-name (ret (->* arg-tys return-ty)))
114120
(ret return-ty)))
115121
(or result
116-
(begin (expected-but-got t (-Tuple (map tc-expr/t args-list)))
117-
(fix-results expected)))]
122+
;; When arguments to the list function fail to typecheck, the
123+
;; odds are those argument expressions are ill-typed. In that
124+
;; case, we should only report those type errors instead of the error
125+
;; that the result type of application of list doesn't match
126+
;; the expected one.
127+
(let-values ([(tys errs) (for/lists (tys errs)
128+
([i (in-list args-list)])
129+
(tc-expr/t* i))])
130+
(when (andmap not errs)
131+
(expected-but-got t (-Tuple tys)))
132+
(fix-results expected)))]
118133
[else
119134
(define arg-tys (map tc-expr/t args-list))
120135
(define return-ty (-Tuple arg-tys))

typed-racket-lib/typed-racket/typecheck/tc-expr-unit.rkt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@
6767
[(tc-result1: t _ _) t]
6868
[t (int-err "tc-expr returned ~a, not a single tc-result, for ~a" t (syntax->datum e))]))
6969

70+
;; typecheck an expression. The result contains two values
71+
;; 1. the type of the expression
72+
;; 2. whether there are type errors during checking the expression
73+
;;
74+
;; Unlike tc-expr/check/t? and tc-expr/check?, this function raises or keeps errors from
75+
;; checking the expression in the error queue.
76+
;;
77+
;; tc-expr/t* : Expr -> (values Type Boolean)
78+
(define (tc-expr/t* expr)
79+
(parameterize ([current-type-error? #f])
80+
(values (tc-expr/t expr) (current-type-error?))))
81+
7082
(define (tc-expr/check/t e t)
7183
(match (tc-expr/check e t)
7284
[(tc-result1: t) t]))

typed-racket-test/unit-tests/typecheck-tests.rkt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3489,6 +3489,12 @@
34893489
#:ret (tc-ret (-seq (-vec Univ)))
34903490
#:expected (tc-ret (-seq (-vec Univ)))]
34913491

3492+
[tc-err
3493+
(ann (list (symbol->string "10")) (Listof String))
3494+
#:ret (tc-ret (-lst -String))
3495+
#:expected (tc-ret (-lst -String))
3496+
#:msg #rx"expected: Symbol.*given: String.*"]
3497+
34923498
;; PR 14557 - apply union of functions with different return values
34933499
[tc-err
34943500
(let ()

0 commit comments

Comments
 (0)