Files
f64d69fec6 Ensure that multibuffer anchor ordering is stable over time and consistent with resolution (#62636)
Digging into ZED-7G6 ("buffer snapshot not found for excerpt boundary",
171 events) revealed some bugs in the implementation of multibuffer
anchors that landed in #52364. Specifically:

- In the presence of multibuffer excerpt changes, it was possible for
two anchors to satisfy `a1 < a2` but `a1.to_offset() > a2.to_offset()`.
This happened in particular when a `PathKey` was reused for two
different buffers at different times, and could cause crashes in code
that sorted anchors by `cmp` and expected the resulting offsets to be
sorted.
- Changes of diff base and normal buffer edits could cause two anchors
to sort `a1 < a2` against one snapshot and `a2 < a1` against a later
snapshot. This could also cause crashes in downstream code that
(reasonably) expected anchors to have a stable ordering.

This PR adds a property test asserting that multibuffer anchor ordering
is stable over time and consistent at every moment in time with the
ordering obtained from resolving the anchors, and fixes the bugs in
anchor resolution and comparison that are revealed by that test. It also
includes tests downstream for specific cases that previously crashed.

Closes ZED-7G6
 
Release Notes:

- Fixed a crash that could occur when inlay hints were present while a
multibuffer replaced the contents of a file, such as a diff view whose
base changed.
- Fixed crashes that could occur when a file's contents were replaced in
a multibuffer (such as a diff view refreshing) while highlights, inlay
hints, or other positions still referenced the old contents.

---------

Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-08-28 18:05:57 +00:00

66 lines
1.6 KiB
TOML

[package]
name = "multi_buffer"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/multi_buffer.rs"
doctest = false
[features]
test-support = [
"buffer_diff/test-support",
"gpui/test-support",
"language/test-support",
"text/test-support",
"util/test-support",
]
[dependencies]
anyhow.workspace = true
clock.workspace = true
collections.workspace = true
ctor.workspace = true
futures-lite.workspace = true
buffer_diff.workspace = true
gpui.workspace = true
itertools.workspace = true
language.workspace = true
log.workspace = true
parking_lot.workspace = true
rand.workspace = true
rope.workspace = true
settings.workspace = true
serde.workspace = true
smallvec.workspace = true
sum_tree.workspace = true
text.workspace = true
theme.workspace = true
tree-sitter = { workspace = true, features = ["wasm"] }
ztracing.workspace = true
tracing.workspace = true
util.workspace = true
unicode-segmentation.workspace = true
[dev-dependencies]
buffer_diff = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, features = ["test-support"] }
indoc.workspace = true
language = { workspace = true, features = ["test-support"] }
pretty_assertions.workspace = true
proptest.workspace = true
proptest-derive.workspace = true
rand.workspace = true
settings = { workspace = true, features = ["test-support"] }
text = { workspace = true, features = ["test-support"] }
util = { workspace = true, features = ["test-support"] }
zlog.workspace = true
[package.metadata.cargo-shear]
ignored = ["tracing"]