← board

U TypeInfo name spelling for scalars: our canonical name, or FPC's?

The fork

compiler/rtti_emit.inc's TypeInfoOrdName maps one canonical spelling per pxx TTypeKind. Measured against FPC 3.2.2:

source FPC 3.2.2 pxx today
TypeInfo(Integer) LongInt Integer
type TMyInt = Integer; TypeInfo(TMyInt) LongInt Integer
TypeInfo(Byte) Byte Byte
TypeInfo(Int64) Int64 Int64

Only the Integer row differs, and it differs for a structural reason: in FPC (objfpc mode) Integer is not a type of its own, it is an alias of LongInt, so its typeinfo blob is LongInt's and carries LongInt's name. pxx has tyInteger and tyInt32 as separate kinds, so it has a name of its own to report.

Options

  1. Keep Integer (today). Honest about pxx's own type system; a user who writes Integer and reads back Integer is not surprised. Diverges from FPC on a string an FPC-targeting program could compare.
  2. Report LongInt for tyInteger. Byte-for-byte FPC parity on the API. Costs: a pxx program that reads back the name it wrote gets a different word, and it entrenches an FPC implementation detail (that Integer is 32-bit and spelled LongInt) into our RTTI.
  3. Make Integer a true alias of tyInt32 and delete the separate kind. The root-cause option — it removes the fork rather than choosing a side — but it is a type-system change with reach far past RTTI, so it is a different, much larger ticket, not a decision to take here.

Recommendation

Option 1, keep Integer — unless a real corpus target is found comparing the name against 'LongInt'. Nothing in the repo branches on this string today; the FPC-parity argument is real but hypothetical, and option 2 buys parity on the one row by making the other rows describe FPC's type system rather than ours. Revisit if a compat target actually reads it.

test/test_typeinfo_named_types.pas asserts the current answer explicitly and points here, so whichever way this goes the test is the place to change it.

ANSWER (user, 2026-08-21) — neither 1 nor 2: BOTH, gated

"in strict FPC mode, we just mangle the name 'Integer' to 'Longint'. we are already compatible about the underlying type. it's just naming."

Keep Integer by default; report LongInt under strict-FPC mode. The same shape as every other parity call made this day: our own answer by default, FPC's exact convention behind the mimic flag, because "we seek LANGUAGE compliance, not error-handling compliance" — and this is not even semantics, it is a string.

Implementation: [[feature-a-typeinfo-integer-name-under-strict-fpc]].

That link resolved to nothing from 2026-08-21 to 2026-08-30 — the ticket was named here and never filed, so this decision sat in decided/ reading as discharged with nothing tracking it. Filed 2026-08-30 under exactly this slug, after first ruling out the likelier and quieter possibility that it had been delivered under another name: measured against $(PXX_STABLE), TypeInfo of a plain Integer rename reports Integer under default, --mimic-fpc, --strict-case and --strict-fpc alike. Undelivered, not undocumented.

The umbrella itself is live — --strict-fpc is absent from --help, which is what makes it look absent, but it is accepted and it changes behaviour (Char(Variant(65)) gives A by default and 6 under it). So this is a missing arm, not a missing flag.

Premise corrected before deciding (measured, FPC 3.2.2 / x86-64)

The ticket's table was right but its framing invited two wrong turns, both taken and both closed by measurement:

FPC objfpc/delphi FPC tp/fpc pxx x86-64
SizeOf(Integer) 4 2 4
SizeOf(LongInt) 4 4
SizeOf(NativeInt) / PtrInt 8 8
TypeInfo(Integer)^.Name LongInt Integer

So option 3 (make Integer a true alias of tyInt32) buys nothing here — the observable behaviour is already identical and only the RTTI label differs. It stays what the ticket called it: a much larger type-system ticket, not this one.

Why gating beats picking a side

Option 1 alone leaves a real FPC-parity gap in a compat-sensitive API. Option 2 alone buys parity on one row by making every OTHER row describe FPC's type vocabulary rather than ours — Integer genuinely is a distinct kind here (tyInteger vs tyInt32), so calling it LongInt unconditionally would state FPC's aliasing as though it were our type system.

Gating gets both and costs two lines, because the underlying type already matches. That is the cheapest possible resolution and it was not on the ticket's list.

2026-09-06 (frankA) — one supporting sentence is falsified; the DECISION is not

The decision above stands and is not reopened. This corrects a claim used to dismiss option 3:

option 3 ... buys nothing here — the observable behaviour is already identical and only the RTTI label differs.

Measured at 4d0642bfa917: the label is identical and the behaviour differs.

type TMyInt = Integer;
TypeInfo(TMyInt)  name=Integer kind=1
TypeInfo(Integer) name=Integer kind=1
TypeInfo(TMyInt) = TypeInfo(Integer)  ->  DIFFER      (fpc 3.2.2: SAME)

Two RTTI blobs describing one type, agreeing on name and on kind and differing in identity — so the standard dispatch idiom if p = TypeInfo(Integer) takes the fall-through arm for a variable declared through the alias, silently, while every name-based inspection says it should have matched.

Filed as [[bug-a-a-plain-type-alias-gets-its-own-rtti-blob-so-typeinfo-pointer-dispatch-misses]].

Why this does not touch the decision. That defect reproduces WITHIN one kind — TMyInt and Integer are both tyInteger and both named Integer — so it is not the tyInteger/tyInt32 question option 3 is about, and collapsing those kinds would not fix it. The name-spelling call, and the gating that implements it, are unaffected.

What is worth keeping is why the sentence read as safe. Its table swept SizeOf and ^.Name — the two things a scalar type is usually asked about — and both agreed, so "already identical" was true of everything measured. RTTI IDENTITY was not in the table, and it is the one property TypeInfo exists to provide. The observables a premise happens to enumerate become the definition of "observable" for every later reader, which is why the dismissal survived two re-reads of this ticket, including one of mine.