Opened 8 months ago

Closed 3 months ago

#1430 closed defect (invalid)

local binding should not trigger scrutinizer warning

Reported by: felix 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 8 months ago by sjamaan

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.

comment:2 Changed 5 months ago by felix

  • Summary changed from local binding should not trigger scritinizer warning to local binding should not trigger scrutinizer warning

comment:3 Changed 3 months ago by sjamaan

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.

comment:4 Changed 3 months ago by felix

  • Resolution set to invalid
  • Status changed from new to closed

Yep, sounds right.

Note: See TracTickets for help on using tickets.