chicken-janitors
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-janitors] #1399: Scrutinizer produces incorrect procedure t


From: Chicken Trac
Subject: Re: [Chicken-janitors] #1399: Scrutinizer produces incorrect procedure types after merge
Date: Sun, 27 May 2018 13:25:01 -0000

#1399: Scrutinizer produces incorrect procedure types after merge
------------------------------------+----------------------
            Reporter:  LemonBoy     |      Owner:  evhan
                Type:  defect       |     Status:  reopened
            Priority:  major        |  Milestone:  4.13.0
           Component:  scrutinizer  |    Version:  4.12.0
          Resolution:               |   Keywords:
Estimated difficulty:  medium       |
------------------------------------+----------------------
Changes (by megane):

 * status:  closed => reopened
 * resolution:  fixed =>


Comment:

 LemonBoy's original analysis seems to be correct; the merged type should
 be `(procedure (* |#!rest|) . *)`. Here is a case that fails at runtime:

 {{{
 (: f1 (#!rest * -> noreturn))
 (define (f1 #!rest _) (exit))

 (: f2 (procedure (* #!rest *) . *))
 (define (f2 a #!rest _) (begin))

 (declare (not inline foo))
 (: foo ((#!rest ->) -> *))
 (define (foo f)
   (f))

 (print "running")
 (foo (if (the * #f) f1 f2))

 ;; The merged type is (procedure (#!rest) . *)
 ;; (compiler-typecase (if (the * #f) f1 f2) ((not *) 1))

 ;; Output:
 ;;
 ;; $ csc -O3 1399-case.scm && ./1399-case
 ;; running
 ;;
 ;; Error: too few arguments - received 0 but expected 1: #<procedure (f2 a
 . _)>
 ;;
 ;;      Call history:
 ;;
 ;;      1399-case.scm:12: chicken.base#print
 ;;      1399-case.scm:13: foo
 ;;      1399-case.scm:10: f             <--
 }}}

 I think the procedure merging could be implemented with a simple
 algorithm:
 {{{
 Input: (or P1 P2 ... Pk)
 T1  <- (or P1)
 T_n <- if P_n < T_n-1
          T_n-1
        else
          (or T_n-1 P_n)
 Result is T_k
 }}}

 This would return correct, but not necessarily minimal types.

 For `(or (procedure (|#!rest|) noreturn) (procedure (* |#!rest|) . *))` it
 wouldn't change the type.
 For `(or (procedure (* |#!rest|) . *) (procedure (|#!rest|) noreturn) )`
 it would return `(procedure (* |#!rest|) . *)`.

--
Ticket URL: <https://bugs.call-cc.org/ticket/1399#comment:7>
CHICKEN Scheme <https://www.call-cc.org/>
CHICKEN Scheme is a compiler for the Scheme programming language.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]