I'm not absolutely sure if it is a bug or a "feature", but it is extremely confusing. To reproduce: store this as file `test.el': (defvar special-variable nil) (defmacro is-special-as-macro () (special-variable-p 'special-variable)) (defun is-special-as-function () (is-special-as-macro)) (print (is-special-as-function)) (print (eval '(is-special-as-macro))) Now, from command line: $ rm -f test.elc; emacs --batch -l test.el This loads the file as interpreted Elisp and prints `t' two times, i.e. always recognizes the variable as special. Next, byte-compile the file before loading: $ rm -f test.elc; emacs --batch --eval "(byte-compile-file \"test.el\")"; emacs --batch -l test.elc This prints `nil' and `t', i.e. variable is now considered non-special by `is-special-as-function'. From investigating `.elc' file, it is apparent that this is encoded into it as a macroexpanded constant. Note that `is-special-as-macro' still works fine, the problem appears only when it gets macroexpanded during byte-compilation. So, apparently `defvar' form is sort of "skipped without paying attention" during byte-compilation. If I put it into an `eval-and-compile' form, then macroexpansion does produce expected result. I noticed this with code using `iter2' library. When `iter2-defun' generator functions get macroexpanded during compilation, built-in `special-variable-p' is called, because for generator functions this is important to distinguish between local and dynamic variables. The example above is derived from debugging real failure. Standard `generator' package is also affected. Here is example code: ;;; -*- lexical-binding: t -*- (require 'generator) (defvar special-variable nil) (defun get-special-variable () special-variable) (iter-defun buggy () (let ((special-variable t)) (iter-yield (get-special-variable)))) (print (iter-next (buggy))) As before, save as `test.el' and execute the same two commands. Produced output is different depending on whether the file has been byte-compiled or not. Is `eval-and-compile' the proper workaround? Can things be made less confusing by noticing declared special variables during byte-compilation? Paul