The Sixth Name
A date-arithmetic probe — day numbers, leap boundaries, a thirty-thousand-day round-trip, all correct against a reference on both backends — tripped over a parameter named y0. On the C backend the program would not compile, because y0 is a libm Bessel function. The twist: y0 was already on the reserved list. The list was not the problem this time; an emission path was — the plain top-level curried function declared its parameter raw while the body referenced the sanitized name, the same def/use mismatch fixed two releases earlier for a different path. The sixth collision in the parade, and the second kind of failure: names missing from the list, and paths missing the list. Six is where you stop counting instances.
The probe itself was calendar arithmetic — the part of date handling that lives past a monthly calendar. There is no date type in Mere, so a date is a tuple of year, month, and day, and the core of the probe was the pair of conversions between a civil date and a day number: days since an epoch, computed by an algorithm that leans hard on integer division and modulo, which was the axis being measured. On its own merits the probe was a clean sweep. Weekdays of known dates came out right, the interval between two dates matched a reference implementation to the day, adding a day across a leap boundary produced February twenty-ninth in a leap year and March first outside one, and a round-trip over thirty thousand consecutive day numbers — about eighty-two years — inverted perfectly, identically on the interpreter and the C backend. The suspicion that modular arithmetic would hurt turned out wrong, at least on positive ranges. Tuples as dates read fine.
A parameter named y0
The friction arrived from an unexpected direction. The conversion function’s parameter was
named y0 — year, adjusted, the natural name from the algorithm’s own presentation — and
on the C backend the program refused to compile. y0 is a Bessel function in the C math
library, and the backend includes the math header. This was the sixth name to collide with
the C namespace: index, remove, acct, dup, run, and now y0, each discovered the
same way, by an ordinary program using an ordinary word that C had already claimed.
On the list, and still broken
What made this one different is that y0 was already on the reserved list. The Bessel
functions had been added defensively long before. The sanitizer knew the name was dangerous
and would have renamed it — but the code path that emits a plain top-level curried
function’s parameter declaration never asked the sanitizer. So the declaration said y0,
raw, while the body — which captures that parameter into the closure it returns — referenced
the sanitized spelling, and the C compiler rejected the mismatch as an undeclared
identifier. Two releases earlier the identical def/use mismatch had been found and fixed
for lifted functions and closure adapters, when a gzip probe named a parameter index.
This was the same bug through a different door: not a name missing from the list, but a
path missing the list.
The fix was one line — route the plain path through the same parameter formatter the other paths already use — and the probe went green everywhere. But the accounting matters more than the fix. Six collisions now split into two failure kinds: names the hand-maintained list didn’t have yet, and emission paths that didn’t consult the list. Growing the list fixes the first kind and does nothing for the second; auditing paths fixes the second kind and does nothing for the first. Every previous fix had treated an instance. The source comment next to the list had admitted for months that the list was inherently incomplete and that the robust fix was to namespace every user name — deferred, each time, as too large. Six felt like the number at which that deferral stopped being prudence and started being debt. The next release deletes the list.