Next: Multiple Values Optimization, Previous: Control Optimization, Up: Source Optimization [Contents][Index]
Python will delete code whenever it can prove that the code can never be executed. Code becomes unreachable when:
if
is optimized away, or
go
or
return-from
, or
When code that appeared in the original source is deleted, the compiler prints a note to indicate a possible problem (or at least unnecessary code.) For example:
(defun foo () (if t (write-line "True.") (write-line "False.")))
will result in this note:
In: DEFUN FOO (WRITE-LINE "False.") Note: Deleting unreachable code.
It is important to pay attention to unreachable code notes, since they often indicate a subtle type error. For example:
(defstruct foo a b) (defun lose (x) (let ((a (foo-a x)) (b (if x (foo-b x) :none))) ...))
results in this note:
In: DEFUN LOSE (IF X (FOO-B X) :NONE) ==> :NONE Note: Deleting unreachable code.
The :none
is unreachable, because type inference knows that the argument
to foo-a
must be a foo
, and thus can’t be nil
. Presumably the
programmer forgot that x
could be nil
when he wrote the binding for
a
.
Here is an example with an incorrect declaration:
(defun count-a (string) (do ((pos 0 (position #\a string :start (1+ pos))) (count 0 (1+ count))) ((null pos) count) (declare (fixnum pos))))
This time our note is:
In: DEFUN COUNT-A (DO ((POS 0 #) (COUNT 0 #)) ((NULL POS) COUNT) (DECLARE (FIXNUM POS))) --> BLOCK LET TAGBODY RETURN-FROM PROGN ==> COUNT Note: Deleting unreachable code.
The problem here is that pos
can never be null since it is declared a
fixnum
.
It takes some experience with unreachable code notes to be able to tell what they are trying to say. In non-obvious cases, the best thing to do is to call the function in a way that should cause the unreachable code to be executed. Either you will get a type error, or you will find that there truly is no way for the code to be executed.
Not all unreachable code results in a note:
nil
and t
are never
given, since it is too easy to confuse these constants in expanded
code with ones in the original source.
Somewhat spurious unreachable code notes can also result when a macro inserts multiple copies of its arguments in different contexts, for example:
(defmacro t-and-f (var form) `(if ,var ,form ,form)) (defun foo (x) (t-and-f x (if x "True." "False.")))
results in these notes:
In: DEFUN FOO (IF X "True." "False.") ==> "False." Note: Deleting unreachable code. ==> "True." Note: Deleting unreachable code.
It seems like it has deleted both branches of the if
, but it has really
deleted one branch in one copy, and the other branch in the other copy. Note
that these messages are only spurious in not satisfying the intent of the rule
that notes are only given when the deleted code appears in the original source;
there is always some code being deleted when a unreachable code note is
printed.
Next: Multiple Values Optimization, Previous: Control Optimization, Up: Source Optimization [Contents][Index]