Skip to content

A braceless else was consumed and its branch dropped - #2883

Merged
gHashTag merged 2 commits into
masterfrom
w732
Aug 29, 2026
Merged

A braceless else was consumed and its branch dropped#2883
gHashTag merged 2 commits into
masterfrom
w732

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

parse_if_stmt handles two shapes — else if and else { — and has no third arm. On any other token it consumes else and returns, so the else-body is parsed as the next statement of the enclosing block and runs unconditionally.

if (a > 10) {
    x = 1;
} else
    x = 2;

emits, in every backend, the same thing as if the else keyword had been deleted:

if (a > 10) {
    x = 1;
}
x = 2;

pick(20) returns 2 where the spec says 1.

The decisive control is a comparison, not a reading

Three variants of one spec — braceless else, braced else, and else deleted:

Zig C Rust Verilog
braceless == else-deleted
braceless == braced

The token contributes literally nothing. That answers "is it just a representation I find surprising" — no backend recovers the branch from anywhere else.

Nothing reported it

parse-complete, this project's own silent-truncation detector, prints nothing discarded for a file whose else has vanished. All five commands exit 0 with zero bytes on stderr.

The then-branch has had this arm all along

Twenty lines above, in the same function:

} else {
    // single statement: if (cond) return expr;

Only the else-branch was missing it.

Scope, stated honestly

4 sites, in numeric/gf16.t27 and numeric/tf3.t27, all of the shape if (a_val >= b_val) return a else return b;. Early return accidentally preserves their semantics today, so the corruption there is latent and fires on the first non-return else-body — which the minimal spec above is.

An earlier audit reported this same shape with "0 corpus sites". The count is 4.

Two further specs changed output with zero restored elseigla/coder/pipeline.t27 and its import copy. Sorted content is identical in both: only the splice order moved, because the fixpoint now discovers the else-body's identifiers at a different point. Checked by sorting and comparing rather than assumed.

No measure moved

before after
zig ast-check 228 / 572 228 / 572
specs cc accepts 173 173
specs iverilog accepts 379 379
suite 2455 / 0 2455 / 0

The wrong parse was always valid output in all four languages.

bootstrap/stage0/FROZEN_HASH resealed.

Refs #2880

`parse_if_stmt` handles two shapes -- `else if` and `else {` -- and has
no third arm. On any other token it consumes `else` and returns, so the
else-body is parsed as the next statement of the ENCLOSING block and
runs unconditionally.

    if (a > 10) {
        x = 1;
    } else
        x = 2;

emitted, in every backend, the same thing as if the `else` keyword had
been deleted: `if (a > 10) { x = 1; }` then `x = 2;`. `pick(20)` returned
2 where the spec says 1.

The decisive control is a comparison, not a reading: the braceless output
is BYTE-IDENTICAL to the else-deleted control and DIFFERENT from the
braced one, in Zig, C, Rust and Verilog alike. The token contributes
nothing.

Nothing reported it. `parse-complete`, this project's own
silent-truncation detector, prints "nothing discarded" for a file whose
`else` has vanished.

The then-branch has had this arm all along, twenty lines above:
`// single statement: if (cond) return expr;`. Only the else-branch was
missing it.

4 sites, in `numeric/gf16.t27` and `numeric/tf3.t27`, all of the shape
`if (a_val >= b_val) return a else return b;`. Early return accidentally
preserves their semantics today, so the corruption there is latent and
fires on the first non-return else-body. An earlier audit reported this
same shape with "0 corpus sites".

Two further specs changed output with zero restored `else`
(`igla/coder/pipeline.t27` and its import copy). Sorted content is
identical in both -- only the splice ORDER moved, because the fixpoint
now discovers the else-body's identifiers at a different point. Checked
by sorting and comparing, not assumed.

No measure moved: zig ast-check 228/572, cc 173, iverilog 379, suite
2455 passed 0 failed -- the wrong parse was always valid output.

FROZEN_HASH resealed.

Refs #2880
@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-29 20:51:54 UTC

Summary

Status Count
Total Open PRs 8
PRs with Failing Checks 7
PRs with All Checks Green 1
READY 0
FAILING 7
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=7d2ffcd4a5c3 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit 0990a43 into master Aug 29, 2026
26 of 28 checks passed
gHashTag added a commit that referenced this pull request Aug 29, 2026
… improvements (#2888)

335: an audit ruled out the braceless `else` with "the corpus has 0 such
sites -- all 37 `} else <non-brace>` hits are paren-less `else if`".
There are four. They do not match that pattern because the `if` has no
braces either: `if (a >= b) return a else return b;` is one line, so
there is no `}` before the `else` to anchor on. A zero from a pattern
that cannot match the real spelling CLOSES the question, which makes the
defect harder to find again than if it had never been reported. Before
believing a zero, feed the pattern a case you know exists.

336: two ratchets went red in one hour and neither on a regression. The
Lean/Rust classifier reported four new disagreements because four specs
that could not be PARSED became parseable, so the classifier could
finally disagree with a theorem that had always been wrong. The corpus
ratchet reported 19 unexpected passes and 1 unexpected failure -- the
nineteen are that same unblocking, and the one failure is one of the
nineteen, now parsing and therefore now measurable for discard. A
down-only ratchet fails on an improvement exactly as on a regression,
and that is the design. The work is the same work, and the failure mode
is doing it without writing the reason down.

Refs #2883, #2887
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant