← board

s := w where w: WideChar segfaults (WideChar var → AnsiString)

Repro

var s: AnsiString; w: WideChar;
begin
  s := WideChar($41);   { direct value  -> "A"   OK }
  w := WideChar($41);
  s := w;               { via a variable -> SEGFAULT }
end.

s := WideChar($41) (direct) prints A. w := WideChar($41); s := w segfaults. Char→string and string concat are fine — only WideChar variable → string crashes.

Root

NodeIsWideCharVal (parser.inc:6243) matches only an AN_PTR_CAST node with the -3 widechar-cast sentinel — i.e. a literal widechar(x) expression. A WideChar variable read is a plain AN_IDENT, so NodeIsWideCharVal returns False, the assign path skips WrapWideCharToUTF8, and the 16-bit ordinal falls into the managed-string assign path which treats it as a pointer → deref → crash. (This is exactly the failure the code comment at the WideChar-assign site warns about, for the sibling case it does handle.)

Same class as the PChar-cast bugs: a decision keyed on node shape (the -3 cast node), missing another shape (the variable read).

Why there is no clean type-based fix

WideChar is not a distinct typeparser.inc:6612 maps widechar to tyUInt16 (the RTL is byte/ASCII; the type exists only so FPC sources compile). No subtype marker is recorded on the symbol, so after declaration a WideChar variable is indistinguishable from a Word. Keying NodeIsWideCharVal on "type is tyUInt16" would also fire for genuine Word values.

Semantic fork (needs a call — flagging, not guessing)

s := <tyUInt16 value> cannot be both:

Recommendation: convert-as-widechar. Rationale: pxx has deliberately collapsed WideChar→tyUInt16, Word → string is invalid code nobody writes, and converting matches the already-working s := widechar(x) path — least-surprise for the real use. Either way the crash must go first; a Word → string that currently segfaults is strictly worse than either resolution.

Fix (once the fork is settled)

If convert: extend NodeIsWideCharVal (or the assign-path guard) to also treat a tyUInt16 RHS assigned to a string as a widechar source, wrapping it in WrapWideCharToUTF8. Cover the cast, assign, arg, and return contexts (the shape/context matrix), per [[refactor-centralize-managed-string-pchar-conversion]].

Acceptance

Log