← board

ParseTypeKind's builtin-name chain runs BEFORE the alias table — every builtin name shadows a source declaration

The defect

ParseTypeKind's chain of built-in type names (widechar, tdatetime, currency, sizeint, valreal, utf8string, ...) is tested before FindTypeAlias is ever consulted. A comment inside that chain asserts the opposite —

"A user or RTL declaration still wins — FindTypeAlias is consulted before this."

— and it is simply not true. The alias lookup happens further down. So a program (or an RTL unit) that declares its own type with one of those names gets the BUILT-IN meaning instead, with no diagnostic.

Why it has not bitten yet, and why that is luck

Nobody redeclares widechar or tdatetime. But the moment the P-names (PInteger, PWord, ...) were added to the same chain, it became fatal immediately: this compiler declares PWord = ^NativeInt (the machine word — see the PWord/ILP32 landmine), and the builtin PWord = ^UInt16 silently re-typed it. pw^ read TWO bytes instead of eight.

That was caught by a test that DECLARES ITS OWN PWord (test_builtin_pointer_types_b303.pas). The self-host byte-identical gate did NOT catch it — the compiler's own PWord kept working by luck of where it happens to be declared. Do not rely on the self-host gate for this class of bug; it only proves the compiler still builds itself, not that name resolution is right.

The P-names were shipped with an EXPLICIT FindTypeAlias(lo) < 0 guard on their own branch, so they are correct today. The rest of the chain is still wrong.

The fix

Consult FindTypeAlias ONCE, at the top of the identifier case, and only fall through to the builtin-name chain when it misses. Then delete the per-name guard the P-names carry, and correct the comment that started this.

Care: some builtins may be deliberately winning today (the chain maps tdatetime/currency to what lib/rtl/sysutils declares them as, so the two agree and nothing shows). Changing the order makes the RTL's declaration authoritative instead — which is what it should be, but check each name that the RTL also declares, and gate on make test + the RTL/lib tests, not just self-host.

Gate

make test + self-host byte-identical + make lib-test (this touches how RTL type names resolve).

Log