Skip to content

repsel-census red since v0.5.1613: a pre-existing unnamed ptr-shape residue became visible when #10774 consumed the workload's only named mechanism #10793

Description

@proggeramlug

repsel-census has been red on main since v0.5.1613 (merge train 234). It was green on every sweep through v0.5.1612.

I landed that train, so this is mine.

Bisected with pinned release binaries, not inferred

candidate233r  perry 0.5.1612  census --gate  →  rc=0
candidate234r  perry 0.5.1613  census --gate  →  rc=1

Same command CI runs (python3 scripts/compiler_output_regression.py census --perry <bin> --keep-reports … --gate), same tree, only the compiler differs. CI agrees: success at v0.5.1611 and v0.5.1612, failure at v0.5.1614 and v0.5.1615; v0.5.1613's own run was cancelled, which is why the bracket needed closing locally.

The single hard failure

WASTED PROMOTION WITH NO NAMED MECHANISM:
  batch: 1 selected ptr-shape promotion(s) were not consumed, and not one of them
  names a mechanism. A wasted promotion with no rule attached is the state this
  census was built to end: it reads exactly like an honest zero. Either a
  mechanism recorder was removed, or a new way to drop a proof exists and needs one.

Everything else the census reports is an improvement, advisory only — and the shape of that list is the clue:

fixture_ptr_shape_elements: canonical-i32 promoted 2, floor is 1 (+1)
batch: ptr-shape promoted 3, floor is 2 (+1)
batch: ptr-shape-consumed promoted 2, floor is 1 (+1)
suite_02_loop_overhead / suite_11_prime_sieve / suite_15_mandelbrot: canonical-i32 (+1 each)
… 13 workloads, all up

Prime suspect, stated as a suspect

Train 234 carried four PRs: #10766 (literal-key member fold after const substitution), #10774 (stop disabling Ptr<Shape> in entry bodies), #10767 (string-coercion ladders), #10776 (toFixed cliff).

#10774 is the Ptr<Shape> change, the census counts ptr-shape promotions, and promotions went up across thirteen workloads — exactly what re-enabling a shape proof in entry bodies should do. The plausible mechanism is that a proof is now made in a position that previously refused it, and the path that drops it has no mechanism recorder because that path was unreachable before.

This is not commit-level bisected — I have per-train binaries, not per-commit ones, so #10774 is an attribution from the subsystem and the counter that moved, not from an A/B. Confirm before fixing.

Note #10774 is not obviously wrong here: more promotions is the point of that change, and the census's own message says the alternative reading is "a new way to drop a proof exists and needs one". The fix may well be to name the mechanism rather than to undo anything.

The process gap that let it through

My merge-train validation runs the nine cheap gates, cargo check --workspace --all-targets, the unit suites, lint, and a scoped gap sweep. repsel-census is a separate CI job and none of those invoke it, so a census regression is structurally invisible to the pre-merge check — which is why this landed in 234 and was still landing in 235, 236 and 237 before anyone looked. I am adding the census to the train driver so the next train cannot repeat it.

Worth noting the census did its job perfectly: it refused to treat a wasted promotion as an honest zero, and the message says exactly what to check. The gate is good; the thing that failed is that nobody was reading it.

Activity

  1. proggeramlug commented on Sep 20, 2026

    @proggeramlug
    ContributorAuthor

    Fixed — fix/10793-repsel-wasted-ptr-shape @ 653ec93266, queued for a merge train.

    And my framing in the issue title was wrong: #10774 is the trigger, not the fault. It did not create the wasted promotion. Diffing the two reports, exactly one entry changed on batch:

    v0.5.1612 v0.5.1613
    acc @ totalsRow consumed consumed
    totals @ module_init unconsumed, mechanism module_init_context consumed
    row @ buildRows selected, unconsumed, no mechanism selected, unconsumed, no mechanism

    v0.5.1612: wasted 2, mechanisms 1 → passes on the residue allowance. v0.5.1613: wasted 1, mechanisms 0 → red. #10774 consumed totals, which is it working as intended — and that removed the workload's only named mechanism, leaving a pre-existing unnamed residue as the only wasted promotion, and therefore the only one the check could see.

    The attribution was not left as subsystem-matching either: reconstructing "today's main minus #10769" — restoring the literal allows_ptr_shape: false / ptr_shape_denial: Some(MODULE_INIT_CONTEXT) in the Entry arm and nothing else — turns the census green and reproduces the deleted v0.5.1612 report entry-for-entry. (Also worth knowing for anyone following the trail: #10774's squashed commit is titled with issue #10769. Same change, two numbers.)

    What was actually wasted

    row in buildRows (benchmarks/app-patterns/kernels/batch.ts:55). Its only use is rows.push(row) — a contained element push into an element-shape-proven array — which clears the containment rule while giving the local no property access anywhere in the body. The field reads happen later, through the array's own element-shape fact, on a different value. The proof is sound and there is nothing to spend it on. check_unconsumed_is_explained's own docstring already named this shape: "a promotion with no access site at all is dropped by nobody." Nobody is a mechanism; it just had no recorder.

    The fix names the mechanism — no floor lowered, nothing reverted

    PTR_SHAPE_NO_ACCESS_SITE joins module_init_context and scalar_replaced, recorded from the same loop iteration as the select() it annuls, reading the use walk's own containment bookkeeping rather than a second definition of "access site". Inferring the rule at render time from selected − consumed was explicitly rejected: that fabricates a mechanism for every gap and permanently disarms the check.

    I verified it does not disarm the gate, from a different angle than the sabotage

    The concern with any "make the red gate green" change is that the greenness comes from the config rather than from the thing being fixed. So:

    fixed tree + FIXED compiler    → rc=0, "Census OK."   (9 workload lines, genuinely ran)
    fixed tree + UNFIXED compiler  → rc=1, "WASTED PROMOTION WITH NO NAMED MECHANISM"
    

    The green requires the compiler emitting the new record. Nothing in the tree relaxes anything. That is independent of the three sabotages in the branch, the most important of which is worth restating: disabling the pre-existing scalar_replaced recorder still reds fixture_alloc_buckets, suite_07_object_create and suite_12_binary_trees — the new recorder does not paper over other mechanisms.

    Still open, deliberately

    The thirteen workloads whose promotion counts rose are advisory canonical-i32/spec-abi-entry improvements from train 234, and --update was deliberately not run. The floors are all satisfied, so this is not blocking — but somebody ratcheting those floors should do it as its own change with its own justification, not as a side effect of a fix.

    The process failure, which was mine

    repsel-census is a sweep-tier job and nothing in my merge-train validation invoked it, so this was structurally invisible for four trains. I have since derived the driver's coverage from scripts/ci_plan.py --table rather than from memory: of the 12 sweep-tier jobs, it ran 7. repsel-census and security-audit are now in, and the remaining gaps are named rather than assumed — gc-stress is a 90-minute fan-in over downloaded shard artifacts, and windows-build / windows-arm64-build / harmonyos-smoke are the wrong host.

    The census itself did its job exactly right: it refused to treat a wasted promotion as an honest zero, and its message named both possible readings, one of which was correct.

  2. changed the title [-]repsel-census red since v0.5.1613 (train 234): one wasted ptr-shape promotion with no named mechanism — bisected to the train, prime suspect #10774[/-] [+]repsel-census red since v0.5.1613: a pre-existing unnamed ptr-shape residue became visible when #10774 consumed the workload's only named mechanism[/+] on Sep 20, 2026
  3. proggeramlug commented on Sep 20, 2026

    @proggeramlug
    ContributorAuthor

    Landed via merge train 239 (#10800) as v0.5.1618 — b9ba951ff8.

    repsel-census is green for the first time since v0.5.1613, and #10787 travelled with the fix without adding a wasted promotion: repsel_census rc=0 wasted_promotion=False.

    Holding #10787 back one train was only safe because the #10793-only census was verified green before assembly, so any wasted promotion in this train would have been unambiguously attributable. There was none.

    I verified the green is not a disarm, independently of the branch's own sabotages:

    fixed tree + FIXED compiler    → rc=0, "Census OK."  (9 workload lines — it genuinely ran)
    fixed tree + UNFIXED compiler  → rc=1, "WASTED PROMOTION WITH NO NAMED MECHANISM"
    

    The green requires the compiler emitting the new no_access_site record; nothing in the config relaxes anything. And the landing gate now requires repsel_census rc=0 rather than carrying its old known-red tolerance forward — a baseline that still accepts the failure it just fixed is how a fix silently stops holding.

    The corrected framing is in the train body: #10774 was the trigger, not the fault. It consumed totals, which is it working as intended, and that removed the workload's only named mechanism — exposing a pre-existing unnamed residue as the only wasted promotion the check could see. My original issue title implied otherwise and has been retitled.

    For #10787 specifically: the honesty about not reaching parity (2–7 instructions against node's 6.9–9.2) and about #7109 and the missing SlotRep::F64 being absences rather than zeros is preserved in the body. So is the o.a * 1 explanation — "Binary is a shape the predicate recognises, and the multiply normalises nothing" — which finally accounts for the + 0 versus - 0 split in #10777.

    One transient is disclosed rather than buried: cor_native-abi-proof reported native_memory_fixture during the run and does not reproduce (standalone re-run rc=0, failed_workloads: []). It is the only fixture in the corpus that shells out to cargo build for a Rust staticlib mid-check, so it is uniquely exposed to concurrent cargo activity and disk pressure, and the box was at 19–24 GB with this train's own build and sweep running. The landing gate accepts that one workload and refuses any other compiler-output failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions