[R6RS] Safe/unsafe mode

William D Clinger will at ccs.neu.edu
Thu Jul 13 13:27:57 EDT 2006

Kent wrote:
> Thanks for your patience in answering my questions.  Unfortunately, this
> confuses me further.  Based on your proposal and earlier examples, I was
> pretty sure you would say that an exception did not have to be raised. 
> Your proposal says:
>   If unsafe code does something that might generate an exception or cause
>   unspecified behavior, then all bets are off.
> Calling g with a symbol definitely "does something" that raises an
> exception, so all bets should be off.  Can you offer up something more
> precise than "does something" to justify why all bets are not off in this
> case?

Yes, I can do better.  Permit me, however, to point
out a flaw in your reasoning.  If it is true, as you
say, that `Calling g with a symbol definitely "does
something" that raises an exception', then an exception
will definitely be raised, contrary to your alleged
expectation that "all bets should be off."  Hence the
language I have already offered is precise enough to
deal with this particular example.

> Based on your response, I'm guessing that
>   (let ((f (lambda (x) (- x))))
>     (declare unsafe)
>     (f '(a)))
> must raise an exception, so a compiler cannot eta reduce (lambda (x) (- x))
> to - and propagate -, nor inline the body of f at its call site, either
> of which would produce:
>   (let ()
>     (declare unsafe)
>     (- '(a)))
> Right?

Right, assuming the context of your examples is safe
code.  Please recall that reducing (lambda (x) (- x))
to - is generally illegal even in R5RS Scheme, for
several reasons, so you can hardly complain about it
being illegal here.

> You say that g has no documented constraints.  Is there a way to document
> constraints of user-defined procedures?


> If not, are the safe and unsafe
> entry points of each user-defined procedure always the same?

Not necessarily.  Recall that implementations are free
to ignore the unsafe declaration.  Hence compilers are
free to generate unsafe-ignoring code for the safe
entry point, while generating unsafe code for the
unsafe entry point.  For example,

    (let ()
      (declare unsafe)
      (define (f x) (- x))
      (f 'a))

might not raise an exception, while

    (let ()
      (declare unsafe)
      (define (f x) (- x))
      (let ()
        (declare safe)
        (f 'a)))

might (but is not required to) raise an exception.  IMO,
this level of detail should be left for implementations
to work out on their own, without micro-management from
the editors.


More information about the R6RS mailing list