Skip to content

Commit 0cf01d2

Browse files
authored
enable proposition propagation when checking module-level exprs (#1225)
close #782
1 parent e82ac35 commit 0cf01d2

File tree

4 files changed

+52
-26
lines changed

4 files changed

+52
-26
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
[cond-contracted tc-expr/t (syntax? . -> . Type?)]
1616
[cond-contracted tc-expr/t* (syntax? . -> . (values Type? boolean?))]
1717
[cond-contracted single-value ((syntax?) ((or/c tc-results/c #f)) . ->* . full-tc-results/c)]
18+
[cond-contracted tc-expr-seq (->* ((listof syntax?) (-> syntax? tc-results/c full-tc-results/c))
19+
(tc-results/c
20+
#:unreachable-op (-> (listof syntax?) void?))
21+
full-tc-results/c)]
1822
[cond-contracted tc-dep-fun-arg ((syntax?) ((or/c tc-results/c #f)) . ->* . full-tc-results/c)]))
1923

2024
(define-signature check-subforms^

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

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -407,34 +407,47 @@
407407
"expected single value, got multiple (or zero) values")]))
408408

409409

410+
(define (tc-expr-seq exps tc-expr
411+
[tail-expected (-tc-any-results #f)]
412+
#:unreachable-op [unreachable-op #f])
413+
(define any-res (-tc-any-results #f))
414+
(if (null? exps)
415+
(-tc-any-results -tt)
416+
(let loop ([exps exps])
417+
(match exps
418+
[(list tail-exp) (tc-expr tail-exp tail-expected)]
419+
[(cons e rst)
420+
(define props
421+
(match (tc-expr e any-res)
422+
[(tc-any-results: p) (list p)]
423+
[(tc-results: tcrs _)
424+
(map (match-lambda
425+
[(tc-result: _ (PropSet: p+ p-) _)
426+
(-or p+ p-)])
427+
tcrs)]))
428+
(with-lexical-env+props
429+
props
430+
#:expected any-res
431+
;; If `e` is ill-typed and unreachable-op is supplied, call
432+
;; unreachable-op. Otherwise, check the subsequent expressions
433+
#:unreachable (if unreachable-op
434+
(unreachable-op rst)
435+
(loop rst))
436+
;; Keep going with an environment extended with the
437+
;; propositions that are true if execution reaches this
438+
;; point.
439+
(loop rst))]))))
440+
410441
;; tc-body/check: syntax? tc-results? -> tc-results?
411442
;; Body must be a non empty sequence of expressions to typecheck.
412443
;; The final one will be checked against expected.
413444
(define (tc-body/check body expected)
414-
(define any-res (-tc-any-results #f))
415-
(define exps (syntax->list body))
416-
(let loop ([exps exps])
417-
(match exps
418-
[(list tail-exp) (tc-expr/check tail-exp expected)]
419-
[(cons e rst)
420-
(define results (tc-expr/check e any-res))
421-
(define props
422-
(match results
423-
[(tc-any-results: p) (list p)]
424-
[(tc-results: tcrs _)
425-
(map (match-lambda
426-
[(tc-result: _ (PropSet: p+ p-) _)
427-
(-or p+ p-)])
428-
tcrs)]))
429-
(with-lexical-env+props
430-
props
431-
#:expected any-res
432-
;; If `e` bails out, mark the rest as ignored.
433-
#:unreachable (for-each register-ignored! rst)
434-
;; Keep going with an environment extended with the
435-
;; propositions that are true if execution reaches this
436-
;; point.
437-
(loop rst))])))
445+
(tc-expr-seq (syntax->list body)
446+
tc-expr/check
447+
expected
448+
#:unreachable-op
449+
;; the expr bails out, mark the rest as ignored
450+
(lambda (rst) (for-each register-ignored! rst))))
438451

439452
;; find-stx-type : Any [(or/c Type? #f)] -> Type?
440453
;; recursively find the type of either a syntax object or the result of syntax-e

typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@
306306
;; typecheck the expressions of a module-top-level form
307307
;; no side-effects
308308
;; syntax? -> (or/c 'no-type tc-results/c)
309-
(define (tc-toplevel/pass2 form [expected (-tc-any-results -tt)])
309+
(define (tc-toplevel/pass2 form [expected (-tc-any-results #f)])
310310
(do-time (format "pass2 ~a line ~a"
311311
(if #t
312312
(substring (~a (syntax-source form))
@@ -517,7 +517,10 @@
517517
(do-time "computed def-tbl")
518518
;; typecheck the expressions and the rhss of defintions
519519
;(displayln "Starting pass2")
520-
(for-each tc-toplevel/pass2 forms)
520+
(tc-expr-seq forms (lambda (expr expected)
521+
(match (tc-toplevel/pass2 expr expected)
522+
[(? full-tc-results/c r) r]
523+
[_ (-tc-any-results -tt)])))
521524
(do-time "Finished pass2")
522525
;; check that declarations correspond to definitions
523526
;; and that any additional parsed apps are sensible
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#lang typed/racket/base
2+
3+
(define x : (U String (Listof Any)) '(1))
4+
(unless (list? x)
5+
(error "not a list" x))
6+
(length x)

0 commit comments

Comments
 (0)