← board

rparser.inc calls RExprRecId before declaring it — the FPC bootstrap seed does not compile

The measurement

$ fpc -Mobjfpc -Sh compiler/compiler.pas
rparser.inc(1416,12) Error: Identifier not found "RExprRecId"
compiler.pas(2121) Fatal: There were 1 errors compiling module, stopping

Exactly one error. The call sites are rparser.inc:1416, :2314, :2846; the declaration is at :1754. The first call precedes it by ~340 lines and there is no forward — grep -c 'RExprRecId.*forward' returns 0, against five forwards already present at :63-67 for exactly this reason.

Why every gate stayed green

pxx and FPC do not resolve names the same way. pxx resolves across the whole unit, so order does not matter to it; FPC resolves in source order and requires the forward. make compiler/pascal26 — which is the entire per-fix loop and which doubles as the byte-identical self-host fixedpoint — compiles compiler.pas with pxx. It therefore cannot see this class of defect at all, and neither can any tier of testmgr, for the same reason.

So the property that broke is the one property the normal loop structurally cannot check: a fresh tree with no trusted binary can still be seeded. That is not a Rust-frontend property, it is a repo-wide one, which is why this is p80 rather than ranked with the rest of Track R's queue.

The fix

Add, next to the existing block at rparser.inc:63-67:

function RExprRecId(node: Integer): Integer; forward;

Left to Track R rather than made here: this lane does not own rparser.inc, and the one-line certainty of the fix is not a reason to cross a lane boundary — it is the usual reason people do.

The general shape, which is not Rust's

check_forwards.sh exists in test/wasm/ because this lane hit the same thing in its own backend on 2026-08-28: WasmDataAddr was called ~300 lines above its declaration, make compiler/pascal26 passed, and only the FPC seed would have failed. That was caught by the check on the day it was written. This one is the same defect in a different file, found by the same check.

The check is generic — it reads compiler/*.inc and knows nothing about wasm — and it is sitting in a wasm-specific directory where no other lane will ever run it. Two instances in two days in two unrelated frontends says the hazard is repo-wide and the placement is wrong. Suggested follow-up, filed separately if anyone wants it: move it to tools/ and hang it off gate.sh quick, which is ~30s and already the pre-pin brake. A pin is exactly the moment the seed's health matters, and it is currently the moment nothing asks.

Log


Duplicate noted, 2026-08-29 (frankA). I filed the same defect independently as bug-r-rexprrecid-breaks-the-fpc-bootstrap-seed before seeing this one. Both are in done/ — Track R fixed the defect while I was folding them together, so "duplicate" is the right relation but rejected/ was the wrong disposition: it was a real bug and it was really fixed. This ticket is the fuller of the two; it names the landing commit (68dac6d2a) and the five existing forwards at rparser.inc:63-67.

Two facts from the duplicate worth keeping here:

Two lanes filed this within hours of each other, each finding it the moment it happened to run a wider gate. That duplication is the argument the decision ticket is weighing, in miniature.