A fn def'd into a var reports a JVM-style class name (clojure.core$odd_QMARK_)

jolt fns reported (class f) = clojure.lang.IFn, so they carried no defining
symbol — clojure.spec.alpha's fn-sym (which reads a fn's class name to recover its
symbol) produced garbage, so explain-data's :pred for a bare-fn predicate was `/`
instead of e.g. clojure.core/keyword?.

Now def-var! records proc -> (ns . name) (first def of a proc wins, so an alias
like (def inc' inc) doesn't rename inc), and jolt-class-name returns "ns$munged"
for a known fn — matching the JVM, where (class odd?) is clojure.core$odd_QMARK_.
A munged fn class's ancestors include clojure.lang.AFunction's hierarchy
(IFn/AFn/Fn/Runnable/Callable), so (ancestors (class f)) still holds. Anonymous /
unregistered fns stay clojure.lang.IFn (fn-sym yields :unknown, as on the JVM).

This fixes explain-data / s/form / s/describe of bare-fn predicates in
clojure.spec.alpha (and unblocks parts of its suite + test.check's reporter test).

make test green (+1 corpus row, the (type inc) unit row updated to the JVM value),
shakesmoke byte-identical, runtime only (no re-mint).
This commit is contained in:
Yogthos 2026-06-27 21:03:12 -04:00
parent 10592fa746
commit 0becba7f93
5 changed files with 43 additions and 4 deletions

View file

@ -479,7 +479,7 @@
{:suite "type" :expr "(type (filter odd? [1 2 3]))" :expected "clojure.lang.PersistentList"}
{:suite "type" :expr "(type (lazy-seq (cons 1 nil)))" :expected "clojure.lang.LazySeq"}
{:suite "type" :expr "(type (take 2 (iterate inc 0)))" :expected "clojure.lang.PersistentList"}
{:suite "type" :expr "(type inc)" :expected "clojure.lang.IFn"}
{:suite "type" :expr "(type inc)" :expected "clojure.core$inc"}
{:suite "type" :expr "(type (sorted-map :a 1))" :expected ":map"}
{:suite "type" :expr "(type (sorted-set 1))" :expected ":jolt/sorted-set"}
{:suite "type" :expr "(type (with-meta [1] {:type :custom}))" :expected ":custom"}