Opened 7 years ago
Closed 6 years ago
#1430 closed defect (invalid)
local binding should not trigger scrutinizer warning
Reported by: | felix winkelmann | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | 5.0 |
Component: | scrutinizer | Version: | 4.13.0 |
Keywords: | Cc: | sjamaan, evhan | |
Estimated difficulty: | hard |
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
).
Change History (4)
comment:1 Changed 7 years ago by
comment:2 Changed 7 years ago by
Summary: | local binding should not trigger scritinizer warning → local binding should not trigger scrutinizer warning |
---|
comment:3 Changed 6 years ago by
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.
I think the macro definition of
while0
is in the wrong;exit
is supposed to be unhygienically introduced byloop
, butsyntax-rules
referencesexit
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 intendedexit
. This probably means we need to pass the exit identifier towhile0
, or turnwhile0
into a low-level macro which refers toexit
.