# taffy#1000 — `distribute_space_up_to_limits` olvida lo que ya repartió # # CAUSA RAÍZ, encontrada instrumentando taffy 0.12.2 (2026-07-28). La función # reparte espacio libre entre pistas «hasta su límite», en varias iteraciones, # acumulando en `track.item_incurred_increase`. Las DOS cuentas que deciden # cuánto le cabe a cada pista miran `track_affected_property(track)` PELADO, sin # sumarle lo ya acumulado: # # · el margen restante (`min_increase_limit`), que queda inflado en todo lo # que la pista ya creció en iteraciones anteriores; y # · el guarda que aplica el incremento, que por lo mismo deja pasar pistas ya # CONGELADAS por el filtro de elegibilidad de arriba. # # Traza del caso real (infobox «Rust Foundation» de Wikipedia, contenedor 352, # bases [87, 140], límites [147, 197], libre 125): # iter 1: cabe min(60, 57) = 57 → ambas +57 → [144, 197], sobran 11. # iter 2: elegible sólo la 1ª (la 2ª topó), pero el margen se calcula # 147 − 87 = 60 (debería ser 3) y el guarda compara 87 + 11 ≤ 147 # (debería ser 144 + 11) → **las DOS** se llevan +11. # salida [155, 208] = 363 en un contenedor de 352, con límites que sumaban # 344 y entraban de sobra. # # Explica las dos caras que veníamos midiendo (ver # `tests/grid_maximise_overshoot.rs`): la pista que supera su propio # max-content, y el reparto que empeora al SACAR filas. # # VERIFICADO contra el repo de taffy en el tag v0.12.2: la suite entera pasa — # 4421 tests generados (los de web-platform), 105 unitarios, 43 hand-written, # 5 de doc; cero fallas. Y arregla los dos casos: el original de taffy#1000 # (contenedor 928, max-contents [400, 674]) pasa de [528, 528] = 1056 a # [400, 528] = 928 EXACTO, y el infobox de 2 filas de 363 a 344. # # Sigue VIVO en master (0972b84, posterior a 0.12.2). # # Para aplicarlo hace falta un taffy vendorizado + `[patch.crates-io]`; mientras # eso no se decida, esto es la evidencia y la receta, no un parche activo. # diff --git a/src/compute/grid/track_sizing.rs b/src/compute/grid/track_sizing.rs index 10e3ea2..9d8ad07 100644 --- a/src/compute/grid/track_sizing.rs +++ b/src/compute/grid/track_sizing.rs @@ -1399,7 +1399,10 @@ fn distribute_space_up_to_limits( .iter() .filter(|track| track_affected_property(track) + track.item_incurred_increase < track_limit(track)) .filter(|track| track_is_affected(track)) - .map(|track| (track_limit(track) - track_affected_property(track)) / track_distribution_proportion(track)) + .map(|track| { + (track_limit(track) - track_affected_property(track) - track.item_incurred_increase) + / track_distribution_proportion(track) + }) .min_by(|a, b| a.total_cmp(b)) .unwrap(); // We will never pass an empty track list to this function let iteration_item_incurred_increase = @@ -1407,7 +1410,10 @@ fn distribute_space_up_to_limits( for track in tracks.iter_mut().filter(|track| track_is_affected(track)) { let increase = iteration_item_incurred_increase * track_distribution_proportion(track); - if increase > 0.0 && track_affected_property(track) + increase <= track_limit(track) + THRESHOLD { + if increase > 0.0 + && track_affected_property(track) + track.item_incurred_increase + increase + <= track_limit(track) + THRESHOLD + { track.item_incurred_increase += increase; space_to_distribute -= increase; }