Record the tenth sweep, over the deferred request system
This commit is contained in:
1 parent
e6a035d06e
commit
992a4a2e97
2 files changed
+114
-8
No files matched your search
@@ -6,6 +6,99 @@ nothing here is rediscovered. Each entry says who found it and when.
|
||||
it (settled design, the measurement method) belongs in `docs/LAYOUT.md`, and
|
||||
the current plan is in `docs/HANDOFF.md`.
|
||||
|
||||
## Tenth sweep: the deferred request system (2026-09-20)
|
||||
|
||||
Over the part of #19 no earlier round reviewed -- `76aaf06` and `de1eb7e`
|
||||
(the bound rules and the rule/widget split), `8780b40` (deferred comparisons)
|
||||
and `0e838e9` (the invalidation fix) -- 2,243 inserted lines over 32 files,
|
||||
with `core/src/widget/request.rs`, `MaxSize` and the deferred cases new. Ten
|
||||
findings, all in `4cb6f68`.
|
||||
|
||||
- **A bound's held length was looked up a second time, through a value that
|
||||
could not say which end.** `Bound::outside` returned `Option<Outside>` and
|
||||
the caller asked `Bound::at(outside)` for the length, which `expect`s an end
|
||||
the enum says nothing about -- `at(Shorter)` on a bound with no floor
|
||||
panics, and only the pairing of the two calls kept it from happening.
|
||||
`outside` already had the length in hand (`held`), so it now returns it;
|
||||
`Outside` and `Bound::at` are deleted, and the state that could panic
|
||||
cannot be written.
|
||||
- **A pixel bound pinned the rel base it was not read against.**
|
||||
`Painter::measured_request` recorded a rel-base dependency for any bound at
|
||||
all, so a measured share under `Min(px(80))` was invalidated by a change to
|
||||
a base its answer does not depend on. This is the class `0e838e9` fixed one
|
||||
instance of; `Placing::ask` already asked the narrower question inline, so
|
||||
the question is now `Bound::has_fraction` and all three callers ask it.
|
||||
- **One question about a pair, written out three times.** `[bound.min,
|
||||
bound.max].into_iter().flatten().any(|len| len.rel != Rel::ZERO)` appeared
|
||||
in `SizeRule::has_fraction` and again in `Placing::ask`, over a pair the
|
||||
framework names. It is `Bound::has_fraction` once.
|
||||
- **Three buffers reused for their capacity, on an invariant nothing
|
||||
stated.** `draw_at` now hands the painter the old draw's `textures`,
|
||||
`primitives` and `request_deps`, which is only sound because every path to
|
||||
it goes through `remove`, which drains them. A drawing over a buffer that
|
||||
still held primitives would record them twice and free them once. A
|
||||
`debug_assert` says so where they are taken.
|
||||
- **Two names and two spellings for one switch in the rigs.** The walk that
|
||||
drops a generated tree's bounds was written out in `layout_dump.rs` and
|
||||
`layout_diagnostics.rs`, under `IRIS_DUMP_UNBOUNDED` read with
|
||||
`var_os().is_some()` in one and `IRIS_UNBOUNDED` read with the file's own
|
||||
`env` helper in the other. It is `Plan::drop_bounds` and `IRIS_UNBOUNDED`
|
||||
in both, and the dump's module comment says so.
|
||||
- **`Span` wrote its gaps twice and read its allocation three ways.** The gap
|
||||
total is `Span::gaps`. In the placement loop `len`, `shares` and "not drawn
|
||||
at all" were three separate matches on whether the row was allocated, two
|
||||
of them deciding one child's length: one match now gives all three, so the
|
||||
allocated and plain rules are read side by side.
|
||||
- **`Stack` spelled "the child that sizes it" a second way** in
|
||||
`size_request`, with two arms answering `LEFTOVER`, where `draw` resolves
|
||||
the same thing once.
|
||||
- **`Pad` spelled its own padding a second way.** `Padding::along(axis)` is
|
||||
the sum of the two sides, which `draw` adds back and `size_request` insets
|
||||
by.
|
||||
- **Comments that described something else.** `with_requests` said nested
|
||||
painters keep discovery from overwriting its buffers, where the hazard is a
|
||||
child *drawn* mid-row; `Painter::allocate`'s doc described the window it
|
||||
holds for rather than what it does; `minimum_request` had none;
|
||||
`RequestArena::allocate` said "one scope of nonnegative shares", which is
|
||||
not this codebase's vocabulary; and `redraw_updates` was left mid-rewrap,
|
||||
with "the set" naming a `BTreeSet` that is now a `BinaryHeap`.
|
||||
- **A live explanation deleted with the path it was not about.** The comment
|
||||
saying a span carries its children's leftover weight whole rather than
|
||||
collapsing it per level -- the rule the handoff still lists as wanting
|
||||
confirmation -- was replaced by one about discovery. Both paths run; both
|
||||
are now described.
|
||||
|
||||
Two findings of the `as i32` kind were **looked at and left**. The allocator
|
||||
narrows i128 prefix sums and i64 segment totals to `Px` with `as i32` rather
|
||||
than `fixed::narrow`, which clamps; but `Fixed::add`, `sub` and `mul` all
|
||||
wrap deliberately (`MAX` is documented as "compared against, never added
|
||||
to"), so wrapping is what the ordinary path does with the same overflow, and
|
||||
`narrow` is for ranges. The epoch check in `RequestArena::segment` stays a
|
||||
release `assert`: a retained `RequestedLen` would otherwise read a node
|
||||
belonging to another widget and answer silently, which is worse than the
|
||||
compare it costs. The negative-weight check beside it is a caller bug like
|
||||
`div_int`'s and is now a `debug_assert`.
|
||||
|
||||
Two things the sweep did not change and somebody should decide:
|
||||
|
||||
- **The generator's leftover density halved** when `76aaf06` grew bounds:
|
||||
`Sow::rule` draws `LEFTOVER` 1 time in 8 where `Sow::len` drew it 1 in 4,
|
||||
and `Free` 2 in 8 where it was 1 in 2. The seed scans are the main defence
|
||||
for share logic, so the corpus now exercises it half as often. Restoring it
|
||||
costs a new dump baseline and three fresh scans.
|
||||
- **`MaxSize` holds `x` and `y` with a hand-written axis match**, where the
|
||||
framework names every other pair (`Bounds`, `Declared`, `Size`) and indexes
|
||||
it. Left because the fields are the constructor surface `max_width` and
|
||||
`max_height` build, and `impl_axis_index!` on a widget reads oddly; it is
|
||||
three call sites inside one file.
|
||||
|
||||
Verified at `4cb6f68`: format, workspace clippy under `-D warnings` with and
|
||||
without `layout-diagnostics`, 197 ordinary and 201 diagnostic workspace
|
||||
tests, the cold dump byte-identical to `0e838e9` across all 34,986 boxes, and
|
||||
all three seed scans (400 at depth 5 in 69.02s, 1,000 at depth 6 in 174.87s,
|
||||
2,000 at depth 4 in 330.39s). The scans were run because the rel-base fix
|
||||
changes what is invalidated, which is exactly what warm-against-cold checks.
|
||||
|
||||
## Performance sweep of #19 (2026-09-20)
|
||||
|
||||
`0e838e9`, by Codex.
|
||||
|
||||
Reference in new issue
Block a user