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

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
8d1cca1587c22189aa 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.

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