One Symbol newtype carries two data classes across the FFI: UTF-8-encoded names (written with symbolIntern, read with symbolText) and raw byte string-values (written with symbolInternBytes, read with symbolBytes). Every read site currently selects the right accessor by the C value tag - convention, not type - and symbolText on a byte-value symbol would silently substitute replacement characters rather than fail.
Splitting the roles (phantom-tagged Symbol Name / Symbol Bytes, or two newtypes over the same interned representation) makes the accessor choice a type error instead of a convention, at zero runtime cost. Touches the symbol module, the thunk read paths, and the context-string marshalling.
From the #85 audit (FFI subsystem).
One
Symbolnewtype carries two data classes across the FFI: UTF-8-encoded names (written withsymbolIntern, read withsymbolText) and raw byte string-values (written withsymbolInternBytes, read withsymbolBytes). Every read site currently selects the right accessor by the C value tag - convention, not type - andsymbolTexton a byte-value symbol would silently substitute replacement characters rather than fail.Splitting the roles (phantom-tagged
Symbol Name/Symbol Bytes, or two newtypes over the same interned representation) makes the accessor choice a type error instead of a convention, at zero runtime cost. Touches the symbol module, the thunk read paths, and the context-string marshalling.From the #85 audit (FFI subsystem).