Skip to content

e2e-scoped: any_call_result_trim_emits_string_tag_dispatch has been failing on main since ~2026-08-10, reddening unrelated PRs #8549

Closed

Description

@proggeramlug

Summary

crates/perry-codegen/tests/argless_builtin_extra_args.rs::any_call_result_trim_emits_string_tag_dispatch fails on clean main and has done for at least nine days. It is currently reddening e2e-scoped on every open PR that touches perry-codegen, where it reads as that PR's fault.

Proof it is not any PR's fault

Fresh worktree at origin/main (7c22189aa), nothing applied:

failures:
    any_call_result_trim_emits_string_tag_dispatch
test result: FAILED. 3 passed; 1 failed; 0 ignored

The assertion is:

assert_eq!(ir.matches("= call double @perry_fn_schema_ts__make(").count(), 2,
    "the receiver must be evaluated once in the init body (plus the generated extern wrapper)");

Observed count is 1, expected 2. The fixture is make().trim() where make is an imported extern returning Any.

Bisect so far

commit date result
debefa55c 2026-08-10 PASS
8bfdac447 2026-08-19 FAIL
6173ff9f6 2026-08-20 FAIL
8d1cca158 … 7c22189aa 08-20/21 FAIL

497 commits in the good→bad window. An automated git bisect run was started and paused when free disk fell to 7.7 GiB — ENOSPC manufactures false failures, so a paused bisect is better than a wrong answer. It needs roughly nine build-and-test rounds with ~10 GiB headroom.

Why nobody noticed

crates/*/tests/*.rs run per-PR only when the diff names them (e2e-scoped, see scripts/ci_plan.py). A break in this suite is therefore invisible on main and only surfaces on whichever PR happens to touch perry-codegen — wearing that PR's name.

This has already cost real time: it was mis-attributed to #8540, and an agent was dispatched to "fix" a receiver-evaluation bug that PR did not introduce. #8537, #8543 and #8525 carry the same inherited red.

Why it matters beyond CI noise

The count pins how many times the receiver expression is evaluated, and the receiver is a call. A count of 1 instead of 2 means the receiver is no longer materialized in the init body before the string-tag dispatch. If that reflects real emitted code rather than a changed wrapper shape, a side-effecting receiver's semantics have shifted. That needs answering before the assertion is adjusted — do not "fix" this by editing the expected count.

Suggested approach

  1. Finish the bisect with adequate disk (git bisect start; git bisect bad <main>; git bisect good debefa55c, then git bisect run on that one test).
  2. Diff the emitted IR for the fixture at the culprit commit against its parent — faster than reading the pass.
  3. Decide from JS semantics whether the new evaluation count is correct. If it is, prove observable behaviour is unchanged with a runtime fixture whose make() has a side effect, then update the assertion with that reasoning recorded. If it is not, fix the lowering.

Related

The same structural gap — a suite that only runs when a PR happens to touch it — is worth a separate look: a main-only sweep that runs the integration suites unconditionally would have caught this on the day it landed.

Activity

  1. proggeramlug commented on Aug 21, 2026

    @proggeramlug
    ContributorAuthor

    A second, independent main breakage: test_gap_eval_as_value

    While attributing PR reds I found the same sibling-evidence pattern for a gap-suite failure. test_gap_eval_as_value: pass -> crash is reported by five independent PRs:

    PR job time
    #8525 2026-08-21T14:08:01Z
    #8531 2026-08-21T13:03:29Z
    #8542 2026-08-21T13:43:30Z
    #8543 2026-08-21T14:20:37Z
    #8545 2026-08-21T15:10:16Z

    Five unrelated PRs — bun:sqlite, child_process, wasm-bindgen, process.argv, and a GC holder census — cannot plausibly break the same eval test in the same way. As with the e2e-scoped failure this issue was opened for, the base is the suspect, not the PRs.

    Worth noting these are two different suites failing for the same structural reason: a break on main surfaces on whichever PR happens to run the affected shard, wearing that PR's name. Right now main has at least two such breakages, and between them they are reddening every open PR.

    I have not yet run test_gap_eval_as_value against a clean main build to close the loop — that needs a fresh compiler build, and I would rather report the concurrence now than sit on it. It should be verified the same way the e2e-scoped one was: build clean main, run that single test, and confirm it crashes with no PR applied.

    Recommend widening this issue (or opening a sibling) to cover both, because the fix for the structural problem is the same: the integration and gap suites need an unconditional main-only sweep. Today they run per-PR only when a diff names them, so nothing observes main directly, and a breakage can sit for days — the e2e-scoped one has been there since somewhere between 2026-08-10 and 08-19 — while quietly failing every contributor's PR.

  2. proggeramlug commented on Aug 22, 2026

    @proggeramlug
    ContributorAuthor

    Closed by #8566, which fixed all five failing targets — argless_builtin_extra_args (4), native_proof_regressions (274), loop_safepoint_purity (8), temp_root_operand_temporaries (19), and perry-api-manifest.

    Two notes for the record.

    The argless_builtin_extra_args assertion moved from 2 to 1, which is what this issue warned against — but correctly. The invariant text still reads "the receiver must be evaluated exactly once"; only the accounting for the __perry_wrap_extern_* wrapper changed, because #8383 dropped it. The semantic guarantee about a side-effecting receiver is intact.

    The second gap this issue raised — test_gap_eval_as_value: pass -> crash reported by five independent PRs — is not addressed here and should stay open or move to its own issue.

    The structural problem remains the real one: these suites run per-PR only when a diff names them, so a break on main is invisible until it surfaces under someone else's PR. This one sat since roughly 2026-08-10 and cost a mis-attribution plus an agent dispatched to fix a bug the PR had not introduced. A main-only unconditional sweep would have caught it the day it landed.

  3. proggeramlug commented on Oct 12, 2026

    @proggeramlug
    ContributorAuthor

    Fixed by #8566 (merged 2026-08-22), which closed the e2e-scoped drift on all five failing targets. The separate test_gap_eval_as_value crash mentioned in the thread should be filed on its own if it still reproduces.

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