Problem
Data.String.CodePoints passes PureScript-side fallback functions (singletonFallback, takeFallback, codePointAtFallback, countFallback, toCodePointArrayFallback, unsafeCodePointAt0Fallback, plus the plain unsafeCodePointAt0) into its foreigns. The Lua FFI implements every operation natively and binds each fallback parameter to _; the fork's CodePoints.lua header states the fallbacks are written for UTF-16 code units and are wrong under this representation. The #186 audit confirmed every one of the 7 fallback slots is dead, yet the linker retains the fallback code because DCE cannot drop an argument to an opaque foreign call: in the committed Golden.StringCodePoints.Test golden the Fallback-named bindings alone are 108 lines / 4.4 kB, 16.9% of the linked output (a lower bound, since their transitive dependencies are not counted). The only recursive string concatenation in the whole package set lives inside these dead fallbacks, so it can never run, but it also never leaves the output.
Approach
Two candidate directions, pick one:
- Fork-side stubs. Replace the fallback definitions in the fork's
CodePoints.purs with tiny unsafeCrashWith-style stubs (they are wrong-if-run today, so a loud crash is strictly safer than the current silent wrong result if a foreign ever started calling them). Cheap, ships with a strings release and a set bump, but diverges the fork's .purs from upstream and must be re-applied on upstream syncs.
- Compiler-side dead-argument elimination. Teach the backend that specific foreigns ignore specific arguments (an allowlist in the spirit of
ForeignLift), so DCE can drop the dead argument expressions and everything only they reference. No fork divergence, benefits any future ignored-argument foreign, but is compiler work and needs a safe contract for what "ignores" means.
The fork-side stub is the pragmatic default; the compiler-side route subsumes it if the allowlist infrastructure is wanted anyway.
Prerequisites / Relations
No hard prerequisites. Found by the #186 audit (closed). The fork-side stub route is self-contained (strings patch release plus a set bump); the compiler-side route builds on the ForeignLift allowlist machinery introduced by #178 (closed).
Verification / Measurement
Linked output for a CodePoints-using program no longer contains the fallback bodies (the Golden.StringCodePoints.Test golden shrinks by roughly the measured 16.9%), and eval goldens stay unchanged.
Problem
Data.String.CodePointspasses PureScript-side fallback functions (singletonFallback,takeFallback,codePointAtFallback,countFallback,toCodePointArrayFallback,unsafeCodePointAt0Fallback, plus the plainunsafeCodePointAt0) into its foreigns. The Lua FFI implements every operation natively and binds each fallback parameter to_; the fork'sCodePoints.luaheader states the fallbacks are written for UTF-16 code units and are wrong under this representation. The #186 audit confirmed every one of the 7 fallback slots is dead, yet the linker retains the fallback code because DCE cannot drop an argument to an opaque foreign call: in the committedGolden.StringCodePoints.Testgolden the Fallback-named bindings alone are 108 lines / 4.4 kB, 16.9% of the linked output (a lower bound, since their transitive dependencies are not counted). The only recursive string concatenation in the whole package set lives inside these dead fallbacks, so it can never run, but it also never leaves the output.Approach
Two candidate directions, pick one:
CodePoints.purswith tinyunsafeCrashWith-style stubs (they are wrong-if-run today, so a loud crash is strictly safer than the current silent wrong result if a foreign ever started calling them). Cheap, ships with a strings release and a set bump, but diverges the fork's.pursfrom upstream and must be re-applied on upstream syncs.ForeignLift), so DCE can drop the dead argument expressions and everything only they reference. No fork divergence, benefits any future ignored-argument foreign, but is compiler work and needs a safe contract for what "ignores" means.The fork-side stub is the pragmatic default; the compiler-side route subsumes it if the allowlist infrastructure is wanted anyway.
Prerequisites / Relations
No hard prerequisites. Found by the #186 audit (closed). The fork-side stub route is self-contained (strings patch release plus a set bump); the compiler-side route builds on the ForeignLift allowlist machinery introduced by #178 (closed).
Verification / Measurement
Linked output for a CodePoints-using program no longer contains the fallback bodies (the
Golden.StringCodePoints.Testgolden shrinks by roughly the measured 16.9%), and eval goldens stay unchanged.