Say the environment once, and stop a hint read going uncounted

The eleventh sweep, over the built-in bounds work in 2ac0843.

`Painter::size_hint` refused to answer for a bounded widget by returning
above the diagnostics, so that read was neither a hint hit nor a miss and
`hint_read` recorded nothing. It is a miss now, with the reason on it.

The two `for axis in Axis::BOTH` loops that `draw_widget` grew, both
writing `own_holds`, are one loop, and the comment about combining the
ask's holds no longer sits between a comment and the code it describes.

`Declared::from_axes` lost its only caller with `Widgets::declared_lens`;
`Bounds::from_axes` and `SizeRule::declared` never had one.

The scenario shrinker printed a rule with derived `Debug`, which is 130
characters an axis in a line that carries every ancestor, in the one
function whose job is output a tree can be rebuilt from. It prints its
parts again.

`bounds_cost` invented three environment-reading spellings where four
copies of one `env` helper already existed; there is now one, in
`tests/rig`, and the four copies are gone. It also verified 128 regions
inside its measured loop, which the other rigs deliberately do before
theirs; that measured 0.65% of the total, and none of it is layout.

The 250-window row with a 300 cap was built by two tests, and the one
that still explained itself tested less; they are one. The half of
`a_cap_attribute_narrows_the_widgets_box` that the wrapper's removal left
without its deciding assertion is the allocator's path instead, which
nothing at the root covered.

Format, workspace clippy under -D warnings with and without
layout-diagnostics, 206 ordinary and 210 diagnostic tests, 400 depth-5
trees warm against cold in 64.19s, and the cold dump byte-identical to
2ac0843 across all 34,986 boxes.
This commit is contained in:
iris-ai committed 2026-09-20 20:13:57 -04:00
1 parent 2ac0843cb2
commit ea1f836bf9
16 files changed
+178 -146

No files matched your search

+20 -11
View File
@@ -30,13 +30,6 @@ pub fn over_seeds(seeds: Vec<u64>, run: impl Fn(u64) + Sync) {
});
}
pub fn env<T: std::str::FromStr>(name: &str, fallback: T) -> T {
std::env::var(name)
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(fallback)
}
/// The window a tree is grown in, and the one a resize takes it to.
const OUTER: (f32, f32) = (1920.0, 1200.0);
const INNER: (f32, f32) = (640.0, 900.0);
@@ -356,8 +349,24 @@ fn change(case: Case, warm: &mut Harness, tree: &mut Tree, plan: &Plan, rng: &mu
/// out by hand. A failure is a lead; the fast test that replaces it has to be
/// buildable from what the failure printed.
fn describe(id: WidgetId, h: &Harness) -> String {
let rules = h.rsc.widgets().size_rules(id).clone();
let rule = |r: SizeRule| format!("{r:?}");
let rules = h.rsc.widgets().size_rules(id);
// The tree a failure names is written out again from what it printed, so
// every part of a rule prints: the preferred length and the bounds are
// independent, and a bound lumped into "no rule" could not be rebuilt.
let rule = |r: &SizeRule| {
let mut out = match &r.request {
None => String::new(),
Some(SizeRequest::Linear(len)) => format!("{len}"),
Some(request) => format!("{request:?}"),
};
if let Some(min) = r.bound.min {
out += &format!(">{}", LayoutLen::from(min));
}
if let Some(max) = r.bound.max {
out += &format!("<{}", LayoutLen::from(max));
}
if out.is_empty() { "-".into() } else { out }
};
let align = h.rsc.widgets().alignment(id);
let side = |a: AxisAlign| {
if a == AxisAlign::NEG {
@@ -373,8 +382,8 @@ fn describe(id: WidgetId, h: &Harness) -> String {
// A rule and an alignment are properties of whatever carries them, so
// they print with that widget rather than as widgets of their own.
let mut out = describe_widget(id, h);
if rules != SizeRules::default() {
out += &format!("[x:{},y:{}]", rule(rules.x), rule(rules.y));
if *rules != SizeRules::default() {
out += &format!("[x:{},y:{}]", rule(&rules.x), rule(&rules.y));
}
if align != RegionAlign::default() {
out += &format!("@{},{}", side(align.x), side(align.y));