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

Đang mở
#2,076 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
58/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
cpp
Lĩnh vực
frontend

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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

Ngôn ngữ chính
C++
Star
18.9k
Fork
1.6k
Merge trung bình
17 giờ 9 phút
Pull request đã merge (30 ngày)
13

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của react/yoga

Tất cả issue của react/yoga

Issue tương tự

Thêm issue về C++

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.