Carry a span's rest weight up instead of collapsing it to one share

A span reporting `Len::default()` whenever a child had a share threw away
how many shares it was holding, so each level of nesting re-divided a
share rather than dividing the same space. One span of a rect beside a
span of three gave 1/2 and 1/6 each, where the same four rects directly
in one span get a quarter.

A span that sizes from its children does not resolve `rest`, it passes
the weight up; resolution belongs at the nearest ancestor with a length,
and since the output became a box there is always one. The placement loop
already divides by `len.rest / total.rest`, so it consumes carried
weights unchanged -- only what the span reported was wrong.

The uneven nesting is the case that fails without this; the even one
passes either way and is here as the statement of intent.

Decided by the owner, 2026-09-14.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Opus 5 committed 2026-09-14 23:29:25 -04:00
1 parent ef815dadfd
commit b165164e59
2 files changed
+51 -4

No files matched your search

+8 -4
View File
@@ -60,10 +60,14 @@ impl Widget for Span {
start.px += self.gap;
}
let along = match total.rest == 0.0 && total.rel == 0.0 {
true => total,
false => Len::default(),
};
// Carried whole rather than collapsed to one share: a span that sizes
// from its children does not resolve `rest`, it passes the weight up,
// so nesting spans divides the same space rather than re-dividing a
// share of it. Four `rest(1)` children under two spans under one span
// get a quarter each, which collapsing to `rest(1)` per level does
// not give. Resolution happens at the nearest ancestor with a length,
// and the root always has one.
let along = total;
Size::from_axis(axis, along, ortho)
}