I have noticed that, when eval is called at macroexpansion time and it tries to evaluate a symbol that doesn't name a special form or a local binding in the evaluated code but names a local binding in the macroexpanded code, an exception is thrown, even if the symbol also names a global variable.
Here are some examples of this behavior and other more or less related ones:
(def x 0)
(defmacro m0 [] (eval 'x))
(let [x 1] (m0))
;=> CompilerException java.lang.UnsupportedOperationException: Can't eval locals
(let [y 1] (m0))
;=> 0
(defmacro m1 [] (eval '(inc x)))
(let [x 1] (m1))
;=> CompilerException java.lang.InstantiationException: user$eval572$eval573__574
(let [y 1] (m1))
;=> 1
(defmacro m2 [] (eval '(let [x 2] x)))
(let [x 1] (m2))
;=> 2
(defmacro m3 [] (load-string "x"))
(let [x 1] (m3))
;=> 0
(defmacro m4 [] x)
(let [x 1] (m4))
;=> 0
(let [x 1] (eval 'x))
;=> 0
I have found a short discussion about this issue here. I think that, according to this description of evaluation, a symbol in such a case should evaluate to the content of a global variable. In fact this is what happens if instead of Clojure's built-in macroexpansion mechanism we use some macroexpand-all function (let's say the one from clojure.tools.analyzer.jvm, which is the most accurate that I know of):
(require '[clojure.tools.analyzer.jvm :refer [macroexpand-all]])
(macroexpand-all '(let [x 1] (m0)))
;=> (let* [x 1] 0)
;Here is a workaround:
(defmacro mexa [form] (macroexpand-all form))
(mexa (let [x 1] (m0)))
;=> 0
So should this be considered a bug? If not, what could be the rationale? Shouldn't there be some documentation and explanation of this behavior somewhere and also a better error message when the "problematic" symbol occurs in a complex form?