Skip to content

A braceless test body opening with var is silently emptied; the obvious fix regresses one spec #2735

Description

@gHashTag

A braceless test body that opens with var or const is silently emptied. Every assertion in it is discarded, and gen_test_block emits the empty test with no marker.

test opens_with_var
    var x : i32 = 1;
    assert g(x) == 999      ← never reaches any backend

The same body works if any clause precedes the var:

test opens_with_given
    given pad = 0
    var x : i32 = 1;
    assert g(x) == 999      ← lowered

Why

parse_bdd_clauses gates its statement arm on first_clause_col, which is set after the first clause is lowered. A body opening with var/const has no earlier clause, so the column is None, the arm is skipped, and the block falls back to the wholesale discard.

I wrote the fix, measured it, and did not ship it

Seeding the column from the opening statement recovers 1,914 discarded tokens across the corpus (35,224 → 33,310, and one spec leaves the discarding set entirely).

It also regresses specs/memory/notebooklm.t27 from parsing to not parsing.

The mechanism, isolated by disabling one edit at a time rather than by reading the code: seeding the column lets an earlier clause take the statement arm, and the parser then arrives at

const (notebook, err) = notebook_find_by_name(client, "nonexistent");

— a tuple destructure the arm cannot handle — in a state where the old path would have fallen back for the whole block. Instead it dies with Expected identifier after 'const', got LParen.

Narrowing the guard to peek == Ident does not help, because the failure is not at the seeded clause: it is downstream, at a const ( several clauses later.

parse_bdd_clauses carries an explicit contract in its own doc comment:

Safety contract: this may only ADD assertions, never break a file.

That version breaks one, so it stayed out. The trailing-semicolon half of the same family shipped separately — regression-free, 154 tokens.

What the real fix probably needs

Containment rather than a better guard: the statement arm's failure should restore the block-level fallback instead of propagating a hard parse error out of the caller. Then seeding the column is safe, because the worst case returns to today's behaviour for that block rather than failing the file.

That is a change to how parse_bdd_clauses reports failure, not to when it fires, and it is worth doing on its own terms — the 1,914 tokens are the reward, and the same containment would make every future widening of this arm safe by construction.

Refs #2161

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions