REJECTED 2026-08-30 (frankP) — DUPLICATE, filed before I read the decided/ queue
Superseded by bug-p-object-value-types-standard-meaning [P p70,
working/, owner frank-user], which the owner decided in
decided/decide-revisit-object-types-rtl-generics-fired-the-trigger hours before
I filed this. Same wall, same line, same message. Do not work this ticket;
that one is a live lock.
I filed it off a measurement without checking decided/ or working/ for the
same subject first — the wall reproduced, so the finding was real, but the
ticket was not new. A duplicate is the invisible-work problem in the ticket
system itself: two entries that each look individually reasonable, and the reader
who greps for the wall now has to work out which is authoritative.
One fact from my measurement that the live ticket does not carry, offered
here rather than edited into another lane's working/ ticket: the wall
reproduces identically on pinned and on HEAD — same line, same message —
so it is long-standing and NOT a regression from the generics work of
2026-08-29/30. That distinction is worth having before anyone bisects for it.
The reproduction command, for whoever wants it:
$ ./compiler/pascal26 -Fu<rtl-generics/src> coll.pas # {$mode delphi}; uses Generics.Collections
$ stable_linux_amd64/default/pinned -Fu<same> coll.pas
Both: generics.collections.pas:146: generic templates must be class, record, interface, array or procedure declarations.
A generic template cannot be an object type
Repro
program g;
{$mode delphi}
type
TBox<T> = object
V: T;
end;
var
b: TBox<Integer>;
begin
b.V := 7;
writeln(b.V);
end.
pascal26:N: error: generic templates must be class, record, interface, array or procedure declarations
FPC compiles it. object is the old Turbo Pascal value-semantics class: a record
with methods and inheritance, no reference semantics, no automatic lifetime. It
is not deprecated in FPC and rtl-generics uses it deliberately, for exactly the
reason it exists — a collection helper that must not allocate.
Where it was found, and the measurement that matters
The current stop for uses Generics.Collections:
pascal26:146: error: generic templates must be class, record, interface, array or procedure declarations
in: .../rtl-generics/src/generics.collections.pas
near: T PT >>> object strict private
TCustomPointersCollection<T, PT> = object
strict private type
TLocalEnumerable = TEnumerable<T>;
protected
function Enumerable: TLocalEnumerable; inline;
Measured on HEAD and on pinned, same command, same line, same message — so
this is a long-standing gap and not a regression from any of the generics work of
2026-08-29/30. It is recorded that way deliberately: the nested-type ticket's
summary carried a stale "the stop is line 120" figure that no longer reproduced
against either binary, and an unverified corpus figure is worth less than none.
Shape of the fix, as far as it was looked at
The rejection is a kind-check on what follows = in a template declaration; the
list already admits class / record / interface / array / procedure. object is
closest to record in every respect that matters to the template machinery
(value semantics, a body terminated by end, nested type sections), so the
question is whether it can join the record arm outright or needs its own —
which is a question about inheritance (object can have a parent, records
cannot) and about the class-vs-record split in the specialization streamer, not
about the kind check itself. Nobody has traced it; do not treat this paragraph as
a design.
Note the second line of the corpus snippet: strict private type — a
visibility-qualified nested type section inside an object. Whoever takes this
should check that path is reachable before assuming the kind check is the whole
job.
Gate
make compiler/pascal26 (the byte-identical self-host fixedpoint) +
python3 tools/forwardlint.py + the repro above + the named generic tests. A new
test with FPC as the oracle. Track T sweeps the matrix.