Rob MacLachlan wrote:
> This test is somewhat hueristic, but the idea is that insofar as
> possible, dead code introduced by macros should not cause a note.
That is good to know. I was unaware that there was any magic that goes
on here. As a rule, I treat the note as constructive, even with code
generated by macros. Usually, if a macro is causing code to be deleted
in my application, the macro could be written in a better fashion.
> If SB-KERNEL:FLOAT-WAIT doesn't appear explicitly in the source code
> being compiled, then there shouldn't be an unreachable code note, at
> least not for that particular source location.
This does seem to violate the principle of least surprise to the
developer. The simplest case of this at work is the code (on x86):
(handler-case (princ "foobar")
(error (e) e))
; in: LAMBDA NIL
; note: deleting unreachable code
; compilation unit finished
; printed 1 note
This is not a result of the with-timeout code. The expansion of
handler-bind creates a call to sb-kernel:float-wait that occurs _after_
an unconditional call to return-from (generated by handler-case). This
creates hopelessly stranded code.
Both handler-case and handler-bind add a #!+x86 (float-wait) to be
evaluated after the body forms. In the case of handler-bind, this
(float-wait) occurs after the non-local exit made after the form passed
to handler-case is evaluated.
To clarify, the full expansion of the above is:
(let ((#:g1041 nil))
(declare (ignorable #:g1041))
(setq #:g1041 sb-impl::temp)
(multiple-value-prog1 (princ "foobar")
(sb-kernel:float-wait))) ;;; <<--- *deleted* *code*
(let ((e #:g1041))
The last float-wait is the one that is nailing us. I would be greatly
interested if someone here would explain what exactly float-wait does
and why it is necessary in certain code locations for x86 (and not x86_64?).
> In this case, the macro with-timeout is definitely going to cause
> dead code notes, but the top-level source context of the note should
> be something that explicitly appears in the orginal source.
I certainly agree.
I could imagine these notes being immensely confusing and discomforting
to someone new to SBCL. I believe both issues raised here should be
> i.m.o. it would be better to change with-timeout to use FLET so as
> not to duplicate the body.
Even if the body is not duplicated in the expansion, the deleted call to
the flet bound function would be noted by SBCL. This note, since it
would refer to code not in the original source, would be even less clear.
In my opinion, with-timeout should simply timeout immediately if passed
a non-positive value for `expires`. If I have code that has the
possibility of passing 0 or -1 to with-timeout, I would be expecting it
to signal a sb-ext:timeout condition. A simple patch to achieve this is
In fact, allowing code to rely on this artifact (passing 0 or negative
numbers to with-timeout to prevent timeout checking) just feels dirty ;)
As far as handler-case / handler-bind goes, I would like to better
understand (sb-kernel:float-wait) before proposing a patch.