Skip to content

[fork-ffi] strings: drop the dead CodePoints fallbacks from linked output #270

Description

@Unisay

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:

  1. 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.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    OptimisationA Compiler Optimisationarea: package-setBug in a package-set fork (FFI/sources), not the compiler

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions