Skip to content

fix(compiler): make named-fn self-reference the fn value#58

Merged
skydread1 merged 2 commits into
developfrom
fix/named-fn-self-reference
Jul 20, 2026
Merged

fix(compiler): make named-fn self-reference the fn value#58
skydread1 merged 2 commits into
developfrom
fix/named-fn-self-reference

Conversation

@skydread1

@skydread1 skydread1 commented Jul 20, 2026

Copy link
Copy Markdown
Member

Closes #52, Closes #53

  • Strip reader source meta (line/column/file/source-span/rettag) from fn forms at analysis, as stock Clojure does. A fn is no longer wrapped in withMeta, so the fn value and its self-reference are the same object. Also removes a wrapper + map allocation per fn-literal evaluation.
  • Under *direct-linking*, an arity that uses the fn's own name as a value compiles as an instance method, so the name resolves to this. Plain self-calls keep invokeStatic; recursive defns stay direct-linked.
  • Refresh DLLs (broad: every stdlib namespace containing a fn literal changes). Regression tests in magic.test.fn, plus two smoke-suite checks verified under IL2CPP.

@skydread1 skydread1 self-assigned this Jul 20, 2026
identical?/= between a named fn and its self-reference returned false
where JVM and ClojureCLR return true. Two causes: reader source meta
wrapped every fn in withMeta so the fn value was a MetaWrapper while
the self-reference resolved to the wrapped instance, and under
direct-linking the static body emitted the self-name as a fresh newobj.

fn* parsing now strips line/column/file/source-span/rettag from fn
meta like upstream FnExpr, and a method that uses the fn's own name as
a value (not as a direct callee) keeps the instance compilation so the
name resolves to this. Upstream's any-self-reference guard would strip
invokeStatic from every recursive defn since MAGIC's defn names the
fn form.

The meta strip also fixes fn literals carrying reader source-location
metadata: (meta (fn [] 1)) is now nil, matching JVM and ClojureCLR
(#53).
Broad ripple: the old compiler emitted a runtime withMeta wrap for
every literal fn expression, so every stdlib namespace with one changes.
@skydread1
skydread1 force-pushed the fix/named-fn-self-reference branch from 5ced510 to a50e522 Compare July 20, 2026 02:14
@skydread1
skydread1 merged commit 642698f into develop Jul 20, 2026
1 check passed
@skydread1
skydread1 deleted the fix/named-fn-self-reference branch July 21, 2026 02:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant