Opened 6 years ago

Closed 6 years ago

#1533 closed defect (fixed)

Scrutinizer seems to get confused about list length

Reported by: sjamaan Owned by:
Priority: major Milestone: 5.0
Component: scrutinizer Version: 5.0.0rc2
Keywords: flow analysis Cc:
Estimated difficulty: hard


Seen when compiling awful-salmonella-tar:

(/usr/home/chicken/src/awful-salmonella-tar/ast-cache-manager.scm:86) in procedure call to `scheme#car', expected argument #1 of type `pair' but was given an argument of type `null'

Here's a stripped-down example that triggers it:

(module ast-cache-manager ()

(import scheme (chicken base) (chicken process-context))

(define (usage #!optional exit-code)
  (when exit-code
    (exit exit-code)))

(let ((args (command-line-arguments)))

  (when (or (member "-h" args)
            (member "-help" args)
            (member "--help" args))
    (usage 0))

  (when (< (length args) 3)
    (usage 1))

  (let ((cache-dir (car args))
        (awful-pid (string->number (cadr args)))
        (max-items (and (not (null? (cddr args)))
                        (string->number (caddr args)))))
    (assert awful-pid)))

) ;; end module

It seems that when you remove the when, the warning goes away.

Change History (2)

comment:1 Changed 6 years ago by megane

There's at least two things going on here.

First is type smashing. The calls to usage, which has unknown type
smashes the type of args to (or pair null). This can be avoided by
moving the usage calls to tail call positions.

In theory, defining usage like this should help:

(define usage
  (the (#!optional fixnum -> noreturn)
        (lambda (#!optional exit-code)
          (when exit-code
            (exit exit-code)))))

But doesn't, for some reason.

Secondly, there's an issue with refinement:

(import scheme (chicken base) (chicken type))

(let ([a (the (or pair null) (cons 1 '()))])
  (length a) ; refine (or pair null) with list (= (or pair null))
  (compiler-typecase a ((not *) 1)))
;; Error: at toplevel:
;;   (hoi.scm:33) no clause applies in `compiler-typecase' for expression of type `null':
;;     (not *)

The type should stay (or pair null), but is refined to null.

comment:2 Changed 6 years ago by sjamaan

Resolution: fixed
Status: newclosed

Fixed with b7e293696efe4f1bfdfdcd8239c0b76de0dd615f

Note: See TracTickets for help on using tickets.