iris: the guards against silently wrong output survive into release
docs/REVIEW-2026-09-07.md's R1. Every invariant guard added on 2026-09-07
was a `debug_assert!`, and every build anybody runs on this project is
release -- the bench APK must be (the debug `libmain.so` is 325 MB and
will not install) and Iris's phone gets release too. So a `List` drawn
without a mask painted over its surroundings again, in exactly the build
the fault was found in, with nothing saying so.
Promoted to `assert!`, each O(1) or a handful per *draw* and each
protecting against output that is wrong on screen with no other symptom:
`List::draw`'s `painter.is_masked()`, `List`'s `extents`-are-on-screen
check, `Painter::set_mask`'s doubled-call check (the second call replaces
rather than nests, i.e. an unclipped widget), `Painter::glyphs`'s atlas
generation (glyphs sampled from coordinates now holding other letters),
and `List::fling`'s finiteness (one comparison per gesture; NaN
propagates into `deceleration_for`'s `ln()` and the fling never settles).
Left as `debug_assert!` and now saying so in a comment: `List::place`'s
slot-exists precondition (once per row placed per frame, and its release
failure is the `.expect` below rather than something wrong on screen) and
`poly_fit_least_squares`'s two preconditions (run on every velocity query,
with `MIN_SAMPLE_SIZE` and the `is_finite` check giving release a defined
outcome either way). `PointerClock::sample`'s ordering assert was already
annotated in 2ec0fee for the same reason.
Verified: `cargo test --lib -p iris` (103) and `cargo test -p
transcript-fixture` (12) pass in both debug *and* `--release`, which is
what says the promoted asserts do not fire on a real replayed flick;
fmt, clippy and `cargo ndk check -p iris` clean.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
7e79ec11e0
commit
551c01398f
3 files changed
+35
-8
No files matched your search
@@ -65,7 +65,12 @@ impl<'a> Painter<'a> {
|
||||
/// so keeps pointing at whichever slot it was drawn under. See
|
||||
/// `ActiveData::own_mask` for what pushing a fresh one cost.
|
||||
pub fn set_mask(&mut self, region: UiRegion) {
|
||||
debug_assert!(
|
||||
// `assert!`, not `debug_assert!`: one comparison per widget draw,
|
||||
// and the second call silently *replacing* the first is a widget
|
||||
// drawn unclipped -- which reaches the screen and nothing says so.
|
||||
// Every build anybody runs here is release
|
||||
// (docs/REVIEW-2026-09-07.md's R1).
|
||||
assert!(
|
||||
self.own_mask == MaskIdx::NONE || self.mask != self.own_mask,
|
||||
"set_mask called twice while drawing one widget: the second would replace the first \
|
||||
rather than nest inside it",
|
||||
@@ -264,8 +269,10 @@ impl<'a> Painter<'a> {
|
||||
// A caller re-emitting quads placed against an atlas that has since
|
||||
// been cleared draws every glyph from coordinates now holding
|
||||
// something else. Caught at the submission rather than on screen,
|
||||
// where it reads as fragments of unrelated letters.
|
||||
debug_assert_eq!(
|
||||
// where it reads as fragments of unrelated letters. `assert_eq!`
|
||||
// for R1's reason: two integers per laid-out string, not per
|
||||
// glyph, and the failure is unreadable text on a release build.
|
||||
assert_eq!(
|
||||
text.generation,
|
||||
self.atlas_generation(),
|
||||
"glyphs placed against atlas generation {} submitted against {}: the holder did not \
|
||||
|
||||
Reference in new issue
Block a user