Summary
local binding should not trigger scrutinizer warning
Metadata
- Id: 961224e8c048bc91be15c9856f0540dd04820bc3
- Trac id: 1430
- Type: defect
- Reporter: felix
- Owner:
- Cc: sjamaan, evhan
- Status: closed
- Component: scrutinizer
- Estimated difficulty: hard
- Resolution: invalid
- Priority: major
- Milestone: 5.0
- Version: 4.13.0
- Changetime: 2018-05-28 10:24:44 UTC
- Created: 2017-12-13 11:58:13 UTC
- Keywords:
Description
In `tests/syntax-tests.scm`, the following warning is produced:
" (syntax-tests.scm:412) in procedure call to `chicken.base#exit', expected argument #1 of type `fixnum' but was given an argument of type `false"'
`exit` is a local variable (an exit procedure from a `loop` macro. Either hygiene is not properly handled here, or the scrutinizer mistakes a local binding of `exit` for the global one (`chicken.base#exit`).
Changes and comments
[2017-12-13 12:09:32 UTC] sjamaan wrote:
I think the macro definition of while0 is in the wrong; exit is supposed to be unhygienically introduced by loop, but syntax-rules references exit hygienically.
This would originally have been the same because exit at toplevel was bound to a procedure directly, but that's more of an accident than intentional. So the macro(s?) will need to be rewritten to correctly refer to the intended exit. This probably means we need to pass the exit identifier to while0, or turn while0 into a low-level macro which refers to exit.
[2018-03-19 17:30:49 UTC] felix changed summary
[2018-05-27 15:30:31 UTC] sjamaan wrote:
Aha! It looks like the purpose of this test is exactly to ensure that exit is the exit procedure and not the exit of the loop, which is why it is wrapped in `(f ..)`. The code is supposed to raise an exception:
#;1> (define-syntax loop
(er-macro-transformer
(lambda (x r c)
(let ((body (cdr x)))
`(,(r 'call/cc)
(,(r 'lambda) (exit)
(,(r 'let) ,(r 'f) () ,@body (,(r 'f)))))))))
#;2> (define-syntax while0
(syntax-rules ()
((_ t b ...)
(loop (if (not t) (exit #f))
b ...))))
#;3> (while0 #f (print "no."))
Error: bad argument type - not a fixnum: #f
Call history:
<syntax> (##core#lambda () (if71 (not72 #f) (exit73 #f)) (print "no.") (f77))
<syntax> (##core#begin (##core#if (not72 #f) (exit73 #f)) (print "no.") (f77))
<syntax> (##core#if (not72 #f) (exit73 #f))
<syntax> (not72 #f)
<syntax> (exit73 #f)
<syntax> (##core#undefined)
<syntax> (print "no.")
<syntax> (##core#begin (f77))
<syntax> (f77)
<syntax> (##core#let () f77)
<syntax> (##core#begin f77)
<syntax> (##core#undefined)
<eval> (call/cc74 (lambda75 (exit) (let76 f77 () (if71 (not72 #f) (exit73 #f)) (print "no.") (f77))))
<eval> ((##core#letrec* ((f77 (##core#loop-lambda () (if71 (not72 #f) (exit73 #f)) (print "no.") (f77)))) f...
<eval> (not72 #f)
<eval> (exit73 #f) <--
So the scrutinizer warning seems correct to me. If you agree, we can close this ticket.
[2018-05-28 10:24:44 UTC] felix changed status from new to closed
[2018-05-28 10:24:44 UTC] felix set resolution to invalid
[2018-05-28 10:24:44 UTC] felix wrote:
Yep, sounds right.