Hold a clipping widget to its box, and check that it is

`Scroll` reports `LEFTOVER` on both axes because it clips its content to its
box: it can neither take less of one nor honestly ask for more. `Masked` is
the other widget that clips and was passing its inner's size up, so a mask
over something taller than its box asked to be placed at the length it had
just cut off. It reports its box now, for the same reason.

The `debug_assert` the handoff has been asking for is the one that would have
caught both, narrowed to what is actually true: a widget that set a mask this
draw has to report inside the box it drew in. Reported as "does not exceed
the box" it fires on ordinary overflow instead -- measured, a hundred fuzzer
trees produce thousands of them, every one a text too tall for the box it was
offered, which is what a text is meant to say.

`tests/cases/scroll.rs` has a clipping widget that reports its content, to
show the assertion catches it.

Checked: fmt, clippy, 104 tests, all five shrinker cases at 300 seeds, 100
generated seeds, five examples byte-identical at 1920x1200.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Opus 5 committed 2026-09-16 03:48:23 -04:00
1 parent bdab55824f
commit 95fb4f962c
3 files changed
+49 -1

No files matched your search

+7 -1
View File
@@ -7,6 +7,12 @@ pub struct Masked {
impl Widget for Masked {
fn draw(&mut self, painter: &mut Painter) -> Size {
painter.set_mask(painter.region());
painter.widget(&self.inner).size()
painter.widget(&self.inner);
// What it occupies is its box, on both axes, for the reason `Scroll`
// reports the same: it clips what is inside to that box, so it can
// neither take less of one nor honestly ask for more. Passing the
// inner size up instead asks to be placed at a length it does not
// draw, and the framework would place the drawing it clipped away.
Size::LEFTOVER
}
}