marcoheisig / fast-generic-functions

Seal your generic functions for an extra boost in performance.
MIT License
94 stars 5 forks source link

compiler-typep from default compiler macro is not correct #11

Open Gleefre opened 12 months ago

Gleefre commented 12 months ago

It checks if the expression is constant in null lexical environment, and if it is, evaluates it; but the value of an expression that is constant in null lexical environment is not necessarily the same when evaluated in given environment (because of possible lexical shadowing of functions / macros / symbol-macros).

I was able to construct a counterexample only on ACL, as other implementations don't macroexpand the expression when given to constantp. (Although because of https://github.com/marcoheisig/sealable-metaobjects/issues/3 can't test it in the context of fast-generic-funtions.)

CL-USER> (lisp-implementation-type)
"International Allegro CL Free Express Edition"
CL-USER> (defun compiler-typep (form type environment) ...)
COMPILER-TYPEP
CL-USER> (defmacro macro-integerp (form &environment env)
           (compiler-typep form 'integer env))
MACRO-INTEGERP
CL-USER> (define-symbol-macro %x 10)
%X
CL-USER> (defmacro foo ()
           '(values %x (macro-integerp %x)))
FOO
CL-USER> (foo)
10
T
CL-USER> (symbol-macrolet ((%x :symbol))
           (foo))
:SYMBOL
T  ;; should be NIL!
Gleefre commented 12 months ago

Actually, same behavior can be observed on ECL as well.