Skip to content

gpui: don't shift a scroll layer's own scene index when its list view is drawn again - #51

Merged
sunli829 merged 2 commits into
mainfrom
fix-list-scroll-shift-overflow
Oct 9, 2026
Merged

sunli829 merged 2 commits into
mainfrom
fix-list-scroll-shift-overflow

Conversation

@sunli829

@sunli829 sunli829 commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

What

In a debug build, gpui_perf's showcase panicked when the List page's list was scrolled:

thread 'main' panicked at crates/gpui/src/fast/retained.rs:363:26:
attempt to subtract with overflow

The call path is reuse_retained_paint → fast/layers/reuse.rs follow_paint → its shift closure, which LayerRows::follow_paint also uses. A scroll layer's paint ranges count their scene index from the layer's own scene, not the window's. shift ran the scene index through PaintIndex::shifted anyway and put it back afterwards. When the view holding the list is drawn after something of its parent's, such as the showcase's sidebar, from.start.scene_index is greater than the layer's own index, so the subtraction underflowed. Release builds wrap the value and then overwrite it, so nothing showed there.

follow_paint now shifts by copies of from.start and to whose scene index is 0, which leaves the layer's own scene index as it is. Every other index shifts exactly as before. No upstream file changes.

The other shift sites (finish_frame, splice.rs, reuse_retained_prepaint/reuse_retained_paint, follow_prepaint) only shift ranges that count from the window's scene, so they cannot hit this.

Correctness

  • New test a_list_view_drawn_again_after_its_parents_backdrop_keeps_its_layer: a list view drawn after its parent's backdrop, with the parent notified every few frames while it scrolls. Before the fix it panics at the same line through the same path. After the fix it draws as it does with layers off, and the list stays composited. The existing list tests all use the list's view as the root, where from.start.scene_index is 0, which is why none of them caught this.
  • cargo test -p gpui --features test-support --lib: 647 passed.
  • gpui_perf --headless --verify (debug): all 55 checks identical.
  • Debug gpui_perf --demo: panicked within 90 s before the fix. After it, it ran 180 s, and 120 s after the simplification, with no panic.
  • script/check-upstream: 0 violations.

🤖 Generated with Claude Code

… is drawn again

follow_paint shifted the layer's paint ranges, scene index included, and only
then put the scene index back. A layer's scene index counts from its own
scene, so when the view holding the list was drawn after something of its
parent's (a sidebar), it lay before the window's and the subtraction
underflowed: gpui_perf's showcase panicked scrolling the list page in a debug
build.
trancong12102 pushed a commit to aislopware/gpui-fast that referenced this pull request Oct 9, 2026
…r its parent's backdrop

longbridge#51 (a6dc1cb, a985280) stops `follow_paint` shifting a
scroll layer's own scene index, which underflowed when the list's view is
drawn after something of its parent's. The fork fixed the same shift in
5b02224 (PaintIndex::shifted_outside_scene, which never touches the scene
index), so reuse.rs keeps ours and only the PR's regression test,
a_list_view_drawn_again_after_its_parents_backdrop_keeps_its_layer, is
taken. Reconcile with upstream's version of the fix when longbridge#51 lands.

(cherry picked from commit a6dc1cb, test only)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sunli829
sunli829 merged commit 6cc2089 into main Oct 9, 2026
4 checks passed
@sunli829
sunli829 deleted the fix-list-scroll-shift-overflow branch October 9, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant