sum_tree: Implement recursive `Sumtree::find`, use it over `Cursor::seek` if possible (#40700)

Lukas Wirth created

Reduces peak stack usage in these functions and should generally be a
bit performant.

Display map benchmark results
```
To tab point/to_tab_point/1024
                        time:   [531.40 ns 532.10 ns 532.97 ns]
                        change: [-2.1824% -2.0054% -1.8125%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high severe

To fold point/to_fold_point/1024
                        time:   [530.81 ns 531.30 ns 531.80 ns]
                        change: [-2.0295% -1.9054% -1.7716%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe
```

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Change summary

crates/editor/src/display_map/block_map.rs     |  60 +++++----
crates/editor/src/display_map/fold_map.rs      |  87 ++++++-------
crates/editor/src/display_map/inlay_map.rs     |  56 ++++----
crates/editor/src/display_map/wrap_map.rs      |  63 +++++----
crates/gpui/src/elements/list.rs               |  27 ++-
crates/multi_buffer/src/multi_buffer.rs        |   5 
crates/notifications/src/notification_store.rs |  14 +
crates/rope/src/rope.rs                        |  38 ++---
crates/sum_tree/src/cursor.rs                  |   4 
crates/sum_tree/src/sum_tree.rs                | 126 +++++++++++++++++++
crates/sum_tree/src/tree_map.rs                |   7 
crates/text/src/anchor.rs                      |  13 +
crates/text/src/text.rs                        |  38 +++--
13 files changed, 332 insertions(+), 206 deletions(-)

Detailed changes

crates/editor/src/display_map/block_map.rs 🔗

@@ -1521,10 +1521,11 @@ impl BlockSnapshot {
     }
 
     pub(super) fn line_len(&self, row: BlockRow) -> u32 {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
-        cursor.seek(&BlockRow(row.0), Bias::Right);
-        if let Some(transform) = cursor.item() {
-            let Dimensions(output_start, input_start, _) = cursor.start();
+        let (start, _, item) =
+            self.transforms
+                .find::<Dimensions<BlockRow, WrapRow>, _>((), &row, Bias::Right);
+        if let Some(transform) = item {
+            let Dimensions(output_start, input_start, _) = start;
             let overshoot = row.0 - output_start.0;
             if transform.block.is_some() {
                 0
@@ -1539,15 +1540,13 @@ impl BlockSnapshot {
     }
 
     pub(super) fn is_block_line(&self, row: BlockRow) -> bool {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
-        cursor.seek(&row, Bias::Right);
-        cursor.item().is_some_and(|t| t.block.is_some())
+        let (_, _, item) = self.transforms.find::<BlockRow, _>((), &row, Bias::Right);
+        item.is_some_and(|t| t.block.is_some())
     }
 
     pub(super) fn is_folded_buffer_header(&self, row: BlockRow) -> bool {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
-        cursor.seek(&row, Bias::Right);
-        let Some(transform) = cursor.item() else {
+        let (_, _, item) = self.transforms.find::<BlockRow, _>((), &row, Bias::Right);
+        let Some(transform) = item else {
             return false;
         };
         matches!(transform.block, Some(Block::FoldedBuffer { .. }))
@@ -1557,9 +1556,10 @@ impl BlockSnapshot {
         let wrap_point = self
             .wrap_snapshot
             .make_wrap_point(Point::new(row.0, 0), Bias::Left);
-        let mut cursor = self.transforms.cursor::<Dimensions<WrapRow, BlockRow>>(());
-        cursor.seek(&WrapRow(wrap_point.row()), Bias::Right);
-        cursor.item().is_some_and(|transform| {
+        let (_, _, item) =
+            self.transforms
+                .find::<WrapRow, _>((), &WrapRow(wrap_point.row()), Bias::Right);
+        item.is_some_and(|transform| {
             transform
                 .block
                 .as_ref()
@@ -1627,13 +1627,16 @@ impl BlockSnapshot {
     }
 
     pub fn to_block_point(&self, wrap_point: WrapPoint) -> BlockPoint {
-        let mut cursor = self.transforms.cursor::<Dimensions<WrapRow, BlockRow>>(());
-        cursor.seek(&WrapRow(wrap_point.row()), Bias::Right);
-        if let Some(transform) = cursor.item() {
+        let (start, _, item) = self.transforms.find::<Dimensions<WrapRow, BlockRow>, _>(
+            (),
+            &WrapRow(wrap_point.row()),
+            Bias::Right,
+        );
+        if let Some(transform) = item {
             if transform.block.is_some() {
-                BlockPoint::new(cursor.start().1.0, 0)
+                BlockPoint::new(start.1.0, 0)
             } else {
-                let Dimensions(input_start_row, output_start_row, _) = cursor.start();
+                let Dimensions(input_start_row, output_start_row, _) = start;
                 let input_start = Point::new(input_start_row.0, 0);
                 let output_start = Point::new(output_start_row.0, 0);
                 let input_overshoot = wrap_point.0 - input_start;
@@ -1645,26 +1648,29 @@ impl BlockSnapshot {
     }
 
     pub fn to_wrap_point(&self, block_point: BlockPoint, bias: Bias) -> WrapPoint {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
-        cursor.seek(&BlockRow(block_point.row), Bias::Right);
-        if let Some(transform) = cursor.item() {
+        let (start, end, item) = self.transforms.find::<Dimensions<BlockRow, WrapRow>, _>(
+            (),
+            &BlockRow(block_point.row),
+            Bias::Right,
+        );
+        if let Some(transform) = item {
             match transform.block.as_ref() {
                 Some(block) => {
                     if block.place_below() {
-                        let wrap_row = cursor.start().1.0 - 1;
+                        let wrap_row = start.1.0 - 1;
                         WrapPoint::new(wrap_row, self.wrap_snapshot.line_len(wrap_row))
                     } else if block.place_above() {
-                        WrapPoint::new(cursor.start().1.0, 0)
+                        WrapPoint::new(start.1.0, 0)
                     } else if bias == Bias::Left {
-                        WrapPoint::new(cursor.start().1.0, 0)
+                        WrapPoint::new(start.1.0, 0)
                     } else {
-                        let wrap_row = cursor.end().1.0 - 1;
+                        let wrap_row = end.1.0 - 1;
                         WrapPoint::new(wrap_row, self.wrap_snapshot.line_len(wrap_row))
                     }
                 }
                 None => {
-                    let overshoot = block_point.row - cursor.start().0.0;
-                    let wrap_row = cursor.start().1.0 + overshoot;
+                    let overshoot = block_point.row - start.0.0;
+                    let wrap_row = start.1.0 + overshoot;
                     WrapPoint::new(wrap_row, block_point.column)
                 }
             }

crates/editor/src/display_map/fold_map.rs 🔗

@@ -98,28 +98,26 @@ impl FoldPoint {
     }
 
     pub fn to_inlay_point(self, snapshot: &FoldSnapshot) -> InlayPoint {
-        let mut cursor = snapshot
+        let (start, _, _) = snapshot
             .transforms
-            .cursor::<Dimensions<FoldPoint, InlayPoint>>(());
-        cursor.seek(&self, Bias::Right);
-        let overshoot = self.0 - cursor.start().0.0;
-        InlayPoint(cursor.start().1.0 + overshoot)
+            .find::<Dimensions<FoldPoint, InlayPoint>, _>((), &self, Bias::Right);
+        let overshoot = self.0 - start.0.0;
+        InlayPoint(start.1.0 + overshoot)
     }
 
     pub fn to_offset(self, snapshot: &FoldSnapshot) -> FoldOffset {
-        let mut cursor = snapshot
+        let (start, _, item) = snapshot
             .transforms
-            .cursor::<Dimensions<FoldPoint, TransformSummary>>(());
-        cursor.seek(&self, Bias::Right);
-        let overshoot = self.0 - cursor.start().1.output.lines;
-        let mut offset = cursor.start().1.output.len;
+            .find::<Dimensions<FoldPoint, TransformSummary>, _>((), &self, Bias::Right);
+        let overshoot = self.0 - start.1.output.lines;
+        let mut offset = start.1.output.len;
         if !overshoot.is_zero() {
-            let transform = cursor.item().expect("display point out of range");
+            let transform = item.expect("display point out of range");
             assert!(transform.placeholder.is_none());
             let end_inlay_offset = snapshot
                 .inlay_snapshot
-                .to_offset(InlayPoint(cursor.start().1.input.lines + overshoot));
-            offset += end_inlay_offset.0 - cursor.start().1.input.len;
+                .to_offset(InlayPoint(start.1.input.lines + overshoot));
+            offset += end_inlay_offset.0 - start.1.input.len;
         }
         FoldOffset(offset)
     }
@@ -706,19 +704,18 @@ impl FoldSnapshot {
     }
 
     pub fn to_fold_point(&self, point: InlayPoint, bias: Bias) -> FoldPoint {
-        let mut cursor = self
+        let (start, end, item) = self
             .transforms
-            .cursor::<Dimensions<InlayPoint, FoldPoint>>(());
-        cursor.seek(&point, Bias::Right);
-        if cursor.item().is_some_and(|t| t.is_fold()) {
-            if bias == Bias::Left || point == cursor.start().0 {
-                cursor.start().1
+            .find::<Dimensions<InlayPoint, FoldPoint>, _>((), &point, Bias::Right);
+        if item.is_some_and(|t| t.is_fold()) {
+            if bias == Bias::Left || point == start.0 {
+                start.1
             } else {
-                cursor.end().1
+                end.1
             }
         } else {
-            let overshoot = point.0 - cursor.start().0.0;
-            FoldPoint(cmp::min(cursor.start().1.0 + overshoot, cursor.end().1.0))
+            let overshoot = point.0 - start.0.0;
+            FoldPoint(cmp::min(start.1.0 + overshoot, end.1.0))
         }
     }
 
@@ -787,9 +784,10 @@ impl FoldSnapshot {
     {
         let buffer_offset = offset.to_offset(&self.inlay_snapshot.buffer);
         let inlay_offset = self.inlay_snapshot.to_inlay_offset(buffer_offset);
-        let mut cursor = self.transforms.cursor::<InlayOffset>(());
-        cursor.seek(&inlay_offset, Bias::Right);
-        cursor.item().is_some_and(|t| t.placeholder.is_some())
+        let (_, _, item) = self
+            .transforms
+            .find::<InlayOffset, _>((), &inlay_offset, Bias::Right);
+        item.is_some_and(|t| t.placeholder.is_some())
     }
 
     pub fn is_line_folded(&self, buffer_row: MultiBufferRow) -> bool {
@@ -891,23 +889,22 @@ impl FoldSnapshot {
     }
 
     pub fn clip_point(&self, point: FoldPoint, bias: Bias) -> FoldPoint {
-        let mut cursor = self
+        let (start, end, item) = self
             .transforms
-            .cursor::<Dimensions<FoldPoint, InlayPoint>>(());
-        cursor.seek(&point, Bias::Right);
-        if let Some(transform) = cursor.item() {
-            let transform_start = cursor.start().0.0;
+            .find::<Dimensions<FoldPoint, InlayPoint>, _>((), &point, Bias::Right);
+        if let Some(transform) = item {
+            let transform_start = start.0.0;
             if transform.placeholder.is_some() {
                 if point.0 == transform_start || matches!(bias, Bias::Left) {
                     FoldPoint(transform_start)
                 } else {
-                    FoldPoint(cursor.end().0.0)
+                    FoldPoint(end.0.0)
                 }
             } else {
                 let overshoot = InlayPoint(point.0 - transform_start);
-                let inlay_point = cursor.start().1 + overshoot;
+                let inlay_point = start.1 + overshoot;
                 let clipped_inlay_point = self.inlay_snapshot.clip_point(inlay_point, bias);
-                FoldPoint(cursor.start().0.0 + (clipped_inlay_point - cursor.start().1).0)
+                FoldPoint(start.0.0 + (clipped_inlay_point - start.1).0)
             }
         } else {
             FoldPoint(self.transforms.summary().output.lines)
@@ -1480,28 +1477,26 @@ pub struct FoldOffset(pub usize);
 
 impl FoldOffset {
     pub fn to_point(self, snapshot: &FoldSnapshot) -> FoldPoint {
-        let mut cursor = snapshot
+        let (start, _, item) = snapshot
             .transforms
-            .cursor::<Dimensions<FoldOffset, TransformSummary>>(());
-        cursor.seek(&self, Bias::Right);
-        let overshoot = if cursor.item().is_none_or(|t| t.is_fold()) {
-            Point::new(0, (self.0 - cursor.start().0.0) as u32)
+            .find::<Dimensions<FoldOffset, TransformSummary>, _>((), &self, Bias::Right);
+        let overshoot = if item.is_none_or(|t| t.is_fold()) {
+            Point::new(0, (self.0 - start.0.0) as u32)
         } else {
-            let inlay_offset = cursor.start().1.input.len + self.0 - cursor.start().0.0;
+            let inlay_offset = start.1.input.len + self.0 - start.0.0;
             let inlay_point = snapshot.inlay_snapshot.to_point(InlayOffset(inlay_offset));
-            inlay_point.0 - cursor.start().1.input.lines
+            inlay_point.0 - start.1.input.lines
         };
-        FoldPoint(cursor.start().1.output.lines + overshoot)
+        FoldPoint(start.1.output.lines + overshoot)
     }
 
     #[cfg(test)]
     pub fn to_inlay_offset(self, snapshot: &FoldSnapshot) -> InlayOffset {
-        let mut cursor = snapshot
+        let (start, _, _) = snapshot
             .transforms
-            .cursor::<Dimensions<FoldOffset, InlayOffset>>(());
-        cursor.seek(&self, Bias::Right);
-        let overshoot = self.0 - cursor.start().0.0;
-        InlayOffset(cursor.start().1.0 + overshoot)
+            .find::<Dimensions<FoldOffset, InlayOffset>, _>((), &self, Bias::Right);
+        let overshoot = self.0 - start.0.0;
+        InlayOffset(start.1.0 + overshoot)
     }
 }
 

crates/editor/src/display_map/inlay_map.rs 🔗

@@ -825,22 +825,21 @@ impl InlayMap {
 
 impl InlaySnapshot {
     pub fn to_point(&self, offset: InlayOffset) -> InlayPoint {
-        let mut cursor = self
+        let (start, _, item) = self
             .transforms
-            .cursor::<Dimensions<InlayOffset, InlayPoint, usize>>(());
-        cursor.seek(&offset, Bias::Right);
-        let overshoot = offset.0 - cursor.start().0.0;
-        match cursor.item() {
+            .find::<Dimensions<InlayOffset, InlayPoint, usize>, _>((), &offset, Bias::Right);
+        let overshoot = offset.0 - start.0.0;
+        match item {
             Some(Transform::Isomorphic(_)) => {
-                let buffer_offset_start = cursor.start().2;
+                let buffer_offset_start = start.2;
                 let buffer_offset_end = buffer_offset_start + overshoot;
                 let buffer_start = self.buffer.offset_to_point(buffer_offset_start);
                 let buffer_end = self.buffer.offset_to_point(buffer_offset_end);
-                InlayPoint(cursor.start().1.0 + (buffer_end - buffer_start))
+                InlayPoint(start.1.0 + (buffer_end - buffer_start))
             }
             Some(Transform::Inlay(inlay)) => {
                 let overshoot = inlay.text().offset_to_point(overshoot);
-                InlayPoint(cursor.start().1.0 + overshoot)
+                InlayPoint(start.1.0 + overshoot)
             }
             None => self.max_point(),
         }
@@ -855,47 +854,48 @@ impl InlaySnapshot {
     }
 
     pub fn to_offset(&self, point: InlayPoint) -> InlayOffset {
-        let mut cursor = self
+        let (start, _, item) = self
             .transforms
-            .cursor::<Dimensions<InlayPoint, InlayOffset, Point>>(());
-        cursor.seek(&point, Bias::Right);
-        let overshoot = point.0 - cursor.start().0.0;
-        match cursor.item() {
+            .find::<Dimensions<InlayPoint, InlayOffset, Point>, _>((), &point, Bias::Right);
+        let overshoot = point.0 - start.0.0;
+        match item {
             Some(Transform::Isomorphic(_)) => {
-                let buffer_point_start = cursor.start().2;
+                let buffer_point_start = start.2;
                 let buffer_point_end = buffer_point_start + overshoot;
                 let buffer_offset_start = self.buffer.point_to_offset(buffer_point_start);
                 let buffer_offset_end = self.buffer.point_to_offset(buffer_point_end);
-                InlayOffset(cursor.start().1.0 + (buffer_offset_end - buffer_offset_start))
+                InlayOffset(start.1.0 + (buffer_offset_end - buffer_offset_start))
             }
             Some(Transform::Inlay(inlay)) => {
                 let overshoot = inlay.text().point_to_offset(overshoot);
-                InlayOffset(cursor.start().1.0 + overshoot)
+                InlayOffset(start.1.0 + overshoot)
             }
             None => self.len(),
         }
     }
     pub fn to_buffer_point(&self, point: InlayPoint) -> Point {
-        let mut cursor = self.transforms.cursor::<Dimensions<InlayPoint, Point>>(());
-        cursor.seek(&point, Bias::Right);
-        match cursor.item() {
+        let (start, _, item) =
+            self.transforms
+                .find::<Dimensions<InlayPoint, Point>, _>((), &point, Bias::Right);
+        match item {
             Some(Transform::Isomorphic(_)) => {
-                let overshoot = point.0 - cursor.start().0.0;
-                cursor.start().1 + overshoot
+                let overshoot = point.0 - start.0.0;
+                start.1 + overshoot
             }
-            Some(Transform::Inlay(_)) => cursor.start().1,
+            Some(Transform::Inlay(_)) => start.1,
             None => self.buffer.max_point(),
         }
     }
     pub fn to_buffer_offset(&self, offset: InlayOffset) -> usize {
-        let mut cursor = self.transforms.cursor::<Dimensions<InlayOffset, usize>>(());
-        cursor.seek(&offset, Bias::Right);
-        match cursor.item() {
+        let (start, _, item) =
+            self.transforms
+                .find::<Dimensions<InlayOffset, usize>, _>((), &offset, Bias::Right);
+        match item {
             Some(Transform::Isomorphic(_)) => {
-                let overshoot = offset - cursor.start().0;
-                cursor.start().1 + overshoot.0
+                let overshoot = offset - start.0;
+                start.1 + overshoot.0
             }
-            Some(Transform::Inlay(_)) => cursor.start().1,
+            Some(Transform::Inlay(_)) => start.1,
             None => self.buffer.len(),
         }
     }

crates/editor/src/display_map/wrap_map.rs 🔗

@@ -568,14 +568,17 @@ impl WrapSnapshot {
             let mut old_start = old_cursor.start().output.lines;
             old_start += tab_edit.old.start.0 - old_cursor.start().input.lines;
 
+            // todo(lw): Should these be seek_forward?
             old_cursor.seek(&tab_edit.old.end, Bias::Right);
             let mut old_end = old_cursor.start().output.lines;
             old_end += tab_edit.old.end.0 - old_cursor.start().input.lines;
 
+            // todo(lw): Should these be seek_forward?
             new_cursor.seek(&tab_edit.new.start, Bias::Right);
             let mut new_start = new_cursor.start().output.lines;
             new_start += tab_edit.new.start.0 - new_cursor.start().input.lines;
 
+            // todo(lw): Should these be seek_forward?
             new_cursor.seek(&tab_edit.new.end, Bias::Right);
             let mut new_end = new_cursor.start().output.lines;
             new_end += tab_edit.new.end.0 - new_cursor.start().input.lines;
@@ -628,24 +631,22 @@ impl WrapSnapshot {
     }
 
     pub fn line_len(&self, row: u32) -> u32 {
-        let mut cursor = self
-            .transforms
-            .cursor::<Dimensions<WrapPoint, TabPoint>>(());
-        cursor.seek(&WrapPoint::new(row + 1, 0), Bias::Left);
-        if cursor
-            .item()
-            .is_some_and(|transform| transform.is_isomorphic())
-        {
-            let overshoot = row - cursor.start().0.row();
-            let tab_row = cursor.start().1.row() + overshoot;
+        let (start, _, item) = self.transforms.find::<Dimensions<WrapPoint, TabPoint>, _>(
+            (),
+            &WrapPoint::new(row + 1, 0),
+            Bias::Left,
+        );
+        if item.is_some_and(|transform| transform.is_isomorphic()) {
+            let overshoot = row - start.0.row();
+            let tab_row = start.1.row() + overshoot;
             let tab_line_len = self.tab_snapshot.line_len(tab_row);
             if overshoot == 0 {
-                cursor.start().0.column() + (tab_line_len - cursor.start().1.column())
+                start.0.column() + (tab_line_len - start.1.column())
             } else {
                 tab_line_len
             }
         } else {
-            cursor.start().0.column()
+            start.0.column()
         }
     }
 
@@ -711,9 +712,10 @@ impl WrapSnapshot {
     }
 
     pub fn soft_wrap_indent(&self, row: u32) -> Option<u32> {
-        let mut cursor = self.transforms.cursor::<WrapPoint>(());
-        cursor.seek(&WrapPoint::new(row + 1, 0), Bias::Right);
-        cursor.item().and_then(|transform| {
+        let (.., item) =
+            self.transforms
+                .find::<WrapPoint, _>((), &WrapPoint::new(row + 1, 0), Bias::Right);
+        item.and_then(|transform| {
             if transform.is_isomorphic() {
                 None
             } else {
@@ -749,13 +751,12 @@ impl WrapSnapshot {
     }
 
     pub fn to_tab_point(&self, point: WrapPoint) -> TabPoint {
-        let mut cursor = self
-            .transforms
-            .cursor::<Dimensions<WrapPoint, TabPoint>>(());
-        cursor.seek(&point, Bias::Right);
-        let mut tab_point = cursor.start().1.0;
-        if cursor.item().is_some_and(|t| t.is_isomorphic()) {
-            tab_point += point.0 - cursor.start().0.0;
+        let (start, _, item) =
+            self.transforms
+                .find::<Dimensions<WrapPoint, TabPoint>, _>((), &point, Bias::Right);
+        let mut tab_point = start.1.0;
+        if item.is_some_and(|t| t.is_isomorphic()) {
+            tab_point += point.0 - start.0.0;
         }
         TabPoint(tab_point)
     }
@@ -769,19 +770,19 @@ impl WrapSnapshot {
     }
 
     pub fn tab_point_to_wrap_point(&self, point: TabPoint) -> WrapPoint {
-        let mut cursor = self
-            .transforms
-            .cursor::<Dimensions<TabPoint, WrapPoint>>(());
-        cursor.seek(&point, Bias::Right);
-        WrapPoint(cursor.start().1.0 + (point.0 - cursor.start().0.0))
+        let (start, ..) =
+            self.transforms
+                .find::<Dimensions<TabPoint, WrapPoint>, _>((), &point, Bias::Right);
+        WrapPoint(start.1.0 + (point.0 - start.0.0))
     }
 
     pub fn clip_point(&self, mut point: WrapPoint, bias: Bias) -> WrapPoint {
         if bias == Bias::Left {
-            let mut cursor = self.transforms.cursor::<WrapPoint>(());
-            cursor.seek(&point, Bias::Right);
-            if cursor.item().is_some_and(|t| !t.is_isomorphic()) {
-                point = *cursor.start();
+            let (start, _, item) = self
+                .transforms
+                .find::<WrapPoint, _>((), &point, Bias::Right);
+            if item.is_some_and(|t| !t.is_isomorphic()) {
+                point = start;
                 *point.column_mut() -= 1;
             }
         }

crates/gpui/src/elements/list.rs 🔗

@@ -509,10 +509,11 @@ impl StateInner {
         if self.alignment == ListAlignment::Bottom && new_scroll_top == scroll_max {
             self.logical_scroll_top = None;
         } else {
-            let mut cursor = self.items.cursor::<ListItemSummary>(());
-            cursor.seek(&Height(new_scroll_top), Bias::Right);
-            let item_ix = cursor.start().count;
-            let offset_in_item = new_scroll_top - cursor.start().height;
+            let (start, ..) =
+                self.items
+                    .find::<ListItemSummary, _>((), &Height(new_scroll_top), Bias::Right);
+            let item_ix = start.count;
+            let offset_in_item = new_scroll_top - start.height;
             self.logical_scroll_top = Some(ListOffset {
                 item_ix,
                 offset_in_item,
@@ -550,9 +551,12 @@ impl StateInner {
     }
 
     fn scroll_top(&self, logical_scroll_top: &ListOffset) -> Pixels {
-        let mut cursor = self.items.cursor::<ListItemSummary>(());
-        cursor.seek(&Count(logical_scroll_top.item_ix), Bias::Right);
-        cursor.start().height + logical_scroll_top.offset_in_item
+        let (start, ..) = self.items.find::<ListItemSummary, _>(
+            (),
+            &Count(logical_scroll_top.item_ix),
+            Bias::Right,
+        );
+        start.height + logical_scroll_top.offset_in_item
     }
 
     fn layout_all_items(
@@ -882,11 +886,12 @@ impl StateInner {
         if self.alignment == ListAlignment::Bottom && new_scroll_top == scroll_max {
             self.logical_scroll_top = None;
         } else {
-            let mut cursor = self.items.cursor::<ListItemSummary>(());
-            cursor.seek(&Height(new_scroll_top), Bias::Right);
+            let (start, _, _) =
+                self.items
+                    .find::<ListItemSummary, _>((), &Height(new_scroll_top), Bias::Right);
 
-            let item_ix = cursor.start().count;
-            let offset_in_item = new_scroll_top - cursor.start().height;
+            let item_ix = start.count;
+            let offset_in_item = new_scroll_top - start.height;
             self.logical_scroll_top = Some(ListOffset {
                 item_ix,
                 offset_in_item,

crates/multi_buffer/src/multi_buffer.rs 🔗

@@ -6140,9 +6140,8 @@ impl MultiBufferSnapshot {
         } else if id == ExcerptId::max() {
             Locator::max_ref()
         } else {
-            let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(());
-            cursor.seek(&id, Bias::Left);
-            if let Some(entry) = cursor.item()
+            let (_, _, item) = self.excerpt_ids.find::<ExcerptId, _>((), &id, Bias::Left);
+            if let Some(entry) = item
                 && entry.id == id
             {
                 return &entry.locator;

crates/notifications/src/notification_store.rs 🔗

@@ -123,14 +123,16 @@ impl NotificationStore {
             return None;
         }
         let ix = count - 1 - ix;
-        let mut cursor = self.notifications.cursor::<Count>(());
-        cursor.seek(&Count(ix), Bias::Right);
-        cursor.item()
+        let (.., item) = self
+            .notifications
+            .find::<Count, _>((), &Count(ix), Bias::Right);
+        item
     }
     pub fn notification_for_id(&self, id: u64) -> Option<&NotificationEntry> {
-        let mut cursor = self.notifications.cursor::<NotificationId>(());
-        cursor.seek(&NotificationId(id), Bias::Left);
-        if let Some(item) = cursor.item()
+        let (.., item) =
+            self.notifications
+                .find::<NotificationId, _>((), &NotificationId(id), Bias::Left);
+        if let Some(item) = item
             && item.id == id
         {
             return Some(item);

crates/rope/src/rope.rs 🔗

@@ -41,12 +41,9 @@ impl Rope {
         if self.chunks.is_empty() {
             return offset == 0;
         }
-        let mut cursor = self.chunks.cursor::<usize>(());
-        cursor.seek(&offset, Bias::Left);
-        let chunk_offset = offset - cursor.start();
-        cursor
-            .item()
-            .map(|chunk| chunk.text.is_char_boundary(chunk_offset))
+        let (start, _, item) = self.chunks.find::<usize, _>((), &offset, Bias::Left);
+        let chunk_offset = offset - start;
+        item.map(|chunk| chunk.text.is_char_boundary(chunk_offset))
             .unwrap_or(false)
     }
 
@@ -60,10 +57,9 @@ impl Rope {
                 (u8 as i8) >= -0x40
             }
 
-            let mut cursor = self.chunks.cursor::<usize>(());
-            cursor.seek(&index, Bias::Left);
-            let chunk_offset = index - cursor.start();
-            let lower_idx = cursor.item().map(|chunk| {
+            let (start, _, item) = self.chunks.find::<usize, _>((), &index, Bias::Left);
+            let chunk_offset = index - start;
+            let lower_idx = item.map(|chunk| {
                 let lower_bound = chunk_offset.saturating_sub(3);
                 chunk
                     .text
@@ -78,7 +74,7 @@ impl Rope {
                     })
                     .unwrap_or(chunk.text.len())
             });
-            lower_idx.map_or_else(|| self.len(), |idx| cursor.start() + idx)
+            lower_idx.map_or_else(|| self.len(), |idx| start + idx)
         }
     }
 
@@ -92,10 +88,9 @@ impl Rope {
                 (u8 as i8) >= -0x40
             }
 
-            let mut cursor = self.chunks.cursor::<usize>(());
-            cursor.seek(&index, Bias::Left);
-            let chunk_offset = index - cursor.start();
-            let upper_idx = cursor.item().map(|chunk| {
+            let (start, _, item) = self.chunks.find::<usize, _>((), &index, Bias::Left);
+            let chunk_offset = index - start;
+            let upper_idx = item.map(|chunk| {
                 let upper_bound = Ord::min(chunk_offset + 4, chunk.text.len());
                 chunk.text.as_bytes()[chunk_offset..upper_bound]
                     .iter()
@@ -103,7 +98,7 @@ impl Rope {
                     .map_or(upper_bound, |pos| pos + chunk_offset)
             });
 
-            upper_idx.map_or_else(|| self.len(), |idx| cursor.start() + idx)
+            upper_idx.map_or_else(|| self.len(), |idx| start + idx)
         }
     }
 
@@ -356,11 +351,12 @@ impl Rope {
         if offset >= self.summary().len {
             return self.summary().len_utf16;
         }
-        let mut cursor = self.chunks.cursor::<Dimensions<usize, OffsetUtf16>>(());
-        cursor.seek(&offset, Bias::Left);
-        let overshoot = offset - cursor.start().0;
-        cursor.start().1
-            + cursor.item().map_or(Default::default(), |chunk| {
+        let (start, _, item) =
+            self.chunks
+                .find::<Dimensions<usize, OffsetUtf16>, _>((), &offset, Bias::Left);
+        let overshoot = offset - start.0;
+        start.1
+            + item.map_or(Default::default(), |chunk| {
                 chunk.as_slice().offset_to_offset_utf16(overshoot)
             })
     }

crates/sum_tree/src/cursor.rs 🔗

@@ -388,6 +388,7 @@ where
     T: Item,
     D: Dimension<'a, T::Summary>,
 {
+    /// Returns whether we found the item you were seeking for.
     #[track_caller]
     pub fn seek<Target>(&mut self, pos: &Target, bias: Bias) -> bool
     where
@@ -397,6 +398,7 @@ where
         self.seek_internal(pos, bias, &mut ())
     }
 
+    /// Returns whether we found the item you were seeking for.
     #[track_caller]
     pub fn seek_forward<Target>(&mut self, pos: &Target, bias: Bias) -> bool
     where
@@ -437,7 +439,7 @@ where
         summary.0
     }
 
-    /// Returns whether we found the item you were seeking for
+    /// Returns whether we found the item you were seeking for.
     #[track_caller]
     fn seek_internal(
         &mut self,

crates/sum_tree/src/sum_tree.rs 🔗

@@ -82,6 +82,11 @@ pub trait Dimension<'a, S: Summary>: Clone {
     fn zero(cx: S::Context<'_>) -> Self;
 
     fn add_summary(&mut self, summary: &'a S, cx: S::Context<'_>);
+    #[must_use]
+    fn with_added_summary(mut self, summary: &'a S, cx: S::Context<'_>) -> Self {
+        self.add_summary(summary, cx);
+        self
+    }
 
     fn from_summary(summary: &'a S, cx: S::Context<'_>) -> Self {
         let mut dimension = Self::zero(cx);
@@ -371,12 +376,122 @@ impl<T: Item> SumTree<T> {
         Iter::new(self)
     }
 
-    pub fn cursor<'a, 'b, S>(
+    /// A more efficient version of `Cursor::new()` + `Cursor::seek()` + `Cursor::item()`.
+    ///
+    /// Only returns the item that exactly has the target match.
+    pub fn find_exact<'a, 'slf, D, Target>(
+        &'slf self,
+        cx: <T::Summary as Summary>::Context<'a>,
+        target: &Target,
+        bias: Bias,
+    ) -> (D, D, Option<&'slf T>)
+    where
+        D: Dimension<'slf, T::Summary>,
+        Target: SeekTarget<'slf, T::Summary, D>,
+    {
+        let tree_end = D::zero(cx).with_added_summary(self.summary(), cx);
+        let comparison = target.cmp(&tree_end, cx);
+        if comparison == Ordering::Greater || (comparison == Ordering::Equal && bias == Bias::Right)
+        {
+            return (tree_end.clone(), tree_end, None);
+        }
+
+        let mut pos = D::zero(cx);
+        return match Self::find_recurse::<_, _, true>(cx, target, bias, &mut pos, self) {
+            Some((item, end)) => (pos, end, Some(item)),
+            None => (pos.clone(), pos, None),
+        };
+    }
+
+    /// A more efficient version of `Cursor::new()` + `Cursor::seek()` + `Cursor::item()`
+    pub fn find<'a, 'slf, D, Target>(
+        &'slf self,
+        cx: <T::Summary as Summary>::Context<'a>,
+        target: &Target,
+        bias: Bias,
+    ) -> (D, D, Option<&'slf T>)
+    where
+        D: Dimension<'slf, T::Summary>,
+        Target: SeekTarget<'slf, T::Summary, D>,
+    {
+        let tree_end = D::zero(cx).with_added_summary(self.summary(), cx);
+        let comparison = target.cmp(&tree_end, cx);
+        if comparison == Ordering::Greater || (comparison == Ordering::Equal && bias == Bias::Right)
+        {
+            return (tree_end.clone(), tree_end, None);
+        }
+
+        let mut pos = D::zero(cx);
+        return match Self::find_recurse::<_, _, false>(cx, target, bias, &mut pos, self) {
+            Some((item, end)) => (pos, end, Some(item)),
+            None => (pos.clone(), pos, None),
+        };
+    }
+
+    fn find_recurse<'tree, 'a, D, Target, const EXACT: bool>(
+        cx: <T::Summary as Summary>::Context<'a>,
+        target: &Target,
+        bias: Bias,
+        position: &mut D,
+        this: &'tree SumTree<T>,
+    ) -> Option<(&'tree T, D)>
+    where
+        D: Dimension<'tree, T::Summary>,
+        Target: SeekTarget<'tree, T::Summary, D>,
+    {
+        match &*this.0 {
+            Node::Internal {
+                child_summaries,
+                child_trees,
+                ..
+            } => {
+                for (child_tree, child_summary) in child_trees.iter().zip(child_summaries) {
+                    let child_end = position.clone().with_added_summary(child_summary, cx);
+
+                    let comparison = target.cmp(&child_end, cx);
+                    let target_in_child = comparison == Ordering::Less
+                        || (comparison == Ordering::Equal && bias == Bias::Left);
+                    if target_in_child {
+                        return Self::find_recurse::<D, Target, EXACT>(
+                            cx, target, bias, position, child_tree,
+                        );
+                    }
+                    *position = child_end;
+                }
+            }
+            Node::Leaf {
+                items,
+                item_summaries,
+                ..
+            } => {
+                for (item, item_summary) in items.iter().zip(item_summaries) {
+                    let mut child_end = position.clone();
+                    child_end.add_summary(item_summary, cx);
+
+                    let comparison = target.cmp(&child_end, cx);
+                    let entry_found = if EXACT {
+                        comparison == Ordering::Equal
+                    } else {
+                        comparison == Ordering::Less
+                            || (comparison == Ordering::Equal && bias == Bias::Left)
+                    };
+                    if entry_found {
+                        return Some((item, child_end));
+                    }
+
+                    *position = child_end;
+                }
+            }
+        }
+        None
+    }
+
+    pub fn cursor<'a, 'b, D>(
         &'a self,
         cx: <T::Summary as Summary>::Context<'b>,
-    ) -> Cursor<'a, 'b, T, S>
+    ) -> Cursor<'a, 'b, T, D>
     where
-        S: Dimension<'a, T::Summary>,
+        D: Dimension<'a, T::Summary>,
     {
         Cursor::new(self, cx)
     }
@@ -787,9 +902,8 @@ impl<T: KeyedItem> SumTree<T> {
         key: &T::Key,
         cx: <T::Summary as Summary>::Context<'a>,
     ) -> Option<&'a T> {
-        let mut cursor = self.cursor::<T::Key>(cx);
-        if cursor.seek(key, Bias::Left) {
-            cursor.item()
+        if let (_, _, Some(item)) = self.find_exact::<T::Key, _>(cx, key, Bias::Left) {
+            Some(item)
         } else {
             None
         }

crates/sum_tree/src/tree_map.rs 🔗

@@ -54,9 +54,10 @@ impl<K: Clone + Ord, V: Clone> TreeMap<K, V> {
     }
 
     pub fn get(&self, key: &K) -> Option<&V> {
-        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>(());
-        cursor.seek(&MapKeyRef(Some(key)), Bias::Left);
-        if let Some(item) = cursor.item() {
+        let (.., item) = self
+            .0
+            .find::<MapKeyRef<'_, K>, _>((), &MapKeyRef(Some(key)), Bias::Left);
+        if let Some(item) = item {
             if Some(key) == item.key().0.as_ref() {
                 Some(&item.value)
             } else {

crates/text/src/anchor.rs 🔗

@@ -99,13 +99,14 @@ impl Anchor {
             let Some(fragment_id) = buffer.try_fragment_id_for_anchor(self) else {
                 return false;
             };
-            let mut fragment_cursor = buffer
+            let (.., item) = buffer
                 .fragments
-                .cursor::<Dimensions<Option<&Locator>, usize>>(&None);
-            fragment_cursor.seek(&Some(fragment_id), Bias::Left);
-            fragment_cursor
-                .item()
-                .is_some_and(|fragment| fragment.visible)
+                .find::<Dimensions<Option<&Locator>, usize>, _>(
+                    &None,
+                    &Some(fragment_id),
+                    Bias::Left,
+                );
+            item.is_some_and(|fragment| fragment.visible)
         }
     }
 }

crates/text/src/text.rs 🔗

@@ -2323,12 +2323,15 @@ impl BufferSnapshot {
                 );
             };
 
-            let mut fragment_cursor = self
+            let (start, _, item) = self
                 .fragments
-                .cursor::<Dimensions<Option<&Locator>, usize>>(&None);
-            fragment_cursor.seek(&Some(&insertion.fragment_id), Bias::Left);
-            let fragment = fragment_cursor.item().unwrap();
-            let mut fragment_offset = fragment_cursor.start().1;
+                .find::<Dimensions<Option<&Locator>, usize>, _>(
+                    &None,
+                    &Some(&insertion.fragment_id),
+                    Bias::Left,
+                );
+            let fragment = item.unwrap();
+            let mut fragment_offset = start.1;
             if fragment.visible {
                 fragment_offset += anchor.offset - insertion.split_offset;
             }
@@ -2410,10 +2413,9 @@ impl BufferSnapshot {
                     offset, ch, char_range,
                 );
             }
-            let mut fragment_cursor = self.fragments.cursor::<usize>(&None);
-            fragment_cursor.seek(&offset, bias);
-            let fragment = fragment_cursor.item().unwrap();
-            let overshoot = offset - *fragment_cursor.start();
+            let (start, _, item) = self.fragments.find::<usize, _>(&None, &offset, bias);
+            let fragment = item.unwrap();
+            let overshoot = offset - start;
             Anchor {
                 timestamp: fragment.timestamp,
                 offset: fragment.insertion_offset + overshoot,
@@ -2494,15 +2496,17 @@ impl BufferSnapshot {
             cursor.next();
             Some(cursor)
         };
-        let mut cursor = self
-            .fragments
-            .cursor::<Dimensions<Option<&Locator>, FragmentTextSummary>>(&None);
-
         let start_fragment_id = self.fragment_id_for_anchor(&range.start);
-        cursor.seek(&Some(start_fragment_id), Bias::Left);
-        let mut visible_start = cursor.start().1.visible;
-        let mut deleted_start = cursor.start().1.deleted;
-        if let Some(fragment) = cursor.item() {
+        let (start, _, item) = self
+            .fragments
+            .find::<Dimensions<Option<&Locator>, FragmentTextSummary>, _>(
+                &None,
+                &Some(start_fragment_id),
+                Bias::Left,
+            );
+        let mut visible_start = start.1.visible;
+        let mut deleted_start = start.1.deleted;
+        if let Some(fragment) = item {
             let overshoot = range.start.offset - fragment.insertion_offset;
             if fragment.visible {
                 visible_start += overshoot;