Summary
Scrutinizer seems to get confused about list length
Metadata
- Id: d2852b8b3031e46c9edfb0193f7f1b11f3a068bb
- Trac id: 1533
- Type: defect
- Reporter: sjamaan
- Owner:
- Cc:
- Status: closed
- Component: scrutinizer
- Estimated difficulty: hard
- Resolution: fixed
- Priority: major
- Milestone: 5.0
- Version: 5.0.0rc2
- Changetime: 2018-10-08 21:31:54 UTC
- Created: 2018-09-10 10:22:18 UTC
- Keywords: flow analysis
Description
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.
Changes and comments
[2018-09-10 11:39:53 UTC] megane wrote:
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`.
[2018-10-08 21:31:54 UTC] sjamaan changed status from new to closed
[2018-10-08 21:31:54 UTC] sjamaan set resolution to fixed
[2018-10-08 21:31:54 UTC] sjamaan wrote:
Fixed with b7e293696efe4f1bfdfdcd8239c0b76de0dd615f