Assuming that the symbol foo is not defined nor declared with a defvar or let form, the following code generates a byte-compiler warning in Emacs 26.3 and 27.2:
(defun f-or ()
"Use or."
(when (or (null (boundp 'foo))
(null foo)) ;=> ``Warning: reference to free variable ‘foo’``
(message "foo is not set")))
However, the following, longer, but de Morgan equivalent code does not generate a byte-compiler warning:
(defun f-and ()
"Use and."
(when (null (and (boundp 'foo)
foo)) ; no warning here!
(message "foo is not set")))
Replacing null
for its alias not
, using (unless X ...)
instead of (when (not X) ...
changes nothing, as expected.
Question: Why does Emacs byte-compiler generate a warning for the expression using the or
form but not for the expression using the and
form? Should this be reported as a byte compiler improvement request to not generate this invalid warning in both cases?
(when (null X)...)
is equivalent to(unless X ...)
.and
case.and
case is intentional, forms the basis of thebound-and-true-p
macro, and also applies tofboundp
. Checking whether a variable or function is defined and conditionally using it in that case is quite a common pattern in Elisp, especially for achieving forward/backward compatibility, so the byte-compiler is right not to complain in such cases. Any shortcomings of this feature should be reported viaM-x report-emacs-bug
, if they haven't already been.