Keep the step 3/4 experiment as evidence

The worker's uncommitted attempt at evaluating children in parent-decided
boxes, preserved as it stood when it stopped: separate answer-only pixel
reads, per-child drawing contracts, provisional Fill asks in Span, and an
assertion that a placed drawing hold for its answer box. The suite passes
and every generated case stops on that assertion at Text. Not the
protocol; wip/one-ask is.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Fable 5.1 committed 2026-09-18 18:21:24 -04:00
1 parent 4328eac756
commit aaba7dbfee
6 files changed
+180 -106

No files matched your search

+41 -17
View File
@@ -12,6 +12,7 @@ struct Counted {
draws: Rc<Cell<usize>>,
size: Size,
reads_box: bool,
reads_answer_box: bool,
}
impl Widget for Counted {
@@ -19,6 +20,8 @@ impl Widget for Counted {
self.draws.set(self.draws.get() + 1);
if self.reads_box {
painter.px_size();
} else if self.reads_answer_box {
painter.answer_px_size();
}
self.size
}
@@ -38,11 +41,18 @@ fn counted(h: &mut Harness, size: Size, reads_box: bool) -> (WeakWidget<Counted>
draws: draws.clone(),
size,
reads_box,
reads_answer_box: false,
}
.add(&mut h.rsc);
(id, Counts(draws))
}
fn answer_counted(h: &mut Harness, size: Size) -> (WeakWidget<Counted>, Counts) {
let (id, draws) = counted(h, size, false);
h.rsc[id].reads_answer_box = true;
(id, draws)
}
struct Layered {
children: [StrongWidget<Rect>; 2],
_revision: usize,
@@ -156,8 +166,8 @@ fn a_span_child_that_declares_its_length_is_drawn_once() {
h.set_root((hinted, asked).span(Dir::RIGHT));
assert_eq!(told_draws.get(), 1);
// Only the available length changes: positioning the final slot does
// not invalidate a numeric size read.
// Its final slot is a parent decision, so it is evaluated there after
// the provisional ask established its length.
assert_eq!(asked_draws.get(), 2);
}
@@ -240,7 +250,7 @@ fn a_parent_that_only_read_a_hint_relays_out_when_the_hint_changes() {
assert_corners!(h, inner, (0, 0), (400, 120));
}
/// Reads its box's size, which nothing but its own draw can put right.
/// Reads its box's size to compute its answer.
struct ReadsBox {
draws: Rc<Cell<usize>>,
}
@@ -248,26 +258,36 @@ struct ReadsBox {
impl Widget for ReadsBox {
fn draw(&mut self, painter: &mut Painter) -> Size {
self.draws.set(self.draws.get() + 1);
Size::from_px(painter.px_size().div_int(4))
Size::from_px(painter.answer_px_size().div_int(4))
}
}
/// Reads its box across one axis only, so its drawing holds for a taller
/// box on its own and only a wider one is worth a draw.
///
/// Both of these report a quarter of what they read, without saying that the
/// drawing holds there too, so each length they are asked at costs two draws:
/// one to answer, and one in the quarter-sized box that answer places them
/// in. The counts below are in those pairs.
/// Both report a quarter of what they read. Their empty drawings are
/// independent of that read, so a changed question costs one draw.
struct ReadsWidth {
draws: Rc<Cell<usize>>,
}
struct ReadsDrawingWidth {
draws: Rc<Cell<usize>>,
}
impl Widget for ReadsDrawingWidth {
fn draw(&mut self, painter: &mut Painter) -> Size {
self.draws.set(self.draws.get() + 1);
painter.px_len(Axis::X);
Size::LEFTOVER
}
}
impl Widget for ReadsWidth {
fn draw(&mut self, painter: &mut Painter) -> Size {
self.draws.set(self.draws.get() + 1);
Size::from_px(PxVec2::new(
painter.px_len(Axis::X).div_int(4),
painter.answer_px_len(Axis::X).div_int(4),
Px::from_int(20),
))
}
@@ -323,6 +343,7 @@ fn a_row_moves_what_follows_a_child_that_grew_rather_than_drawing_it() {
draws: ruled.clone(),
size: Size::LEFTOVER,
reads_box: false,
reads_answer_box: false,
};
let second = match declared {
true => second.width(rel(0.25)).add(&mut h.rsc),
@@ -384,7 +405,7 @@ fn a_resize_redraws_what_read_its_box() {
h.resize((800, 100));
h.frame();
assert_eq!(draws.get(), settled + 2);
assert_eq!(draws.get(), settled + 1);
}
#[test]
@@ -404,7 +425,7 @@ fn a_resize_only_redraws_read_axes() {
h.resize((800, 300));
h.frame();
assert_eq!(draws.get(), settled + 2, "width changes its answer");
assert_eq!(draws.get(), settled + 1, "width changes its answer");
}
/// A window is measured onto the grid like everything else, so a resize too
@@ -431,7 +452,7 @@ fn a_resize_within_one_step_is_not_a_resize() {
h.resize((400.0 + step, 200.0));
h.frame();
assert_eq!(draws.get(), settled + 2);
assert_eq!(draws.get(), settled + 1);
}
/// The same for a box that changes because a sibling did: what is compared
@@ -500,7 +521,7 @@ fn a_change_two_levels_under_its_reader_still_reaches_it() {
// Every wrapper up to the outer pad read the size below it, so the outer
// pad is what draws again -- and the span it hands the box to is the same
// size as before, which is what lets a draw reuse its way past the leaf.
let (leaf, _) = counted(&mut h, Size::px((100, 100).into()), true);
let (leaf, _) = counted(&mut h, Size::px((100, 100).into()), false);
let padded = leaf.pad(10).add(&mut h.rsc);
let below = rect(Color::RED).add(&mut h.rsc);
h.set_root((padded, below).span(Dir::DOWN).pad(12));
@@ -1066,7 +1087,7 @@ fn a_declared_size_change_stops_at_an_independent_parent() {
fn an_unmeasured_child_still_invalidates_its_parents_drawing_on_resize() {
let mut h = Harness::new((400, 200));
let draws = Rc::new(Cell::new(0));
let leaf = ReadsWidth {
let leaf = ReadsDrawingWidth {
draws: draws.clone(),
}
.add(&mut h.rsc);
@@ -1077,7 +1098,7 @@ fn an_unmeasured_child_still_invalidates_its_parents_drawing_on_resize() {
h.frame();
assert!(draws.get() > settled);
assert_corners!(h, leaf, (300, 90), (500, 110));
assert_corners!(h, leaf, (0, 0), (800, 200));
}
#[test]
@@ -1212,7 +1233,7 @@ fn moving_an_extent_child_preserves_the_slot_chosen_from_its_measurement() {
struct Measured;
impl Widget for Measured {
fn draw(&mut self, painter: &mut Painter) -> Size {
let width = painter.px_len(Axis::X);
let width = painter.answer_px_len(Axis::X);
painter.primitive(RectPrimitive::color(Color::BLUE));
Size::from((80, if width > Px::from_int(100) { 40 } else { 60 }))
}
@@ -1312,7 +1333,10 @@ fn extent_frames_keep_fractional_reports_and_numeric_dependencies_valid() {
} else {
Size::from((80, 27))
};
let (leaf, _) = counted(h, size, !fractional);
let (leaf, _) = match fractional {
true => counted(h, size, false),
false => answer_counted(h, size),
};
let child = Container {
child: leaf.add_strong(&mut h.rsc),
region,