The bisect
| commit | corpus stops at |
|---|---|
178270aba |
generics.defaults.pas:2729 — no overload of Create matches (the old wall) |
ad7c03b03 |
generics.defaults.pas:224 — forward type not resolved |
e1808ad71, 4a602ebb2, 340175742, master 4413aca53 |
:224, carried forward |
Driver uses generics.defaults, flags -Fu<src> -Fu<src>/inc, corpus tree hash
7314f4e13e39f7fd verified unchanged at every step. Four rebuilds.
The construct
THashFactory = class
private type
PPEqualityComparerVMT = ^PEqualityComparerVMT; { reported here }
PEqualityComparerVMT = ^TEqualityComparerVMT;
TEqualityComparerVMT = packed record ... end;
Two things that must shape the debugging
- The reported line is not the failing line. The forward-type check is deferred to the close of the section, so 224 is where the name was used. Truncating the unit at line 236 parses the block cleanly on pin AND HEAD — something later in the unit decides whether line 225 ever registers.
- The construct is refused by the pin too in a standalone repro (four
spellings: objfpc/delphi, program/unit). So this commit did not break forward
pointers; it removed whatever was letting the corpus through a weakness that
was already there. Fixing the blocker may close this without touching
ad7c03b03at all.
What is NOT wrong with ad7c03b03
Its own fix is correct and was verified here independently of its author:
Take(HashIt) in a method-callee call goes from the segfault a previous attempt
produced to arg 42, byte-matching fpc. The residual Take(Self.HashIt) is
still refused with wrong number of parameters — filed as NOT COVERED when the
original ticket was written, and worth confirming it survived into that ticket's
resolution now that it sits in done/.
Rejected 2026-09-09 — the wall moved FORWARD; the sign was inverted
The bisect is sound: ad7c03b03 is exactly where the message changes. The
sign is wrong, and with it the whole framing. Two measurements settle it.
1. Identical input, both compilers fail at 224. Binary-searching the truncation point gives line 884 of the interface as the smallest reproducing prefix. Compiling that same file with HEAD and with pin v407:
HEAD -> pascal26:224: forward type not resolved: `PEqualityComparerVMT`
PIN -> pascal26:224: forward type not resolved: `PEqualityComparerVMT`
The pin fails identically. ad7c03b03 cannot have caused it. This ticket's own
caveat 2 already said a hand-written version of the construct was refused by the
pin — that observation was right and was not carried into the conclusion.
2. The check runs AFTER the whole unit has parsed.
DrainPendingPtrTargets is called at the unit's closing end.
(pasparser_prog.inc:2068) — which is also why ParsingClassBodyCi is -1 there,
the mechanism of the real bug. So reaching that diagnostic means the unit
parsed completely, and the line it prints is where the unresolved ^T was
declared.
224 < 2729 compares a declaration site to a stopping point. At
178270aba the parse stopped at 2729 and the drain never ran. At ad7c03b03
the parse gets all the way through and the drain finally speaks, about a
declaration 2500 lines earlier. ad7c03b03 removed a wall and exposed a
latent bug that had been unreachable behind it.
This ticket's caveat 1 — "224 is where it is REPORTED, not where it fails" — was correct and one step short: it is also not where anything stopped, because nothing stopped.
What was really there, and it is fixed
[[bug-p-a-forward-pointer-in-a-class-type-section-is-not-resolved]] — a forward
pointer to a nested plain alias, refused because AliasVisibleHere reads
ParsingClassBodyCi, which is -1 at drain time. Fixed by frankZ. Verified here
at binary fba33bdc4855: the driver compiles and prints drv ok, past :224
and past the old :2729.
The residual is retired, not parked
"ad7c03b03 stopped whatever was carrying the corpus case" presupposed the
inverted sign and does not survive it. Nothing was removed; a wall was.
One honest gap, recorded so it is not read as settled: the exact construct
ad7c03b03 unblocked was never identified. The pin's own wall
(System.Integer(ALeft) - System.Integer(ARight) inside class function TCompare.UInt8) would not reduce — standalone it compiles and prints 5 on the
pin and at HEAD. So this says ad7c03b03 unblocked enough to finish the
unit, not what. The two measurements above stand without it, and the corpus
can no longer answer the question anyway: it passes either way now.
rejected/ rather than done/ because the report itself is wrong — there was
no regression. The bug it surfaced was real, has its own ticket, and is closed.