Skip to content

test(rsp): replace a tautological save-state assertion with a live-counting one - #251

Merged
doublegate merged 2 commits into
mainfrom
fix/vacuous-histogram-assertion
Aug 1, 2026
Merged

test(rsp): replace a tautological save-state assertion with a live-counting one#251
doublegate merged 2 commits into
mainfrom
fix/vacuous-histogram-assertion

Conversation

@doublegate

Copy link
Copy Markdown
Owner

A follow-up to #250, from a review that landed as it merged

Two findings arrived on #250 after I had merged it. One repeated the required-features build claim already refuted by running the command. The other was right and is fixed here.

The tautological assertion

assert_eq!(
    restored.vu_funct_histogram().len(),
    64,
    "a restored histogram must still be 64 usable slots, not an empty box"
);

The field is Box<[u64; 64]> — a fixed-size array. .len() is a compile-time constant, so this asserts 64 == 64 and can never fail.

And I had defended it, telling a reviewer on the sibling thread:

Summing to zero is what an empty box would also do. The length assertion is what distinguishes "reset" from "destroyed".

That reasoning is correct for Box<[T]> — an unsized slice, which is exactly what #245's rdram_dirty was and why that one needed the check. For a fixed-size array the failure mode is not representable. I applied a real lesson to a type it does not apply to.

What replaces it

The property actually worth pinning, and the one the sibling retired test already uses: the restored histogram is live. Execute another COP2 instruction and assert its bucket moves.

Mutation-checked — making count_vu_funct a no-op turns it red.

Writing it caught a second thing

The test failed on the first attempt, and correctly: the restored PC carries over from the earlier tick and is 4, so filling only IMEM word 0 fetches a zero and counts nothing. The instruction now goes in where the PC actually points, with a comment saying why.

The tautological version could not have found that — it never executed anything after the restore. That is the concrete cost of an assertion that cannot fail: it does not just fail to guard, it displaces the test that would have.

Gates

cargo fmt --all --check · cargo clippy --workspace --all-targets -- -D warnings · the same for work-counters · cargo test --workspace · cargo test -p rustyn64-rsp --features work-counters · RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps

…unting one

A reviewer caught that `assert_eq!(restored.vu_funct_histogram().len(), 64)` is
tautological. It is: the field is `Box<[u64; 64]>`, a FIXED-size array, so
`.len()` is a compile-time constant and the assertion could never fail.

Worse than useless — I had justified it on the sibling thread, telling a
reviewer that summing to zero is also what an empty box would do and that the
length check distinguished "reset" from "destroyed". That reasoning belongs to
`Box<[T]>`, an unsized slice, which is what #245's `rdram_dirty` was and why
THAT one needed the check. For a fixed-size array the failure mode is not
representable.

Replaced with the property actually worth pinning, which is the one the
`retired` test already uses: the restored histogram is still LIVE. Execute
another COP2 instruction and assert its bucket moves.

Writing it caught a second thing. The restored PC carries over from the first
tick and is 4, so filling only IMEM word 0 fetches a zero and counts nothing —
the test failed until the instruction was written where the PC actually points.
The tautological version could not have found that, because it never executed
anything after the restore.

Mutation-checked: making `count_vu_funct` a no-op turns it red.
Copilot AI review requested due to automatic review settings August 1, 2026 08:11
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@doublegate, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 6 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 970e4dee-b119-418d-8582-fc093c55abad

📥 Commits

Reviewing files that changed from the base of the PR and between 4fcac18 and db769fa.

📒 Files selected for processing (1)
  • crates/rustyn64-rsp/src/lib.rs

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR strengthens the work-counters RSP save-state test by replacing a tautological histogram length assertion with an execution-based assertion that the restored histogram remains “live” (i.e., a post-restore COP2 computational op increments the expected bucket).

Changes:

  • Replace an always-true len() == 64 assertion with a post-restore instruction execution that must increment funct 0x06.
  • Make the restored instance mutable and resume execution (set_halted(false) + tick()).
  • Populate IMEM beyond word 0 to ensure the restored PC fetches the intended instruction.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/rustyn64-rsp/src/lib.rs Outdated
Three review findings, all cheap.

`restored` is deserialized straight into a `mut` binding rather than an
immutable one immediately shadowed — which was also inconsistent with the
sibling `retired` test.

`0x06` becomes `VMUDN_FUNCT`, used at both the encode site and the assertion so
the two provably name the same opcode.

And the comment loses the revision history — which PR caught what, what the
first version did. That belongs in git. What stays is the part a future reader
needs: that asserting `.len()` on a `Box<[u64; 64]>` proves nothing because the
length is a compile-time constant, and that the empty-container failure mode
belongs to `Box<[T]>` instead.
@doublegate

Copy link
Copy Markdown
Owner Author

Adjudication — Antigravity review

All three adopted, in db769fa.

Suggestion: remove the PR meta-commentary — adopted

Fair, and the line is where you drew it. Gone: which PR caught what, what the first version did, the #245/#250 references. That is revision history and git holds it.

Kept, because a future reader needs it at the point of the decision rather than in a commit message they will not go looking for:

Asserting the histogram's .len() would prove nothing: the field is Box<[u64; 64]>, a fixed-size array, so its length is a compile-time constant. The empty-container failure mode that check would be reaching for belongs to Box<[T]>, an unsized slice.

That distinction is the reason this test looks the way it does, and it is exactly the mistake that was made here — so a comment saying "assert execution, not shape" without saying why would invite it back.

Plus your point about the eight IMEM words and the carried-over PC, which stays.

Suggestion: name the magic 0x06adopted

VMUDN_FUNCT, and used at both ends — the instruction encoding and the histogram assertion:

const VMUDN_FUNCT: usize = 0x06;
let word = (0x12u32 << 26) | (0x10u32 << 21) | VMUDN_FUNCT as u32;
...
assert_eq!(rsp.vu_funct_histogram()[VMUDN_FUNCT], 1, ...);

Better than a comment: with the literal written twice, a future edit could change the encoded instruction and leave the assertion checking a bucket nothing writes — which would fail loudly, but for a reason that looks like a counter bug rather than a test bug.

Nitpick: bind mut directly — adopted

Also flagged by Copilot. The shadow was an artifact of adding an execution step to a test that previously only read the value; the sibling retired test already does it the right way.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

Antigravity review (Gemini via Ultra)

This PR replaces a trivial array length assertion on a deserialized RSP state with an execution step verifying that work counters remain functional after state restoration.

Blocking issues

None found.

Suggestions

  • crates/rustyn64-rsp/src/lib.rs#L480: Replace /// with a standard comment //. Outer doc comments attached to local const bindings inside function bodies are ignored by rustdoc and produce unused_doc_comments warnings.

Nitpicks

  • crates/rustyn64-rsp/src/lib.rs#L522: Calling restored.sp.set_halted(false) is redundant because rsp was unhalted before serialization, so restored already inherited halted == false.

Automated first-pass review by agy on a self-hosted runner -- not a human review.

@doublegate
doublegate merged commit 70d6238 into main Aug 1, 2026
13 checks passed
@doublegate
doublegate deleted the fix/vacuous-histogram-assertion branch August 1, 2026 08:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants