#656 was a shadowed registration. reduce was registered both by hand in installLangNS and by the generated //lg:native registrar; the generated body won, the closure's ArrayVector and Range fast paths were lost, and reduce ran 1.75x slower with the suite green — including TestReduceRangeFastPath, which asserts results rather than which path produced them. #686 fixed it and added TestNoNewShadowedHandRegistrations to ratchet the duplicate-registration set.
Three other guards in the same area fail the same way: they pass when the property they exist to protect stops holding. Each was raised as a non-blocking follow-up during review of #639/#640 and never filed.
Checked against main @ 8a8222d0.
1. Nothing enforces the builtins-override-primitives ordering
pkg/rt/zz_run_installers.go documents a precedence guarantee: builtins register after the installer drain, so builtin versions override the generated primitives for overlapping names (vector, cons, contains?, array-map, nth).
Swapping the two calls in that init() inverts the precedence, and go test ./pkg/rt/ still passes.
#686's new test covers a neighbouring hazard: it ratchets which names are registered twice, not which registration wins.
Either the precedence needs a test that fails when the order is wrong, or another mechanism already guarantees it and the comment should name that mechanism instead.
2. The generated-primitive audit skips source-only siblings
AuditGeneratedPrimitives (pkg/rt/generated_prim_audit_test.go) walks genPrimBindings and asserts that each generated primitive resolves in its canonical namespace. They all do. What breaks is the namespace's source-defined siblings: clojure.string/upper-case is generated and guarded, clojure.string/join comes from string.lg, and nothing in the audit looks at it.
Asserting that one known source-only name still resolves after a require would close the gap.
3. TestGeneratePreservesSourcePackageName passes on zero specs
The test (internal/primgen/prims_test.go) asserts that the generated output contains package primitives and does not contain package v2. Reverting its fixture to the pre-fix //lg:native clojure.core noop spelling still passes:
lgprimgen: no //lg:native directives found in <tmpdir>; generating empty stub
lgprimgen: generated primitives → <tmpdir>/zz_primitives_generated.go (0 specs)
--- PASS: TestGeneratePreservesSourcePackageName (0.00s)
The empty-stub branch reaches the same package clause by a different route, so the assertion holds for the wrong reason. An assertion on the spec count, or on the emitted noop binding, pins the premise.
Adjacent open work: #696 and #697, retiring and draining the hand registrations the generated registrar shadows.
Parented under #528.
#656 was a shadowed registration.
reducewas registered both by hand ininstallLangNSand by the generated//lg:nativeregistrar; the generated body won, the closure's ArrayVector and Range fast paths were lost, andreduceran 1.75x slower with the suite green — includingTestReduceRangeFastPath, which asserts results rather than which path produced them. #686 fixed it and addedTestNoNewShadowedHandRegistrationsto ratchet the duplicate-registration set.Three other guards in the same area fail the same way: they pass when the property they exist to protect stops holding. Each was raised as a non-blocking follow-up during review of #639/#640 and never filed.
Checked against
main@8a8222d0.1. Nothing enforces the builtins-override-primitives ordering
pkg/rt/zz_run_installers.godocuments a precedence guarantee: builtins register after the installer drain, so builtin versions override the generated primitives for overlapping names (vector,cons,contains?,array-map,nth).Swapping the two calls in that
init()inverts the precedence, andgo test ./pkg/rt/still passes.#686's new test covers a neighbouring hazard: it ratchets which names are registered twice, not which registration wins.
Either the precedence needs a test that fails when the order is wrong, or another mechanism already guarantees it and the comment should name that mechanism instead.
2. The generated-primitive audit skips source-only siblings
AuditGeneratedPrimitives(pkg/rt/generated_prim_audit_test.go) walksgenPrimBindingsand asserts that each generated primitive resolves in its canonical namespace. They all do. What breaks is the namespace's source-defined siblings:clojure.string/upper-caseis generated and guarded,clojure.string/joincomes fromstring.lg, and nothing in the audit looks at it.Asserting that one known source-only name still resolves after a
requirewould close the gap.3.
TestGeneratePreservesSourcePackageNamepasses on zero specsThe test (
internal/primgen/prims_test.go) asserts that the generated output containspackage primitivesand does not containpackage v2. Reverting its fixture to the pre-fix//lg:native clojure.core noopspelling still passes:The empty-stub branch reaches the same
packageclause by a different route, so the assertion holds for the wrong reason. An assertion on the spec count, or on the emittednoopbinding, pins the premise.Adjacent open work: #696 and #697, retiring and draining the hand registrations the generated registrar shadows.
Parented under #528.