Under FMA contraction, an item that shrinks exactly to its min-width is laid out at its flex basis

Abierto
#2,076 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
58/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
cpp
Área
frontend

Línea de trabajo

Read yoga/algorithm/CalculateLayout.cpp, especially distributeFreeSpaceFirstPass and distributeFreeSpaceSecondPass, using the reproducer linked in the issue to follow the min-width boundary case. Compare the layout with floating-point contraction enabled and disabled; done means the item lays out at width 10 in both cases. Check the related issue #2038 for context on residual free space.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Report

Issues and Steps to Reproduce

A row 20 wide holds an item with flexBasis: 90, flexShrink: 1 and minWidth: 10, and a sibling 10 wide that does not shrink, so the item absorbs the line's 80 of overflow and lands exactly on its minWidth. Built with floating-point contraction, which clang applies by default (-ffp-contract=on) wherever the target has FMA, Yoga lays the item out at its flex basis:

YGNodeRef row = YGNodeNew();
YGNodeStyleSetFlexDirection(row, YGFlexDirectionRow);
YGNodeStyleSetWidth(row, 20);
YGNodeStyleSetHeight(row, 10);

YGNodeRef item = YGNodeNew();
YGNodeStyleSetFlexBasis(item, 90);
YGNodeStyleSetFlexShrink(item, 1);
YGNodeStyleSetMinWidth(item, 10);
YGNodeInsertChild(row, item, 0);

YGNodeRef sibling = YGNodeNew();
YGNodeStyleSetWidth(sibling, 10);
YGNodeInsertChild(row, sibling, 1);

YGNodeCalculateLayout(row, YGUndefined, YGUndefined, YGDirectionLTR);

bash repro.sh from the gist below clones main, builds Yoga with this program twice, with contraction and with -ffp-contract=off, and runs both. In ubuntu:24.04 on x86-64, where contraction needs -mfma:

react/yoga 41118bd, Ubuntu clang version 18.1.3 (1ubuntu1), Linux x86_64
contraction on (-mfma): 90 + (-80 / -90) * -90 is 9.99999905 fused, 10 rounded at each step; item width 90
contraction off (-ffp-contract=off): 90 + (-80 / -90) * -90 is 9.99999905 fused, 10 rounded at each step; item width 10
summary: react/yoga 41118bd lays the item out 90 wide, its flex basis, with contraction, and 10 wide, its min-width, without

and on arm64, with no flag:

react/yoga 41118bd, Ubuntu clang version 18.1.3 (1ubuntu1), Linux aarch64
contraction on: 90 + (-80 / -90) * -90 is 9.99999905 fused, 10 rounded at each step; item width 90
contraction off (-ffp-contract=off): 90 + (-80 / -90) * -90 is 9.99999905 fused, 10 rounded at each step; item width 10
summary: react/yoga 41118bd lays the item out 90 wide, its flex basis, with contraction, and 10 wide, its min-width, without

Expected Behavior

item width 10 with contraction, as without it: the item shrinks onto its minWidth.

Actual Behavior

item width 90: with contraction the item keeps its flex basis and overflows the 20-wide row.

In yoga/algorithm/CalculateLayout.cpp at 41118bd:

  • distributeFreeSpaceFirstPass computes baseMainSize = childFlexBasis + remainingFreeSpace / totalFlexShrinkScaledFactors * flexShrinkScaledFactor, which contraction turns into one fused multiply-add: 9.99999905 here, against 10 when the product is rounded first.
  • baseMainSize != boundMainSize compares exactly, so against the bound of 10 the first pass freezes the item: deltaFreeSpace takes 10 - 90, all -80 of the free space, which leaves remainingFreeSpace at exactly 0.
  • distributeFreeSpaceSecondPass shrinks or grows only while remainingFreeSpace is below or above 0, so the item keeps updatedMainSize = childFlexBasis and is never bounded to its minimum, though the first pass expects a frozen item's "min/max constraints should also trigger in the second pass".

#2038 is another FMA residual in these two passes.

Link to Code

https://gist.github.com/YevheniiKotyrlo/45b864d98eae145b9ef1879d97783657

Lenguaje dominante
C++
Estrellas
18.9k
Forks
1.6k
Merge medio
17 h 9 min
PR fusionados (30 d)
13

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de react/yoga

Todos los issues de react/yoga

Issues similares

Más issues de C++

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.