Record what the last of the fixed-point imprecision is
Traced rather than guessed: the same box reached two ways, each rounding where the other does not. Two of the three are fixed, the third is priced -- it costs the retained resize path, at a thousandth of a pixel. `OrthoSize` is deleted rather than paused; the decision it was waiting on was that a span asks whether a rule already answers for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ddf746d8a4
commit
617331f913
1 file changed
+35
-19
+35
-19
@@ -8,7 +8,7 @@ log.
|
|||||||
|
|
||||||
Canonical Iris `main` is **`ca2b4b2`** (#17, the headless rig). **#18
|
Canonical Iris `main` is **`ca2b4b2`** (#17, the headless rig). **#18
|
||||||
`split/18-position-chain`** is open in `/home/bob/repos/iris-pr18`; its local
|
`split/18-position-chain`** is open in `/home/bob/repos/iris-pr18`; its local
|
||||||
head is **`cb955f1`**, fifty-five commits. Built-in alignment is complete there;
|
head is **`bdab558`**, fifty-seven commits. Built-in alignment is complete there;
|
||||||
see "Built-in alignment" below for the retained-layout details. No PR reviews
|
see "Built-in alignment" below for the retained-layout details. No PR reviews
|
||||||
were present when checked on 2026-09-15.
|
were present when checked on 2026-09-15.
|
||||||
|
|
||||||
@@ -72,13 +72,14 @@ rewrite:
|
|||||||
`core/src/ui/holds.rs`, the retained tests, and the generated cold-layout oracle
|
`core/src/ui/holds.rs`, the retained tests, and the generated cold-layout oracle
|
||||||
pin those rules. Seeds 10 and 86 are now in the ordinary generated set.
|
pin those rules. Seeds 10 and 86 are now in the ordinary generated set.
|
||||||
|
|
||||||
## Verification at `cb955f1`
|
## Verification at `bdab558`
|
||||||
|
|
||||||
- `cargo fmt --all --check`
|
- `cargo fmt --all --check`
|
||||||
- `cargo build --workspace --all-features`
|
- `cargo build --workspace --all-features`
|
||||||
- `cargo clippy --workspace --all-targets --all-features -- -D warnings`
|
- `cargo clippy --workspace --all-targets --all-features -- -D warnings`
|
||||||
- `cargo test --workspace --all-features`: 102 passed, 10 ignored
|
- `cargo test --workspace --all-features`: 103 passed, 10 ignored
|
||||||
- The release generated cold-layout oracle passed 100 seeds in 75 s.
|
- The release generated cold-layout oracle passed 100 seeds in 9.4 s, and a
|
||||||
|
shrinker case at 300 seeds in 3.5 s: both run a thread per core but one.
|
||||||
- The release shrinker passed **all five** cases -- `resize`, `repaint`,
|
- The release shrinker passed **all five** cases -- `resize`, `repaint`,
|
||||||
`resize-repaint`, `reorder`, `size-change` -- at 300 seeds of depth 5:
|
`resize-repaint`, `reorder`, `size-change` -- at 300 seeds of depth 5:
|
||||||
26,001 widgets per case, largest tree 331. It passed 1000 seeds of depth 6
|
26,001 widgets per case, largest tree 331. It passed 1000 seeds of depth 6
|
||||||
@@ -137,6 +138,13 @@ tighter figures.
|
|||||||
|
|
||||||
## Retained-layout invariants
|
## Retained-layout invariants
|
||||||
|
|
||||||
|
- A span is as long across itself as its longest child, unless a rule beside
|
||||||
|
it says how long it is -- and then it does not read its children there at
|
||||||
|
all, since the answer is not wanted and reading one is what makes its size
|
||||||
|
depend on it. `OrthoSize` was that second case written twice and is gone
|
||||||
|
(`9d8415d`); `Painter::ruled` is how a container asks which it is in, and
|
||||||
|
the only thing a widget may learn about a rule over it.
|
||||||
|
|
||||||
- A region node holds a whole `UiRegion` in its parent node's coordinates.
|
- A region node holds a whole `UiRegion` in its parent node's coordinates.
|
||||||
`UiRegion::FULL` is the identity. Widgets opt in with `.region_node()` or
|
`UiRegion::FULL` is the identity. Widgets opt in with `.region_node()` or
|
||||||
`Widgets::set_region_node`; ordinary widgets share the nearest ancestor
|
`Widgets::set_region_node`; ordinary widgets share the nearest ancestor
|
||||||
@@ -315,12 +323,24 @@ pixels and `Holds`. Decided with Bryan on 2026-09-15.
|
|||||||
rounding, so it scales with the step: at `1/64` that was 0.016 px, enough
|
rounding, so it scales with the step: at `1/64` that was 0.016 px, enough
|
||||||
to move a box, and at `1/1024` it is a thousandth of a pixel. Range is
|
to move a box, and at `1/1024` it is a thousandth of a pixel. Range is
|
||||||
+/-2.1M px and conversion to `f32` is exact to 16,384 px.
|
+/-2.1M px and conversion to `f32` is exact to 16,384 px.
|
||||||
- **What the fuzzers ask for is a step per operation.** The shrinker's five
|
- **What the fuzzers ask for is a step per level of nesting**, which is two
|
||||||
cases agree within one (`resize` exactly), the oracle's two-operation cases
|
for these trees. Traced on 2026-09-16 to the same box reached two ways,
|
||||||
within two. Closing that needs one way of asking how long a box is: today a
|
each rounding where the other does not -- not accumulation, and not one
|
||||||
chain composed down through `within` and a length measured against the
|
place. Two of them are fixed in `bdab558`:
|
||||||
window are two, and they round separately. That is the next real step in
|
- `Scroll` wrote a box it had been given back out as its own length in
|
||||||
precision and it is bigger than any of these four commits.
|
pixels. Centring a part in `rel 1` lands a step from centring it in
|
||||||
|
`px 900`, because `a(x - y)` and `ax - ay` do not round alike. Content
|
||||||
|
that fills the viewport unscrolled is handed back as it came, and the
|
||||||
|
`repaint` and `resize-repaint` cases became exact.
|
||||||
|
- `Span` placed each child a step from where the last ended, carrying every
|
||||||
|
share's rounding along the row. A position is now the fixed parts before
|
||||||
|
it, exact, plus one rounded share. Two hundred equal shares of a 1000 px
|
||||||
|
row ended at 999.999 and now end at 1000.
|
||||||
|
What is left is a box centred in a fraction of its parent against the same
|
||||||
|
box centred in its own pixels, one step per level between them. Closing it
|
||||||
|
means alignment resolved in pixels everywhere -- which costs the retained
|
||||||
|
resize path, since it is the fractional form that re-centres a subtree
|
||||||
|
without redrawing it. Not worth it at a thousandth of a pixel.
|
||||||
- `Holds::through` inverts `px + rel * box`, which rounds, so the answer is
|
- `Holds::through` inverts `px + rel * box`, which rounds, so the answer is
|
||||||
an interval even for a single length. It maps the half step either side,
|
an interval even for a single length. It maps the half step either side,
|
||||||
plus one more for the two ways above; inverting the length alone gives a
|
plus one more for the two ways above; inverting the length alone gives a
|
||||||
@@ -376,6 +396,11 @@ targets went from 14.3 s to 7.7 s and `target/` from 45 GB to 13 GB. Pick a
|
|||||||
module out with `cargo test --test suite layout::`. The fuzzers and the
|
module out with `cargo test --test suite layout::`. The fuzzers and the
|
||||||
`*_cost` measurements are still their own targets.
|
`*_cost` measurements are still their own targets.
|
||||||
|
|
||||||
|
The fuzzers take a thread per core but one (`9d8415d`), since a seed grows,
|
||||||
|
lays out and drops its tree alone: the oracle's hundred seeds went from 68 s
|
||||||
|
to 9.4 s and a shrinker case at 300 seeds from 18 s to 3.5 s. A failing seed
|
||||||
|
still shrinks and panics on its own thread.
|
||||||
|
|
||||||
Run the long generated oracle only after ordinary tests pass:
|
Run the long generated oracle only after ordinary tests pass:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -433,15 +458,6 @@ the same `Holds` contract and box chain.
|
|||||||
|
|
||||||
Queued from this work, in order:
|
Queued from this work, in order:
|
||||||
|
|
||||||
- Delete `OrthoSize`. It is redundant now that size is built in: a span should
|
|
||||||
read its own rule on the orthogonal axis and, where that is fixed, skip
|
|
||||||
reading its children's orthogonal sizes entirely, which is what `Full` does
|
|
||||||
today. That also removes the span's own instance of the compounding above.
|
|
||||||
**Paused 2026-09-16 for a decision**: a widget deliberately cannot see its
|
|
||||||
own rule ("the widget under a rule never learns of it"), so either that
|
|
||||||
changes or the span reports something else on the orthogonal axis -- which
|
|
||||||
is what every span reports, and a column sized to its widest item is what
|
|
||||||
`Children` is for.
|
|
||||||
- `Scroll` should take a direction rather than one axis: vertical, horizontal,
|
- `Scroll` should take a direction rather than one axis: vertical, horizontal,
|
||||||
or both. Reporting `LEFTOVER` on both axes is already the right shape for it.
|
or both. Reporting `LEFTOVER` on both axes is already the right shape for it.
|
||||||
- Restore `max_width`/`max_height` as `SizeRule::{Min, Max, Clamp}`. `8220a78`
|
- Restore `max_width`/`max_height` as `SizeRule::{Min, Max, Clamp}`. `8220a78`
|
||||||
|
|||||||
Reference in new issue
Block a user