Problem
The emission-time renumbering pass (Language.PureScript.Backend.Lua.Renumber, #306) guards against capturing free (global) references by skipping, during index allocation, any index whose direct prefix_S_index spelling occurs free in the chunk. That guard covers the terminal-run shapes — for a binder x_S_5 next to a free global x_S_0, allocation skips 0 and renumbers to x_S_1:
-- before -- after
local x_S_5 = 1 local x_S_1 = 1
return x_S_5 + x_S_0 return x_S_1 + x_S_0
It does not cover composite images: a derived name embeds its run mid-name (a dispatcher b_S_5_S_loop renumbering in step with member b_S_5), and the guard only checks the member spelling b_S_0, not the composite b_S_0_S_loop. A hand-written FFI file that reads a global literally named b_S_0_S_loop would be captured by the renamed dispatcher local.
The class is close to unreachable in practice: it needs an FFI global whose name both embeds a supply-shaped digit segment mid-name and lands exactly on a renumbered composite spelling. No real FFI code does this; the direct-spelling guard already covers every name the compiler mints today whose image equals its full spelling.
Approach
Extend the guard to post-check the full rebuilt image of every renamed binder against the chunk's free-name set, and on a hit re-allocate deterministically (bump the run's index until the composite clears). Idempotence and stability must be preserved — the skip has to be a pure function of chunk structure, mirroring how the existing counter-level skip re-derives on a second pass. Note [Supply-drawn digit runs] in the module documents the current guard's scope.
Prerequisites / Relations
Independent; hardens the pass merged in #306. No open issue depends on it.
Verification / Measurement
A unit fixture in the pass's spec: a chunk binding b_S_5 and its dispatcher b_S_5_S_loop alongside a free global read of b_S_0_S_loop must renumber the pair away from the collision (today the dispatcher lands exactly on the free spelling). The existing idempotence property (chunks generated over supply-minted name pools) and the golden corpus must stay green and byte-identical — no real artifact exercises the class.
Problem
The emission-time renumbering pass (
Language.PureScript.Backend.Lua.Renumber, #306) guards against capturing free (global) references by skipping, during index allocation, any index whose directprefix_S_indexspelling occurs free in the chunk. That guard covers the terminal-run shapes — for a binderx_S_5next to a free globalx_S_0, allocation skips0and renumbers tox_S_1:It does not cover composite images: a derived name embeds its run mid-name (a dispatcher
b_S_5_S_looprenumbering in step with memberb_S_5), and the guard only checks the member spellingb_S_0, not the compositeb_S_0_S_loop. A hand-written FFI file that reads a global literally namedb_S_0_S_loopwould be captured by the renamed dispatcher local.The class is close to unreachable in practice: it needs an FFI global whose name both embeds a supply-shaped digit segment mid-name and lands exactly on a renumbered composite spelling. No real FFI code does this; the direct-spelling guard already covers every name the compiler mints today whose image equals its full spelling.
Approach
Extend the guard to post-check the full rebuilt image of every renamed binder against the chunk's free-name set, and on a hit re-allocate deterministically (bump the run's index until the composite clears). Idempotence and stability must be preserved — the skip has to be a pure function of chunk structure, mirroring how the existing counter-level skip re-derives on a second pass.
Note [Supply-drawn digit runs]in the module documents the current guard's scope.Prerequisites / Relations
Independent; hardens the pass merged in #306. No open issue depends on it.
Verification / Measurement
A unit fixture in the pass's spec: a chunk binding
b_S_5and its dispatcherb_S_5_S_loopalongside a free global read ofb_S_0_S_loopmust renumber the pair away from the collision (today the dispatcher lands exactly on the free spelling). The existing idempotence property (chunks generated over supply-minted name pools) and the golden corpus must stay green and byte-identical — no real artifact exercises the class.