~ chicken-core (chicken-5) 62d7991d41418cb29809e3e235fe5b50619f8225
commit 62d7991d41418cb29809e3e235fe5b50619f8225
Author: Evan Hanson <evhan@foldling.org>
AuthorDate: Mon Nov 27 17:15:19 2017 +1300
Commit: Peter Bex <peter@more-magic.net>
CommitDate: Sat Dec 2 16:36:17 2017 +0100
Generalise result type when scrutiniser merges differently-valued procedures
When merging procedures with different result counts, we have to fall
back to an "any" result since there's currently no way to express that a
procedure may have, for example, zero or one results.
We also generalise union types that include a "noreturn" result to the
"any" type, since we can't (currently) do anything useful with
procedures that are potentially-but-not-certainly noreturn.
Fixes #1399.
Signed-off-by: Peter Bex <peter@more-magic.net>
diff --git a/scrutinizer.scm b/scrutinizer.scm
index 074681f1..84e96b29 100644
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -1246,13 +1246,12 @@
constraints))
(simplify (third t))))
((or)
- (let* ((ts (map simplify (cdr t)))
- (tslen (length ts)))
- (cond ((= 1 tslen) (car ts))
- ((null? ts) '*)
- ((> tslen +maximal-union-type-length+)
- (d "union-type cutoff! (~a): ~s" tslen ts)
- '*)
+ (let ((ts (delete-duplicates (map simplify (cdr t)) eq?)))
+ (cond ((null? ts) '*)
+ ((null? (cdr ts)) (car ts))
+ ((> (length ts) +maximal-union-type-length+)
+ (d "union-type cutoff! (~a): ~s" (length ts) ts)
+ '*)
((every procedure-type? ts)
(if (any (cut eq? 'procedure <>) ts)
'procedure
@@ -1281,7 +1280,7 @@
(cond ((and (pair? t) (eq? 'or (car t)))
(cdr t))
((eq? t 'undefined) (return 'undefined))
- ((eq? t 'noreturn) '())
+ ((eq? t 'noreturn) (return '*))
(else (list t)))))
ts))
(ts2 (let loop ((ts ts) (done '()))
@@ -1402,11 +1401,8 @@
(call/cc
(lambda (return)
(let loop ((ts1 ts11) (ts2 ts21))
- (cond ((null? ts1) '())
- ((null? ts2) '())
+ (cond ((and (null? ts1) (null? ts2)) '())
((or (atom? ts1) (atom? ts2)) (return '*))
- ((eq? 'noreturn (car ts1)) (loop (cdr ts1) ts2))
- ((eq? 'noreturn (car ts2)) (loop ts1 (cdr ts2)))
(else (cons (simplify-type `(or ,(car ts1) ,(car ts2)))
(loop (cdr ts1) (cdr ts2)))))))))
diff --git a/tests/scrutiny-tests-3.scm b/tests/scrutiny-tests-3.scm
index 75c88f88..a8bb7db5 100644
--- a/tests/scrutiny-tests-3.scm
+++ b/tests/scrutiny-tests-3.scm
@@ -36,3 +36,12 @@
(number 3))
(compiler-typecase x
(string 4))))
+
+
+;;; #1399 incorrect return type after merge with noreturn procedure
+
+(let ((x (the (->) something))
+ (y (the (-> noreturn) something)))
+ (compiler-typecase (if something x y)
+ ((->) (error "#1399 regression test failure"))
+ (else 'ok)))
Trap