#309 fasl-loaded asdf: defsystem parse dies '__G113__ expected 3, got 5' — lifted method-lambda arity split (next layer after cave#308)

closed
Opened by atgreen

With cave#308 (8b2bfb8) the fasl-loaded asdf's generic dispatch works and (asdf:load-system "alexandria") advances into parsing alexandria.asd, then:

; Error: invalid number of arguments: G113 expected 3, got 5 | in: DEFSYSTEM ; Error: Condition of type MISSING-COMPONENT. | in: LOAD-SYSTEM (consequence)

G113 is a LIFTED LAMBDA gensym (cave#300 lifts (function (lambda ...)) in CO-RUN thunks — here almost certainly a defmethod METHOD BODY recorded via mc-record-method). Expected 3, got 5: a method fn with 3 params invoked with 5 args — mc-dispatch invokes method fns with ALL generic args (variadic dispatcher forwards everything, cave#267), so a method whose lifted defun kept only the 3 REQUIRED params (dropping &rest/&key/&optional markers somewhere in the lift or in mc-method-lambda-list handling on the fasl channel) blows its strict arity check when dispatch passes 5.

Suspect chain: defmethod expansion (src/mini-clos.lisp:1086) builds (function (lambda LL body)) where LL = mc-method-lambda-list (params with specializers stripped, &rest kept); at fasl-compile the lambda LIFTS to a gensym defun (ag-repl-process-form / cave#300); check whether the lift preserves &rest/&key in the lifted defun's lambda-list on the REPLAY side vs the live compile side, and which defsystem-region defmethod owns G113 (candidates: asdf/parse-defsystem's class-for-type / parse-component-form methods with (parent name &rest keys) shapes).

Repro: fasl at 8b2bfb8; (load fasl); (setf asdf:central-registry (list "compat/alexandria/")); (asdf:load-system "alexandria") ~10s. Gensym numbering is deterministic per fasl — G113 identifies one specific lifted lambda; find it by scanning the fasl for the G113 CO and its neighboring named COs (grep -aob on the wire), or add the [INS] replay trace to see which defun precedes it.

Comments (1)

atgreen3992964266

FIXED in ce0157b — and with it, THE NORTH STAR RUNS THROUGH THE FASL: (load asdf.funclfa) 0.15s + (asdf:load-system "alexandria") => iota/flatten/curry/compose all work. Residual error noise (%DEFTYPE-REGISTER float deftypes) is byte-identical to the source-loaded control — pre-existing, unrelated.

The filed hypothesis (lifted method-lambda arity) was WRONG; the 'G113' was a red herring twice over. What it actually was — three stacked wire defects:

  1. ag-serialize-form predates unification: post-ADR-0026 defmacro forms hold SYMBOL/STRING records, which all fell into the 255 fallback the loader reads as NIL. Every wire macro's params AND body degraded to NIL soup — (defmacro defsystem (name &body options) …) reloaded as params (NIL NIL NIL), so the replay-compiled expander was a 3-FIXED-param defun. Its gensym name was the CONSUMER's G113 — the fasl's own 6-param G113 (verified by wire scan, [LIFT] traces showing 'n=6 F', gdb disassembly of the installed CO showing cmp rax,6, and a fresh-boot fn-table probe) was a NAME COINCIDENCE that ate half the investigation. Minimal repro: a 2-line &body macro through a fasl gave 'expected 3, got 5'. Fix: wire tag 6 = SYMBOL (name + optional home); keywords keep their colon and reload through the keyword door; plain tag-4 name bvs were NOT enough (a reloaded bv atom compiles quoted as a STRING literal — (apply 'register-system-definition …) then died 'not a function').

  2. Door-resolved homes on tag 6: the record home slot is first-touch garbage (the cave#303 disease, third appearance) — the defsystem body's register-system-definition atom carried home=ASDF/FIND-SYSTEM on the wire, resolving a record no install ever bound → emit-ir-apply's nameless P4 raise after the fallback declined. ag-quoted-sym-door-home-name at serialize time answers the package whose record the replay installs bind.

  3. Wire fn/value patches now APPLY at replay: they were read into the CO object and never re-resolved, while cave#299's packed install invalidates every raw rel32 they cover. Named fns escaped via the KIND-6 cell-read arm; gensym (function GN) sites are excluded from it. Call sites re-resolve against the consumer table (miss → backpatch/trap lifecycle); value sites through ag-fn-value-patch-resolve.

Debug-trail notes for posterity: the code mmap in the image-baked binary is NOT at +elf-mmap-vaddr+ (0x800000000 holds the environ bv there; true base measured ~0x405FF008) — every raw-address probe must derive the base from a live fn-ptr minus its table offset. And per-session gensym names (GN) collide across producer fasl / consumer runtime / baked image — three independent counters; a bump-past-loaded-gensyms absorber is still worth doing as hygiene (not filed as its own issue; noting here).

Gates: micro macro round-trip green, test-fast-sharded ALL 8 SHARDS PASSED, spike oracle green, --hosted 42, fixed point held.