Skip to content

test(hytte-ui): pin the WarnLatch FIFO bound and the refusal arms' state contract (#1046) - #1048

Merged
vibechoom merged 3 commits into
mainfrom
test/1046-hytte-ui-refusal-residue
Sep 10, 2026
Merged

test(hytte-ui): pin the WarnLatch FIFO bound and the refusal arms' state contract (#1046)#1048
vibechoom merged 3 commits into
mainfrom
test/1046-hytte-ui-refusal-residue

Conversation

@vibechoom

@vibechoom vibechoom commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

What

Closes the three test-side gaps PR #1031's third-pass review found (comment
#5617800572),
filed as #1046. All in crates/hytte-ui/src/{gl_surface.rs,shader_surface.rs};
no production behaviour changes apart from one small extraction and (since
the fix round below) one rename and one reference-kind narrowing.

  1. gl_surface's WarnLatch FIFO bound had no eviction test. Its
    shader_surface twin does
    (two_broken_sources_alternating_cost_two_lines); ported it as
    a_length_evicted_by_the_bound_is_reported_again. WARNED_LENGTHS = 0
    (unbounded) used to pass both cargo test and workspace clippy.
  2. The refusal arms' state half was pinned by nothing in either file.
    Extracted refuse_data_strip (gl_surface) / refuse_data_grid
    (shader_surface, renamed in the fix round below — that file's
    vocabulary is 2-D) so the bookkeeping — data_len = 0 in gl_surface,
    not advancing data_shape in shader_surface — is a pure,
    hermetically testable function, and added the reviewer-supplied tests
    (refusing_a_data_strip_zeros_its_length_and_forgets_the_source,
    refusing_a_data_grid_does_not_advance_its_shape). The GL-backed half of
    each arm (that Texture::new really produces the Err in the first
    place) stays with build(ci): the three GL-context tests in hytte-ui skip everywhere — give the system-tests check a software GL stack (llvmpipe) so they run (#1031 review H1) #1036 — see the fix round's LOW 2 for exactly what
    this does and does not pin.
  3. Doc precision on "the compiler enforces the skip" — corrected the
    warn_on_data_upload_failure doc in shader_surface.rs: the let … else spelling stops one specific mistake (a return-dropping
    one-liner) from compiling; it does not make the skip compiler-enforced
    in general. if upload_data(…).is_none() { } still compilesthis
    claim was wrong, corrected in the fix round below
    : that spelling is
    clippy::needless_ifs under this repo's -D warnings gate. The
    genuinely silent spelling is let _ = upload_data(…);, and the fix
    round makes both spellings a compile error instead of documenting the
    gap.

Fix round — PR #1048 @ 02e6172

The adversarial review at 632c552
(comment)
returned FIX-FIRST: one MEDIUM (a mutation-table claim that did not
reproduce, plus the doc built on it) and three LOW, none a correctness risk.
Full per-finding writeup and mutation table posted as a
PR comment
see that comment for the complete record; summary:

  • MEDIUM 1 — row 4 above was wrong: if upload_data(…).is_none() { }
    does not reach a green pipeline (clippy::needless_ifs, exit 101 under
    -D warnings). The real silent spelling is let _ = upload_data(…);,
    which compiles and passes clippy clean because draw's own
    data: &mut hgl::Texture argument stays in scope once the shadowing
    let Some(data) = … else is dropped — data.bind_unit(…) then binds
    the previous texture while u_data_size describes the new shape (feat(plugin): the shader widget — Node::Shader, a plugin-supplied fragment + data buffer on the GL path (#893) #968
    review L7, restored). Fixed by renaming the shadowed binding from data
    to sampled: both drop spellings now fail with E0425, real compiler
    enforcement rather than an unenforced spelling convention.
  • LOW 1a_length_evicted_by_the_bound_is_reported_again looped
    0..WARNED_LENGTHS, so it pinned only that eviction happens, not the
    bound's value (stayed green at WARNED_LENGTHS shrunk to 3 or grown to
    9). Rewritten two-sided and literal-anchored: a local BOUND constant
    asserted equal to WARNED_LENGTHS, filled to one short of the bound,
    then the claim that fills it, then the eviction.
  • LOW 2 — the hermetic tests pin the refusal helper, not the arm
    that calls it; writing the residue in the arm around the call stays
    green either way. shader_surface's _data_shape never needed &mut
    (never written), so it is now &: advancing it inside the helper is
    E0594, a compile error instead of a test. gl_surface's data_len
    genuinely needs &mut (the helper is the one place that zeros it), so
    that half is doc-narrowed to "pins the helper" — closing it for real
    needs build(ci): the three GL-context tests in hytte-ui skip everywhere — give the system-tests check a software GL stack (llvmpipe) so they run (#1031 review H1) #1036's GL-backed test.
  • LOW 3 — the stale call-site comment ("there is nothing to bind")
    corrected in place, and both refusal-helper docs now name the tests that
    drive them.
  • INFOrefuse_data_striprefuse_data_grid in shader_surface.rs
    (matches that file's 2-D vocabulary); WarnLatch::claim's
    len() == WARNED_LENGTHS>= in both files (the exact hole that let
    bound 0 pass as unbounded).

Mutation table

Every mutation applied to the committed tree, md5sum'd before and after to
confirm it actually landed, gate run in the foreground, then reverted with
git checkout -- and re-verified against the pristine md5sum.

Original round (632c552):

# Mutation Expectation Result
1 gl_surface: WARNED_LENGTHS: usize = 80 RED REDa_length_evicted_by_the_bound_is_reported_again fails
2 gl_surface: delete *data_len = 0; from refuse_data_strip RED REDrefusing_a_data_strip_zeros_its_length_and_forgets_the_source fails
3 shader_surface: add *_data_shape = (state.data_size…, state.format); to the refusal helper RED REDrefusing_a_data_grid_does_not_advance_its_shape fails
4 shader_surface: draw's call site → if upload_data(…).is_none() { } (drop the let … else) compiles, test + clippy green WRONG — clippy exit 101 (needless_ifs); superseded below

Fix round (02e6172), re-run independently, md5sum before/after every mutation:

# Mutation Expectation Result
1 gl_surface: WARNED_LENGTHS 80 RED RED (test failure, exit 101) — const-equality assertion fails immediately
2 gl_surface: WARNED_LENGTHS 89 RED RED (test failure, exit 101) — was GREEN pre-fix (LOW 1 closed)
3 gl_surface: WARNED_LENGTHS 83 RED RED (test failure, exit 101) — was GREEN pre-fix (LOW 1 closed)
4 gl_surface: WARNED_LENGTHS 81 RED RED (test failure, exit 101) — now caught by the new test itself, not just pre-existing ones
5 gl_surface: delete *data_len = 0; from refuse_data_strip RED RED (test failure, exit 101)
6 shader_surface: write *_data_shape = (…) inside refuse_data_grid RED / compile error compile error E0594 (cannot assign, behind &) — was a test failure pre-fix, now caught earlier
7 shader_surface: draw's call site → if upload_data(…).is_none() { } (drop the let … else) compile error compile error E0425 (sampled not found)
8 shader_surface: draw's call site → let _ = upload_data(…); (the actually-silent spelling) compile error compile error E0425 (sampled not found) — this is the spelling MEDIUM 1 named
9 both: no-op both refusal-helper bodies (let _ = (…);), arms untouched RED RED (test failure, exit 101) — both new tests fail; extraction still load-bearing after the rename
10 shader_surface: helper intact, *data_shape = shape; written in the arm right after the call ? GREEN (cargo test exit 0, 87 passed; xvfb-run system-tests exit 0, 186+1 passed) — inherent to the arm/helper boundary, documented in LOW 2
11 gl_surface: helper intact, self.data_len = len; written in the arm right after the call ? GREEN (cargo test exit 0, 87 passed; xvfb-run system-tests exit 0, 186+1 passed) — data_len needs &mut, so this one has no compiler fix; doc-narrowed instead

Gates

Original round (632c552, base 7cda7e2):

Gate Exit
nix fmt -- --no-cache 0 (454 files, 2 changed — this branch's own edits)
cargo clippy -p hytte-ui --all-targets --features system-tests -- -D warnings 0
cargo clippy --workspace --all-targets --features system-tests -- -D warnings 0
cargo test -p hytte-ui 0 — 87 passed
xvfb-run -a cargo test --features system-tests -p hytte-ui 0 — 186 passed

Fix round (02e6172, rebased onto origin/main @ 26f0709), all foreground, RUSTC_WRAPPER unset:

Gate Exit
nix fmt -- --no-cache 0 (458 files, 0 changed)
cargo clippy -p hytte-ui --all-targets --features system-tests -- -D warnings 0
cargo clippy --workspace --all-targets --features system-tests -- -D warnings 0
cargo test -p hytte-ui 0 — 87 passed (unchanged count; fix round edits tests in place, adds none)
xvfb-run -a cargo test --features system-tests -p hytte-ui 0 — 186 + 1 passed, 3 GL-gated tests skip (no mesa in this sandbox)

Nothing deferred beyond what #1046 itself scoped out (#1036's GL-backed half
of each refusal arm — see the fix round's LOW 2 for the precise boundary).

🤖 Generated with Claude Code

https://claude.ai/code/session_0157rpXf1ks2hZEfdB47UJ6v

@vibechoom

Copy link
Copy Markdown
Contributor Author

Adversarial review — PR #1048 @ 632c552

FIX-FIRST — one MEDIUM (a claim in the mutation table that does not reproduce, plus the shipped doc built on it) and three LOW. Nothing here is a correctness risk: the production diff is an exactly behaviour-preserving extraction and every gate is green on the branch, so landing it and fixing in a follow-up regresses nothing. But this PR is the "be precise about what is enforced" PR, and its own row 4 is the imprecise part.

Verified first (the two structural questions)

  • Behaviour preserved. On the non-test hunks: gl_surface's arm was self.data_source = None; self.data_len = 0; warn_on_data_failure(…); return;, and refuse_data_strip does *data_source = None; *data_len = 0; warn_on_data_failure(…) — same three writes, same order, same position relative to the early return. shader_surface's arm was *data_source = None; warn_on_data_upload_failure(…); return None;*data_source = None; warn_on_data_upload_failure(…). Pure refactor, no reordering.
  • Not the pet thinks i am named annika #696 "fix the helper, not the caller" trap. No-op'ing both helper bodies (let _ = (…);) with the arms untouched is RED in both filesrefusing_a_data_strip_zeros_its_length_and_forgets_the_source and refusing_a_data_strip_does_not_advance_its_shape both fail. The arms genuinely route through the helpers; the extraction is load-bearing, not a parallel copy.

MEDIUM 1 — mutation row 4 does not reproduce, and the corrected doc names the one spelling CI already catches

crates/hytte-ui/src/shader_surface.rs:328-335

Row 4 claims that dropping the let … else for if upload_data(…).is_none() { } leaves "cargo test + clippy both green — confirmed — 87 passed, clippy 0 warnings". Applying that exact mutation at shader_surface.rs:819:

  • cargo test -p hytte-uiexit 0, 87 passed (the test half reproduces).
  • cargo clippy -p hytte-ui --all-targets --features system-tests -- -D warningsexit 101:
    error: this `if` branch is emptycrates/hytte-ui/src/shader_surface.rs:819:13 (clippy::needless_ifs).

So the flake's clippy check would reject that spelling — the doc's counterexample is the gate-caught one. The genuinely silent spelling is shorter:

let _ = upload_data(&gl, data, data_shape, data_source, &state, &self.warned_data);

Measured: cargo clippy … -- -D warningsexit 0, 0 warnings; cargo test -p hytte-uiexit 0, 87 passed. (A bare upload_data(…); would at least trip unused_must_use on Option; let _ = silences even that.)

Why either one compiles — the part the doc does not say, and the whole trap: the argument binding data, the &mut hgl::Texture destructured out of Resources and passed in at line 821, is still in scope at line 835, so data.bind_unit(&gl, 0) keeps compiling and binds the previous texture. let Some(data) = … was only shadowing it.

Failure scenario: a plugin moves its grid 8×8 → 16×16, the driver refuses the reallocation, upload_data returns None, the frame draws anyway with the old 8×8 texture bound while set_uniforms publishes u_data_size = (16,16) (shader_surface.rs:909) — the shader samples off the end of what is bound, every frame forever, because the shape is never advanced so the refusal repeats and the latch keeps it quiet after line one. #968 review L7, verbatim.

Fix (either; one line each):

  • (a, minimum) name let _ = upload_data(…); — verified gate-clean — as the counterexample in the doc, and correct row 4 of the PR body.
  • (b, strictly better — it makes the original claim true again) rename the binding so the outer data cannot silently take over:
    let Some(sampled) = upload_data() else { return; };
    …
    sampled.bind_unit(&gl, 0);
    Measured with the rename applied: cargo clippy -p hytte-ui --all-targets --features system-tests -- -D warnings → exit 0; cargo test -p hytte-ui → exit 0, 87 passed — and both drops then fail to compile: error[E0425]: cannot find value `sampled` in this scope. That restores the compiler enforcement the pre-test(hytte-ui): pin the WarnLatch FIFO bound and the refusal arms' state contract (#1046) #1048 doc claimed rather than documenting its absence, and it is a pure rename (upload_data returns Some(data) — the same texture).

LOW 1 — the FIFO test pins that eviction happens, not the bound

crates/hytte-ui/src/gl_surface.rs:1936-1958

The loop is for n in 0..WARNED_LENGTHS, so mutating the constant moves the test with it. Over four values:

bound cargo test -p hytte-ui which test fails
0 RED (101) a_length_evicted_by_the_bound_is_reported_again, alone — real, unique detection power ✅
1 RED (101) warn_on_data_failure_reaches_the_latch_and_warns_once_per_length + a_second_differently_sized_refused_data_strip_still_gets_its_own_line, both pre-existing; the new test passes at 1
3 GREEN (0)
9 (bound + 1) GREEN (0)

So "does WARNED_LENGTHS → N+1 go red too?" — no, and neither does a shrink to 3. The twin it was ported from (two_broken_sources_alternating_cost_two_lines) is not exposed to the shrink direction by its eviction half either, but its first half — ten alternating frames must cost exactly two lines — catches it; the port kept only the eviction half. The title's "pin the WarnLatch FIFO bound" is really "pin that the latch evicts at all".

Fix — two-sided and literal-anchored (red at 0, 7 and 9):

const BOUND: usize = 8;
assert_eq!(WARNED_LENGTHS, BOUND, "this test's arithmetic is written for a bound of 8");
let a = u64::from(100_000_u32);
assert!(latch.claim(a));
for n in 0..BOUND - 1 {                        // one short of the bound: a must survive
    assert!(latch.claim(200_000 + n as u64));
}
assert!(!latch.claim(a), "still remembered one short of the bound");
assert!(latch.claim(300_000));                 // the claim that fills it
assert!(latch.claim(a), "…and now evicted, so it is reported again");

Same family as the "pin external wire units as literals" rule: an assertion derived from the constant under test cannot see that constant move.

LOW 2 — what is pinned is the helper, not "the refusal arm's state contract"

crates/hytte-ui/src/gl_surface.rs:1004, crates/hytte-ui/src/shader_surface.rs:1002

Leaving both helpers intact and adding the residue in the arms, immediately after the call:

// gl_surface.rs:1004, after refuse_data_strip(…)
self.data_len = len;
// shader_surface.rs:1002, after refuse_data_strip(…)
*data_shape = shape;

cargo test -p hytte-ui exit 0 (87 passed) and xvfb-run -a cargo test --features system-tests -p hytte-ui exit 0 (186 + 1 passed). Both suites stay green with the exact two bugs the new tests are named after re-introduced: u_data_len non-zero after a refusal, and a shape advanced onto a texture with no storage.

That is inherent to the boundary #1046 chose (the GL-backed half is #1036's), not a defect introduced here — but the body's "the bookkeeping … is a pure, hermetically testable function" is fair while "the refusal arms' state half" is broader than what is pinned. Worth narrowing to "the helper's half" in the body and in the two test docs.

Sub-point, shader_surface.rs:369: _data_shape: &mut (u32, u32, ShaderFormat) is never read or written, so refusing_a_data_strip_does_not_advance_its_shape's headline assertion is already guaranteed by the compiler; its only detection power is "someone adds a write inside these three lines" — exactly your mutation 3, which I reproduced RED. (Its data_source.is_none() half does carry real weight: RED under the no-op mutation.) If you want the shape property enforced rather than asserted, take it as a shared reference — data_shape: &(u32, u32, ShaderFormat), called as refuse_data_strip(&*data_shape, …) — and the mutation stops compiling, which beats a test that catches it.

LOW 3 — the pre-correction sentence is still at the call site, where the mistake gets made

crates/hytte-ui/src/shader_surface.rs:815-818

// The latch goes *in* and the texture to sample comes back, so
// this arm has no Result to swallow and no return to forget:
// on a refusal there is nothing to bind and the else has to
// diverge (PR #1031 review H1/L2).

There is something to bind — the outer data argument, per MEDIUM 1. The correction landed only on warn_on_data_upload_failure's doc 500 lines away (line 328), which is not where a reader stands when they drop the let … else. Carry the qualification to 815-818 too (or adopt the rename, which makes the sentence true again).

Related: neither the corrected doc (328-335) nor either refuse_data_strip doc names the new hermetic tests, so a reader cannot navigate from "what is enforced?" to "what is pinned, and by which test". One intra-doc link each closes that.

INFO

  • shader_surface's copy is named refuse_data_strip, but that file's vocabulary is a 2-D grid (data_shape, DATA_UPLOAD_REFUSED, u_data_size); "strip" is gl_surface's 1-D word, carried over with the port. refuse_data_upload would match its file.
  • WarnLatch::claim (both files) gates eviction on if self.said.len() == WARNED_LENGTHS. That == is precisely what turns bound 0 into an unbounded latch — the hole the new test exists to catch. >= makes that class of mistake unreachable.

Mutation table (re-run independently; both files md5sum'd before and after each edit, then reverted and re-checked against the pristine digests 99cb7492… / a1db7035…)

# Mutation Expected Measured
1 gl_surface: WARNED_LENGTHS 8 → 0 RED RED (101) — a_length_evicted_by_the_bound_is_reported_again, alone ✅
1b gl_surface: WARNED_LENGTHS 8 → 9 ? GREEN (0) — bound value unpinned (LOW 1)
1c gl_surface: WARNED_LENGTHS 8 → 3 ? GREEN (0) — ditto
1d gl_surface: WARNED_LENGTHS 8 → 1 ? RED (101) — but via two pre-existing tests; the new test passes
2 gl_surface: delete *data_len = 0; from refuse_data_strip RED RED (101) — refusing_a_data_strip_zeros_its_length_and_forgets_the_source
3 shader_surface: advance _data_shape inside refuse_data_strip RED RED (101) — refusing_a_data_strip_does_not_advance_its_shape
4 shader_surface: let … elseif upload_data(…).is_none() {} compiles; test + clippy green test 0, clippy 101 (needless_ifs) — row 4 only half reproduces (MEDIUM 1)
5 both: no-op the refuse_data_strip bodies, arms untouched RED if wired RED (101) — both new tests fail ✅ extraction is not decorative
6 both: helpers intact, residue written in the arms ? GREENcargo test 0 (87) and system-tests 0 (186+1) (LOW 2)
7 shader_surface: let _ = upload_data(…); ? GREEN — clippy 0 warnings, test 0 (87): the silent hole (MEDIUM 1)
8 shader_surface: rename to let Some(sampled) + sampled.bind_unit clean clippy 0, test 0 (87) — and #4 / #7 then both error[E0425]: the proposed fix

Gates — pristine 632c552, foreground, RUSTC_WRAPPER unset, exit codes captured directly (never through tail/head)

Gate Exit
cargo clippy --workspace --all-targets --features system-tests -- -D warnings 0
cargo test -p hytte-ui 0 — 87 passed, 0 failed
xvfb-run -a cargo test --features system-tests -p hytte-ui 0 — 186 + 1 passed, 3 GL-gated ignored (no GL in this sandbox)
nix fmt -- --no-cache 0 — 456 files, 0 changed

Read-only review from a detached worktree at 632c552; nothing pushed to the branch.

🤖 Generated with Claude Code

https://claude.ai/code/session_0157rpXf1ks2hZEfdB47UJ6v

vibechoom and others added 3 commits September 10, 2026 14:19
…ate contract (#1046)

PR #1031's third-pass review (comment #5617800572) found three residual
gaps, all test-side: gl_surface's new WarnLatch had no eviction test (its
shader_surface twin did), the refusal arms' bookkeeping half — data_len
reset in gl_surface, data_shape NOT advancing in shader_surface — was
pinned by nothing, and one doc comment overclaimed "the compiler enforces
the skip" when only one spelling of it does.

Extracts refuse_data_strip in both files so the state half of each
refusal arm is a pure, hermetically testable function (no GL context
needed), adds the reviewer-supplied tests plus a port of
two_broken_sources_alternating_cost_two_lines for gl_surface's latch, and
corrects the doc to say the let-else shape is the contract rather than
the Option return type.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0157rpXf1ks2hZEfdB47UJ6v
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0157rpXf1ks2hZEfdB47UJ6v
…ract claim, and compiler-enforce the shape/rename fixes (#1046 fix round)

Adversarial review at 632c552 (PR #1048, issue #1046) returned FIX-FIRST:
one MEDIUM and three LOW findings, all in gl_surface.rs/shader_surface.rs,
none a correctness risk in the shipped production code.

- MEDIUM 1 (shader_surface.rs): the PR body's row 4 claimed clippy stayed
  green for `if upload_data(...).is_none() {}` — measured, that spelling is
  `clippy::needless_ifs` (exit 101) under the workspace gate. The actually
  silent spelling is the shorter `let _ = upload_data(...);`, which compiles
  clean because the call site's own `data: &mut hgl::Texture` argument stays
  in scope once the shadowing `let Some(data) = ... else` is dropped, so
  `data.bind_unit(...)` keeps binding the *previous* texture while
  `u_data_size` describes the new one (#968 review L7, restored). Fixed by
  renaming the shadowed binding to `sampled`, which the outer scope has no
  other binding for: both drop spellings now fail with `E0425`, which is
  real compiler enforcement rather than an unenforced spelling convention.
  Corrected the doc and the stale call-site comment (LOW 3) to match.

- LOW 1 (gl_surface.rs): `a_length_evicted_by_the_bound_is_reported_again`
  looped `0..WARNED_LENGTHS`, so it moved with the constant and stayed green
  at WARNED_LENGTHS shrunk to 3 or grown to 9 — it pinned only that eviction
  happens, not the bound's value. Rewritten with a literal `BOUND` anchor
  (asserted equal to WARNED_LENGTHS) and a two-sided fill/evict sequence, so
  0, 7, and 9 are all red.

- LOW 2 (both files): the new hermetic tests pin the refusal *helper*, not
  the *arm* that calls it — writing the residue in the arm around the call
  stays green either way. `shader_surface::refuse_data_grid`'s `_data_shape`
  never needed `&mut` (it never writes it), so it is now `&`: advancing the
  shape inside the helper is `E0594`, moving that half of the contract from
  a test into the type system. `gl_surface::refuse_data_strip`'s `data_len`
  genuinely has to be `&mut` (it is the one place that zeros it), so that
  half stays doc-narrowed to "pins the helper" rather than claimed as "the
  arm's state half" — closing the gap for real needs #1036's GL-backed test.

- INFO: `refuse_data_strip` renamed to `refuse_data_grid` in shader_surface.rs
  to match that file's 2-D vocabulary (data_shape/u_data_size/grid) rather
  than gl_surface's 1-D one; `WarnLatch::claim`'s `len() == WARNED_LENGTHS`
  changed to `>=` in both files, which is what let a bound of 0 pass as
  unbounded — `>=` makes that class of mistake unreachable rather than
  merely tested for.

No production behaviour changes beyond the LOW 2 reference-kind narrowing
(a pure widening from `&mut` to `&` in a parameter that was never read or
written) and the MEDIUM 1 rename (no runtime effect, same texture).

Refs #1046 #1031

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0157rpXf1ks2hZEfdB47UJ6v
@vibechoom
vibechoom force-pushed the test/1046-hytte-ui-refusal-residue branch from 632c552 to 02e6172 Compare September 10, 2026 12:39
@vibechoom

Copy link
Copy Markdown
Contributor Author

Fix round — PR #1048 @ 02e6172

Addresses the FIX-FIRST adversarial review at 632c552
(comment):
one MEDIUM, three LOW, no correctness risk. PR body updated to match (the
false "clippy 0" claim in the old row 4 is corrected there and struck
through in item 3 of "What").

Per-finding

Finding File:line What changed
MEDIUM 1 shader_surface.rs warn_on_data_upload_failure doc (~line 328) + draw's call site (~line 857) Corrected the doc: if upload_data(…).is_none() { } is clippy::needless_ifs under -D warnings, not green — the real silent spelling is let _ = upload_data(…);. Took fix (b): renamed the shadowed binding at the call site from data to sampled. The outer data: &mut hgl::Texture argument no longer offers a same-named fallback, so both drop spellings now fail with E0425 instead of silently binding the stale texture (#968 review L7).
LOW 1 gl_surface.rs a_length_evicted_by_the_bound_is_reported_again (~line 1936) Rewritten two-sided and literal-anchored: a local const BOUND: usize = 8 asserted equal to WARNED_LENGTHS, filled to BOUND - 1 (one short — a must survive), then the claim that fills the bound, then the eviction claim. No longer moves with the constant.
LOW 2 gl_surface.rs refuse_data_strip (~line 560) / shader_surface.rs refuse_data_grid (~line 355, renamed — see INFO) shader_surface's _data_shape param changed &mut (u32, u32, ShaderFormat)&(u32, u32, ShaderFormat): it was never written, so "does not advance" is now compiler-enforced (E0594 on a stray write) rather than test-asserted. gl_surface's data_len genuinely needs &mut (the helper is the one place that zeros it), so that half is doc-narrowed instead: both docs now say plainly that this pins the helper, not the arm — closing the arm's half needs #1036's GL-backed test.
LOW 3 shader_surface.rs draw's call site (~line 852) The stale "there is nothing to bind" comment corrected in place: the outer data argument is something to bind, which is exactly what MEDIUM 1's bug was. Both refusal-helper docs and the call-site comment now name the tests that drive them.
INFO shader_surface.rs (rename), both files (WarnLatch::claim) refuse_data_striprefuse_data_grid in shader_surface.rs (2-D vocabulary: data_shape/u_data_size/grid). WarnLatch::claim's self.said.len() == WARNED_LENGTHS>= WARNED_LENGTHS in both files — == is exactly what let a bound of 0 pass as unbounded pre-#1046.

Mutation table (re-run independently, md5sum before/after every mutation, reverted with git checkout -- and re-verified against the pristine digest)

Pristine: c75933b6cf253738a369bdc83375a6d2 (gl_surface.rs),
ff072e578b4d3a8b264fa48c2992d771 (shader_surface.rs).

# Mutation Expected Measured Kind
1 gl_surface: WARNED_LENGTHS 80 RED RED test failure (exit 101) — const-equality assertion fails immediately
2 gl_surface: WARNED_LENGTHS 89 RED RED test failure (exit 101) — was GREEN before this round (LOW 1)
3 gl_surface: WARNED_LENGTHS 83 RED RED test failure (exit 101) — was GREEN before this round (LOW 1)
4 gl_surface: WARNED_LENGTHS 81 RED RED test failure (exit 101) — now via the new test itself, not only the two pre-existing ones
5 gl_surface: delete *data_len = 0; from refuse_data_strip RED RED test failure (exit 101) — refusing_a_data_strip_zeros_its_length_and_forgets_the_source
6 shader_surface: add *_data_shape = (state.data_size.0.max(1), state.data_size.1.max(1), state.format); inside refuse_data_grid RED compile error E0594: cannot assign to *_data_shape, which is behind a & reference — caught before cargo test runs at all
7 shader_surface: draw's call site → if upload_data(…).is_none() { } compile error compile error E0425: cannot find value 'sampled' in this scope
8 shader_surface: draw's call site → let _ = upload_data(…); (the spelling MEDIUM 1 actually names) compile error compile error E0425: cannot find value 'sampled' in this scope — same fix closes both
9 both: no-op both refusal-helper bodies (let _ = (…);), arms untouched RED RED test failure (exit 101) — both refusing_a_data_strip_zeros_its_length_and_forgets_the_source and refusing_a_data_grid_does_not_advance_its_shape fail; extraction still load-bearing after the rename
10 shader_surface: helper intact, *data_shape = shape; added in the arm immediately after the call ? GREEN cargo test -p hytte-ui exit 0 (87 passed); xvfb-run -a cargo test --features system-tests -p hytte-ui exit 0 (186 + 1 passed) — inherent to the arm/helper boundary (documented in LOW 2's doc narrowing, not closeable without restructuring the call site)
11 gl_surface: helper intact, self.data_len = len; added in the arm immediately after the call ? GREEN cargo test -p hytte-ui exit 0 (87 passed); xvfb-run -a cargo test --features system-tests -p hytte-ui exit 0 (186 + 1 passed) — data_len needs &mut in the helper, so no compiler fix exists here; doc-narrowed instead

Gates (02e6172, rebased onto origin/main @ 26f0709; all foreground, RUSTC_WRAPPER unset, exit codes captured directly — never piped through tail/head)

Gate Exit
nix fmt -- --no-cache 0 (458 files, 0 changed)
cargo clippy -p hytte-ui --all-targets --features system-tests -- -D warnings 0
cargo clippy --workspace --all-targets --features system-tests -- -D warnings 0
cargo test -p hytte-ui 0 — 87 passed, 0 failed
xvfb-run -a cargo test --features system-tests -p hytte-ui 0 — 186 + 1 passed, 3 GL-gated tests skip (no mesa in this sandbox, same as prior rounds)

Nothing deferred beyond what #1046 itself scoped out (#1036's GL-backed half
of each refusal arm) — LOW 2's remaining gap (mutations 10/11, both GREEN)
is exactly that boundary, now stated precisely in both files' docs rather
than implied by the tests' names.

🤖 Generated with Claude Code

https://claude.ai/code/session_0157rpXf1ks2hZEfdB47UJ6v

@vibechoom
vibechoom merged commit 6ba9258 into main Sep 10, 2026
1 check passed
@vibechoom
vibechoom deleted the test/1046-hytte-ui-refusal-residue branch September 10, 2026 13:33
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.

1 participant