← board

Copy on a char: FPC promotes char → string, pxx rejects

Repro (5 lines, no fuzzer needed)

program t;
{$mode objfpc}
var s: ansistring;
begin
  s := Copy('a', 1, 1);
  writeln('[', s, ']');
end.

Cause

A single-quoted single character is typed char, not string — 'ab' is a string literal, 'a' is a char. FPC promotes char → string where a string is wanted, so Copy takes it. pxx's Copy dispatch (compiler/parser.inc:8594, the arm that decides between string-Copy and dynamic-array-Copy) sees a non-string, non-array first argument and errors out.

Copy on a string variable, a multi-char literal, and nested Copy(Copy(s,…),…) all work — it is specifically the char-typed argument that falls through. So the fix is in the argument-typing arm, not in Copy itself: a char in a string context should promote, the same way it already does for + (s := s + 'a' compiles fine today, which is what makes the inconsistency visible).

Why it matters beyond the fuzzer

Char-where-string-is-expected is ordinary Pascal, and it already promotes for concatenation in pxx. Copy disagreeing with + about the same promotion is the kind of corner that makes real code fail to port for no reason a user can see.

Not promoted to a bug- ticket: this is a loud rejection of valid code, not silent wrong behaviour (the escape rule in CLAUDE.md). It blocks nothing at runtime.

Acceptance

The repro above compiles under pxx and prints [a]; a test/test_*.pas regression covers char→string promotion for Copy (and, while in there, the other string intrinsics that take a string first argument — Pos, Length, Delete, Insert — which likely share the arm).

Log