#270 Reader: :nil reads as symbol NIL, :t as T (keyword names NIL/T not keywordized)

open
Opened by atgreen

Split-independent reader bug, found mining ANSI symbols/keywordp.lsp (KEYWORDP.6: (keywordp :nil) should be T).

(eq :nil nil) => T (should be NIL — :nil is the keyword :NIL, distinct from nil) (eq :t t) => T (should be NIL) (keywordp :nil) => NIL (should be T) (symbolp :nil) => T (symbol-package :nil) — reads as nil so => (COMMON-LISP) (keywordp :foo) => T (normal keywords fine) (eq (make-symbol "NIL") nil) => NIL (so make-symbol is NOT the culprit) nil/t are correctly homed: (symbol-package nil/t) => (COMMON-LISP), NOT keyword.

Path: reader-read-symbol (reader.lisp:1217) sees leading colon -> ag-intern-keyword(":NIL") -> strip "NIL" -> ag-runtime-static-keyword-ptr / pooled / cached. The static keyword scan (ag-baked-keyword-scan-rec, reader.lisp:993) filters home-pkg == +primordial-keyword-pkg-tagged+, so it should NOT match nil (CL-homed) — yet :nil resolves to the nil constant (eq holds). Suspect a baked-pool record for NIL whose +16 home-pkg slot reads as keyword-tagged even though the runtime symbol-package of nil is CL, i.e. a discrepancy between the baked record home-pkg and the live symbol-package. Same likely for T. Low test count (KEYWORDP.6 + a few), split-independent, deferred.

Comments (1)

atgreen3992785764

CHANGED but still non-conformant (probe 2026-07-11): :nil now reads as #:NIL (an UNINTERNED symbol named NIL, keywordp NIL) and :t as #:T — previously they collapsed to NIL/T. The keywordizer special-cases the names NIL/T into fresh uninterned symbols instead of interning them in KEYWORD. ANSI: :nil is a self-evaluating keyword with (keywordp :nil) => T.