#253 with-deprecation eval chain: version-deprecation returns NIL (even direct) + parse-version returns NIL via eval — 5 "NIL is not NUMBER" in asdf load
closedSuccessor to cave#218 (whose labels/apply macro-execution mechanism is now fixed). With the with-deprecation / with-asdf-deprecation expanders finally EXECUTING (0d55b1d), they run their level form (eval (version-deprecation *asdf-version* :style-warning "3.2" :warning "3.4")) at expansion time — and that yields NIL, which flows into asdf arithmetic → 5 census errors: 3x "NIL is not of type NUMBER | in: WITH-ASDF-DEPRECATION", 1x WITH-UPGRADABILITY, 1x EVAL-WHEN (cave#205 asdf-load, still 8 total).
TWO distinct funcl bugs in the chain, both probed with asdf loaded:
-
version-deprecation returns NIL even called DIRECTLY.
(uiop/version:version-deprecation "3.3.7" :style-warning "3.2" :warning "3.4")=> NIL. Should be :STYLE-WARNING (3.3.7 >= 3.2). Yet every sub-piece works in isolation:(parse-version "3.2" nil)=> (3 2)(funcall (quote <) 2 3)=> T,(funcall (quote <) 3 2)=> NIL- inline lexicographic< of (3 2) vs (3 3 7) => T
- version< / version<= trace by hand => :STYLE-WARNING Suspect the &key DEFAULT CHAIN (warning defaults to (next-version style-warning), error to (next-version warning), delete to (next-version error)) as compiled during asdf block-compile, or the with-upgradability notinline binding — something makes the compiled version-deprecation body compute NIL where the pieces individually dont.
-
parse-version returns NIL when called via eval.
(eval (list (quote uiop/version::parse-version) "3.2" nil))=> NIL, while the DIRECT(parse-version "3.2" nil)=> (3 2). funcl user-level eval (stdlib tree-walker) mis-calls parse-version. A simpler(eval (list (quote f) "3.2" nil))for a trivial &optional f works, so its specific to parse-versions body (block/return + loop :always/:finally + mapcar #(quote)parse-integer + split-string).
Impact: DEPRECATED asdf surface only (backward-compat defuns); core find-system/defsystem unaffected. Low priority. But two real funcl correctness bugs (compiled &key-default-chain, eval of a complex-body fn). Repro files: /tmp/wd-probe.lisp, /tmp/eval-fn.lisp patterns (load asdf, then eval/direct compare).
FIXED 04f94b6. The stated diagnosis was wrong — both "bugs" were red herrings:
&keydefault-chain works fine generically:(defun f (&key (a 10) (b (+ a 1))) ...)→(f :a 5)=(5 6 …).(3 2)(fixed by the #218 labels/apply mechanism).Real root cause:
(format nil ...)returned its rawmake-byte-vectorscratch buffer (type-of SIMPLE-VECTOR), not a SIMPLE-STRING. It printed correctly (write-string/printer are widetag-blind), butstringp= NIL andlength/char/subseqerrored on it.Chain: asdf
next-version=(unparse-version …)=(format nil "~{~D~^.~}" list)→ non-string. The secondnext-versionin the default chain ((next-version (next-version style-warning))) feeds that non-string intoparse-version, whose(unless (stringp version-string) … (return))fires → returns NIL →(incf (car (last NIL)))→ "NIL is not NUMBER". That's whyversion-deprecationwith all four keywords explicit worked but the default-chain form errored — only the chained form callsnext-versionon a formatted string.Fix:
format's null-stream branch now returns(%string-subseq bv 0 (byte-vector-length bv))— copies the written prefix into a fresh%alloc-string-bv(properly-tagged SIMPLE-STRING, trimmed to length). General correctness win: any code that formats then typechecks now works.Verified on build/funcl with real asdf loaded:
(next-version (next-version "3.2"))→"3.4"(was: error)(version-deprecation "3.3.7" :style-warning "3.2")→:WARNING(was: error)(stringp (format nil "~D" 3))→ T;(type-of (format nil "~{~D~^.~}" '(3 3)))→ SIMPLE-STRINGasdf.lisp load census 8 → 3. All 8 bootstrap shards green.
Residual census-3 (next load-clean targets for #205):
undefined function | in: REGISTER-IMAGE-RESTORE-HOOKThere is no symbol ~S in package ~S | in: LET