Skip to content

repsel-census red on main: for (const r of rows) no longer licenses element-shape facts (fixture_ptr_shape_elements 0/3) #7777

Description

@proggeramlug

Symptom

repsel-census is failing on main (runs 31295652054 and 31240304595, both failure):

REGRESSION:
  fixture_ptr_shape_elements: ptr-shape promoted 0, floor is 3 (-3)
  fixture_ptr_shape_elements: ptr-shape-consumed promoted 0, floor is 3 (-3)

The job is not in branch protection's required contexts (its header says promotion was a deliberate follow-up after first landing), so merges proceed over it — CLAUDE.md "four ways a gate can be unable to fail", mode 2.

Localization

The fixture's two read forms isolate cleanly on main @423bb4405 (fresh worktree, debug build):

  • Form A (for (let i = 0; i < rows.length; i++) { const s = rows[i]; … }) — promotes fine on its own.
  • Form B (for (const r of rows) { … }) — promotes zero on its own, method call or not, and its presence in the full fixture voids the whole group (E3: the desugared use of rows is not licensed, so the array loses its facts and the producer is re-denied under rule 2).

Minimal repro (promotes 0; delete the for…of loop and the producer promotes):

class Row {
  id: number; weight: number; score: number;
  constructor(id: number, weight: number) { this.id = id; this.weight = weight; this.score = 0; }
}
function build(n: number): number {
  const rows: Row[] = [];
  for (let i = 0; i < n; i++) { const row = new Row(i, i * 0.5); rows.push(row); }
  let total = 0;
  for (const r of rows) { total = total + r.weight; }
  return total;
}
console.log("b:" + build(6));

collectors/ptr_shape_elements.rs licenses the iterator form by matching the desugar's exact shape (module doc: "for (const r of A) desugars to exactly the E5 shape — a __idx local, __idx < __arr.length, Let r = IndexGet(__arr, __idx)"), and the fixture's own header predicted this failure: "If the desugar ever changes, this fixture's count drops and the gate goes red — which is the point." The gate went red; it just could not block. Suspect a change to lower/stmt_loops.rs::lazy_or_index_elem (or the alias binding it emits — e.g. a now-mutable __arr falls out of collect_alias_edges' mutable: false requirement and the bare LocalGet(rows) in its init disqualifies the array).

Found while

Validating #7770 / PR #7774 (element-group numeric proof): the census caught the drop; A/B on a pristine main worktree shows the branch and main behave identically (and the PR's indexed-form claims are unaffected — form A promotes with all three fields claimed under #7774).

Two follow-ups suggested: bisect main for the desugar change, and promote repsel-census to a required context once green (its header says exactly this).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regression

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions