Replace Default trait bound with a zero function on Summary/Dimension (#17975)

Antonio Scandurra and Nathan created

This lets us provide a context when constructing the zero value. We need
it so we can require anchors to be associated with a buffer id, which
we're doing as part of simplifying the multibuffer API.

Release Notes:

- N/A

Co-authored-by: Nathan <nathan@zed.dev>

Change summary

crates/channel/src/channel_chat.rs                 |  30 ++-
crates/editor/src/display_map.rs                   |   5 
crates/editor/src/display_map/block_map.rs         |  38 ++-
crates/editor/src/display_map/crease_map.rs        |  41 +++-
crates/editor/src/display_map/fold_map.rs          |  79 ++++++--
crates/editor/src/display_map/inlay_map.rs         |  47 +++-
crates/editor/src/display_map/wrap_map.rs          |  44 +++-
crates/editor/src/git/blame.rs                     |  14 +
crates/git/src/diff.rs                             |  46 ++--
crates/gpui/src/elements/list.rs                   |  34 ++-
crates/language/src/buffer.rs                      |  10 
crates/language/src/diagnostic_set.rs              |   8 
crates/language/src/syntax_map.rs                  |  39 +++-
crates/language/src/syntax_map/syntax_map_tests.rs |  16 
crates/multi_buffer/src/multi_buffer.rs            | 142 ++++++++++-----
crates/notifications/src/notification_store.rs     |  21 +
crates/project/src/lsp_store.rs                    |   8 
crates/rope/src/rope.rs                            |  66 +++++--
crates/rope/src/unclipped.rs                       |   4 
crates/sum_tree/src/cursor.rs                      |  36 ++-
crates/sum_tree/src/sum_tree.rs                    | 125 +++++++++----
crates/sum_tree/src/tree_map.rs                    |  22 +
crates/text/src/anchor.rs                          |   2 
crates/text/src/locator.rs                         |   4 
crates/text/src/operation_queue.rs                 |  12 +
crates/text/src/text.rs                            |  94 ++++++---
crates/text/src/undo_map.rs                        |   9 
crates/worktree/src/worktree.rs                    |  59 ++++-
28 files changed, 706 insertions(+), 349 deletions(-)

Detailed changes

crates/channel/src/channel_chat.rs 🔗

@@ -332,7 +332,7 @@ impl ChannelChat {
                 .update(&mut cx, |chat, cx| {
                     if let Some(first_id) = chat.first_loaded_message_id() {
                         if first_id <= message_id {
-                            let mut cursor = chat.messages.cursor::<(ChannelMessageId, Count)>();
+                            let mut cursor = chat.messages.cursor::<(ChannelMessageId, Count)>(&());
                             let message_id = ChannelMessageId::Saved(message_id);
                             cursor.seek(&message_id, Bias::Left, &());
                             return ControlFlow::Break(
@@ -498,7 +498,7 @@ impl ChannelChat {
     }
 
     pub fn message(&self, ix: usize) -> &ChannelMessage {
-        let mut cursor = self.messages.cursor::<Count>();
+        let mut cursor = self.messages.cursor::<Count>(&());
         cursor.seek(&Count(ix), Bias::Right, &());
         cursor.item().unwrap()
     }
@@ -515,13 +515,13 @@ impl ChannelChat {
     }
 
     pub fn messages_in_range(&self, range: Range<usize>) -> impl Iterator<Item = &ChannelMessage> {
-        let mut cursor = self.messages.cursor::<Count>();
+        let mut cursor = self.messages.cursor::<Count>(&());
         cursor.seek(&Count(range.start), Bias::Right, &());
         cursor.take(range.len())
     }
 
     pub fn pending_messages(&self) -> impl Iterator<Item = &ChannelMessage> {
-        let mut cursor = self.messages.cursor::<ChannelMessageId>();
+        let mut cursor = self.messages.cursor::<ChannelMessageId>(&());
         cursor.seek(&ChannelMessageId::Pending(0), Bias::Left, &());
         cursor
     }
@@ -589,11 +589,11 @@ impl ChannelChat {
     fn insert_messages(&mut self, messages: SumTree<ChannelMessage>, cx: &mut ModelContext<Self>) {
         if let Some((first_message, last_message)) = messages.first().zip(messages.last()) {
             let nonces = messages
-                .cursor::<()>()
+                .cursor::<()>(&())
                 .map(|m| m.nonce)
                 .collect::<HashSet<_>>();
 
-            let mut old_cursor = self.messages.cursor::<(ChannelMessageId, Count)>();
+            let mut old_cursor = self.messages.cursor::<(ChannelMessageId, Count)>(&());
             let mut new_messages = old_cursor.slice(&first_message.id, Bias::Left, &());
             let start_ix = old_cursor.start().1 .0;
             let removed_messages = old_cursor.slice(&last_message.id, Bias::Right, &());
@@ -646,7 +646,7 @@ impl ChannelChat {
     }
 
     fn message_removed(&mut self, id: u64, cx: &mut ModelContext<Self>) {
-        let mut cursor = self.messages.cursor::<ChannelMessageId>();
+        let mut cursor = self.messages.cursor::<ChannelMessageId>(&());
         let mut messages = cursor.slice(&ChannelMessageId::Saved(id), Bias::Left, &());
         if let Some(item) = cursor.item() {
             if item.id == ChannelMessageId::Saved(id) {
@@ -685,7 +685,7 @@ impl ChannelChat {
         edited_at: Option<OffsetDateTime>,
         cx: &mut ModelContext<Self>,
     ) {
-        let mut cursor = self.messages.cursor::<ChannelMessageId>();
+        let mut cursor = self.messages.cursor::<ChannelMessageId>(&());
         let mut messages = cursor.slice(&id, Bias::Left, &());
         let ix = messages.summary().count;
 
@@ -716,7 +716,7 @@ async fn messages_from_proto(
     cx: &mut AsyncAppContext,
 ) -> Result<SumTree<ChannelMessage>> {
     let messages = ChannelMessage::from_proto_vec(proto_messages, user_store, cx).await?;
-    let mut result = SumTree::new();
+    let mut result = SumTree::default();
     result.extend(messages, &());
     Ok(result)
 }
@@ -825,6 +825,10 @@ impl Default for ChannelMessageId {
 impl sum_tree::Summary for ChannelMessageSummary {
     type Context = ();
 
+    fn zero(_cx: &Self::Context) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &()) {
         self.max_id = summary.max_id;
         self.count += summary.count;
@@ -832,6 +836,10 @@ impl sum_tree::Summary for ChannelMessageSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChannelMessageSummary> for ChannelMessageId {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ChannelMessageSummary, _: &()) {
         debug_assert!(summary.max_id > *self);
         *self = summary.max_id;
@@ -839,6 +847,10 @@ impl<'a> sum_tree::Dimension<'a, ChannelMessageSummary> for ChannelMessageId {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChannelMessageSummary> for Count {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ChannelMessageSummary, _: &()) {
         self.0 += summary.count;
     }

crates/editor/src/display_map.rs 🔗

@@ -127,7 +127,9 @@ impl DisplayMap {
         let buffer_subscription = buffer.update(cx, |buffer, _| buffer.subscribe());
 
         let tab_size = Self::tab_size(&buffer, cx);
-        let (inlay_map, snapshot) = InlayMap::new(buffer.read(cx).snapshot(cx));
+        let buffer_snapshot = buffer.read(cx).snapshot(cx);
+        let crease_map = CreaseMap::new(&buffer_snapshot);
+        let (inlay_map, snapshot) = InlayMap::new(buffer_snapshot);
         let (fold_map, snapshot) = FoldMap::new(snapshot);
         let (tab_map, snapshot) = TabMap::new(snapshot, tab_size);
         let (wrap_map, snapshot) = WrapMap::new(snapshot, font, font_size, wrap_width, cx);
@@ -138,7 +140,6 @@ impl DisplayMap {
             excerpt_header_height,
             excerpt_footer_height,
         );
-        let crease_map = CreaseMap::default();
 
         cx.observe(&wrap_map, |_, _, cx| cx.notify()).detach();
 

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

@@ -389,10 +389,10 @@ impl BlockMap {
         }
 
         let mut transforms = self.transforms.borrow_mut();
-        let mut new_transforms = SumTree::new();
+        let mut new_transforms = SumTree::default();
         let old_row_count = transforms.summary().input_rows;
         let new_row_count = wrap_snapshot.max_point().row() + 1;
-        let mut cursor = transforms.cursor::<WrapRow>();
+        let mut cursor = transforms.cursor::<WrapRow>(&());
         let mut last_block_ix = 0;
         let mut blocks_in_edit = Vec::new();
         let mut edits = edits.into_iter().peekable();
@@ -757,7 +757,7 @@ impl<'a> BlockMapReader<'a> {
                 .unwrap_or(self.wrap_snapshot.max_point().row() + 1),
         );
 
-        let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>();
+        let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>(&());
         cursor.seek(&start_wrap_row, Bias::Left, &());
         while let Some(transform) = cursor.item() {
             if cursor.start().0 > end_wrap_row {
@@ -950,7 +950,7 @@ impl BlockSnapshot {
         highlights: Highlights<'a>,
     ) -> BlockChunks<'a> {
         let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows);
-        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
+        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
         let input_end = {
             cursor.seek(&BlockRow(rows.end), Bias::Right, &());
             let overshoot = if cursor
@@ -990,7 +990,7 @@ impl BlockSnapshot {
     }
 
     pub(super) fn buffer_rows(&self, start_row: BlockRow) -> BlockBufferRows {
-        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
+        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
         cursor.seek(&start_row, Bias::Right, &());
         let (output_start, input_start) = cursor.start();
         let overshoot = if cursor.item().map_or(false, |t| t.is_isomorphic()) {
@@ -1008,7 +1008,7 @@ impl BlockSnapshot {
     }
 
     pub fn blocks_in_range(&self, rows: Range<u32>) -> impl Iterator<Item = (u32, &Block)> {
-        let mut cursor = self.transforms.cursor::<BlockRow>();
+        let mut cursor = self.transforms.cursor::<BlockRow>(&());
         cursor.seek(&BlockRow(rows.start), Bias::Left, &());
         while cursor.start().0 < rows.start && cursor.end(&()).0 <= rows.start {
             cursor.next(&());
@@ -1050,7 +1050,7 @@ impl BlockSnapshot {
                 let wrap_point = self
                     .wrap_snapshot
                     .make_wrap_point(excerpt_range.start, Bias::Left);
-                let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>();
+                let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>(&());
                 cursor.seek(&WrapRow(wrap_point.row()), Bias::Left, &());
                 while let Some(transform) = cursor.item() {
                     if let Some(block) = transform.block.as_ref() {
@@ -1072,7 +1072,7 @@ impl BlockSnapshot {
                     .wrap_snapshot
                     .make_wrap_point(excerpt_range.end, Bias::Left);
 
-                let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>();
+                let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>(&());
                 cursor.seek(&WrapRow(wrap_point.row()), Bias::Left, &());
                 while let Some(transform) = cursor.item() {
                     if let Some(block) = transform.block.as_ref() {
@@ -1102,7 +1102,7 @@ impl BlockSnapshot {
     }
 
     pub(super) fn line_len(&self, row: BlockRow) -> u32 {
-        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
+        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
         cursor.seek(&BlockRow(row.0), Bias::Right, &());
         if let Some(transform) = cursor.item() {
             let (output_start, input_start) = cursor.start();
@@ -1118,13 +1118,13 @@ impl BlockSnapshot {
     }
 
     pub(super) fn is_block_line(&self, row: BlockRow) -> bool {
-        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
+        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
         cursor.seek(&row, Bias::Right, &());
         cursor.item().map_or(false, |t| t.block.is_some())
     }
 
     pub fn clip_point(&self, point: BlockPoint, bias: Bias) -> BlockPoint {
-        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
+        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
         cursor.seek(&BlockRow(point.row), Bias::Right, &());
 
         let max_input_row = WrapRow(self.transforms.summary().input_rows);
@@ -1172,7 +1172,7 @@ impl BlockSnapshot {
     }
 
     pub fn to_block_point(&self, wrap_point: WrapPoint) -> BlockPoint {
-        let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>();
+        let mut cursor = self.transforms.cursor::<(WrapRow, BlockRow)>(&());
         cursor.seek(&WrapRow(wrap_point.row()), Bias::Right, &());
         if let Some(transform) = cursor.item() {
             debug_assert!(transform.is_isomorphic());
@@ -1188,7 +1188,7 @@ impl BlockSnapshot {
     }
 
     pub fn to_wrap_point(&self, block_point: BlockPoint) -> WrapPoint {
-        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
+        let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(&());
         cursor.seek(&BlockRow(block_point.row), Bias::Right, &());
         if let Some(transform) = cursor.item() {
             match transform.block.as_ref().map(|b| b.disposition()) {
@@ -1368,6 +1368,10 @@ impl sum_tree::Item for Transform {
 impl sum_tree::Summary for TransformSummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &()) {
         self.input_rows += summary.input_rows;
         self.output_rows += summary.output_rows;
@@ -1375,12 +1379,20 @@ impl sum_tree::Summary for TransformSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for WrapRow {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         self.0 += summary.input_rows;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for BlockRow {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         self.0 += summary.output_rows;
     }

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

@@ -12,19 +12,34 @@ use crate::FoldPlaceholder;
 #[derive(Copy, Clone, Default, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
 pub struct CreaseId(usize);
 
-#[derive(Default)]
 pub struct CreaseMap {
     snapshot: CreaseSnapshot,
     next_id: CreaseId,
     id_to_range: HashMap<CreaseId, Range<Anchor>>,
 }
 
-#[derive(Clone, Default)]
+impl CreaseMap {
+    pub fn new(snapshot: &MultiBufferSnapshot) -> Self {
+        CreaseMap {
+            snapshot: CreaseSnapshot::new(snapshot),
+            next_id: CreaseId::default(),
+            id_to_range: HashMap::default(),
+        }
+    }
+}
+
+#[derive(Clone)]
 pub struct CreaseSnapshot {
     creases: SumTree<CreaseItem>,
 }
 
 impl CreaseSnapshot {
+    pub fn new(snapshot: &MultiBufferSnapshot) -> Self {
+        CreaseSnapshot {
+            creases: SumTree::new(snapshot),
+        }
+    }
+
     /// Returns the first Crease starting on the specified buffer row.
     pub fn query_row<'a>(
         &'a self,
@@ -32,7 +47,7 @@ impl CreaseSnapshot {
         snapshot: &'a MultiBufferSnapshot,
     ) -> Option<&'a Crease> {
         let start = snapshot.anchor_before(Point::new(row.0, 0));
-        let mut cursor = self.creases.cursor::<ItemSummary>();
+        let mut cursor = self.creases.cursor::<ItemSummary>(snapshot);
         cursor.seek(&start, Bias::Left, snapshot);
         while let Some(item) = cursor.item() {
             match Ord::cmp(&item.crease.range.start.to_point(snapshot).row, &row.0) {
@@ -56,7 +71,7 @@ impl CreaseSnapshot {
         snapshot: &'a MultiBufferSnapshot,
     ) -> impl '_ + Iterator<Item = &'a Crease> {
         let start = snapshot.anchor_before(Point::new(range.start.0, 0));
-        let mut cursor = self.creases.cursor::<ItemSummary>();
+        let mut cursor = self.creases.cursor::<ItemSummary>(snapshot);
         cursor.seek(&start, Bias::Left, snapshot);
 
         std::iter::from_fn(move || {
@@ -79,7 +94,7 @@ impl CreaseSnapshot {
         &self,
         snapshot: &MultiBufferSnapshot,
     ) -> Vec<(CreaseId, Range<Point>)> {
-        let mut cursor = self.creases.cursor::<ItemSummary>();
+        let mut cursor = self.creases.cursor::<ItemSummary>(snapshot);
         let mut results = Vec::new();
 
         cursor.next(snapshot);
@@ -194,8 +209,8 @@ impl CreaseMap {
     ) -> Vec<CreaseId> {
         let mut new_ids = Vec::new();
         self.snapshot.creases = {
-            let mut new_creases = SumTree::new();
-            let mut cursor = self.snapshot.creases.cursor::<ItemSummary>();
+            let mut new_creases = SumTree::new(snapshot);
+            let mut cursor = self.snapshot.creases.cursor::<ItemSummary>(snapshot);
             for crease in creases {
                 new_creases.append(cursor.slice(&crease.range, Bias::Left, snapshot), snapshot);
 
@@ -227,8 +242,8 @@ impl CreaseMap {
         });
 
         self.snapshot.creases = {
-            let mut new_creases = SumTree::new();
-            let mut cursor = self.snapshot.creases.cursor::<ItemSummary>();
+            let mut new_creases = SumTree::new(snapshot);
+            let mut cursor = self.snapshot.creases.cursor::<ItemSummary>(snapshot);
 
             for (id, range) in removals {
                 new_creases.append(cursor.slice(&range, Bias::Left, snapshot), snapshot);
@@ -264,6 +279,10 @@ impl Default for ItemSummary {
 impl sum_tree::Summary for ItemSummary {
     type Context = MultiBufferSnapshot;
 
+    fn zero(_cx: &Self::Context) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, _snapshot: &MultiBufferSnapshot) {
         self.range = other.range.clone();
     }
@@ -303,7 +322,7 @@ mod test {
         let text = "line1\nline2\nline3\nline4\nline5";
         let buffer = MultiBuffer::build_simple(text, cx);
         let snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
-        let mut crease_map = CreaseMap::default();
+        let mut crease_map = CreaseMap::new(&buffer.read(cx).read(cx));
 
         // Insert creases
         let creases = [
@@ -350,7 +369,7 @@ mod test {
         let text = "line1\nline2\nline3\nline4\nline5\nline6\nline7";
         let buffer = MultiBuffer::build_simple(text, cx);
         let snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
-        let mut crease_map = CreaseMap::default();
+        let mut crease_map = CreaseMap::new(&snapshot);
 
         let creases = [
             Crease::new(

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

@@ -79,7 +79,7 @@ impl FoldPoint {
     }
 
     pub fn to_inlay_point(self, snapshot: &FoldSnapshot) -> InlayPoint {
-        let mut cursor = snapshot.transforms.cursor::<(FoldPoint, InlayPoint)>();
+        let mut cursor = snapshot.transforms.cursor::<(FoldPoint, InlayPoint)>(&());
         cursor.seek(&self, Bias::Right, &());
         let overshoot = self.0 - cursor.start().0 .0;
         InlayPoint(cursor.start().1 .0 + overshoot)
@@ -88,7 +88,7 @@ impl FoldPoint {
     pub fn to_offset(self, snapshot: &FoldSnapshot) -> FoldOffset {
         let mut cursor = snapshot
             .transforms
-            .cursor::<(FoldPoint, TransformSummary)>();
+            .cursor::<(FoldPoint, TransformSummary)>(&());
         cursor.seek(&self, Bias::Right, &());
         let overshoot = self.0 - cursor.start().1.output.lines;
         let mut offset = cursor.start().1.output.len;
@@ -105,6 +105,10 @@ impl FoldPoint {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for FoldPoint {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         self.0 += &summary.output.lines;
     }
@@ -154,8 +158,8 @@ impl<'a> FoldMapWriter<'a> {
         folds.sort_unstable_by(|a, b| sum_tree::SeekTarget::cmp(&a.range, &b.range, buffer));
 
         self.0.snapshot.folds = {
-            let mut new_tree = SumTree::new();
-            let mut cursor = self.0.snapshot.folds.cursor::<FoldRange>();
+            let mut new_tree = SumTree::new(buffer);
+            let mut cursor = self.0.snapshot.folds.cursor::<FoldRange>(buffer);
             for fold in folds {
                 new_tree.append(cursor.slice(&fold.range, Bias::Right, buffer), buffer);
                 new_tree.push(fold, buffer);
@@ -202,8 +206,8 @@ impl<'a> FoldMapWriter<'a> {
         fold_ixs_to_delete.dedup();
 
         self.0.snapshot.folds = {
-            let mut cursor = self.0.snapshot.folds.cursor::<usize>();
-            let mut folds = SumTree::new();
+            let mut cursor = self.0.snapshot.folds.cursor::<usize>(buffer);
+            let mut folds = SumTree::new(buffer);
             for fold_ix in fold_ixs_to_delete {
                 folds.append(cursor.slice(&fold_ix, Bias::Right, buffer), buffer);
                 cursor.next(buffer);
@@ -230,7 +234,7 @@ impl FoldMap {
     pub(crate) fn new(inlay_snapshot: InlaySnapshot) -> (Self, FoldSnapshot) {
         let this = Self {
             snapshot: FoldSnapshot {
-                folds: Default::default(),
+                folds: SumTree::new(&inlay_snapshot.buffer),
                 transforms: SumTree::from_item(
                     Transform {
                         summary: TransformSummary {
@@ -314,8 +318,8 @@ impl FoldMap {
         } else {
             let mut inlay_edits_iter = inlay_edits.iter().cloned().peekable();
 
-            let mut new_transforms = SumTree::<Transform>::new();
-            let mut cursor = self.snapshot.transforms.cursor::<InlayOffset>();
+            let mut new_transforms = SumTree::<Transform>::default();
+            let mut cursor = self.snapshot.transforms.cursor::<InlayOffset>(&());
             cursor.seek(&InlayOffset(0), Bias::Right, &());
 
             while let Some(mut edit) = inlay_edits_iter.next() {
@@ -367,7 +371,10 @@ impl FoldMap {
                 let anchor = inlay_snapshot
                     .buffer
                     .anchor_before(inlay_snapshot.to_buffer_offset(edit.new.start));
-                let mut folds_cursor = self.snapshot.folds.cursor::<FoldRange>();
+                let mut folds_cursor = self
+                    .snapshot
+                    .folds
+                    .cursor::<FoldRange>(&inlay_snapshot.buffer);
                 folds_cursor.seek(
                     &FoldRange(anchor..Anchor::max()),
                     Bias::Left,
@@ -470,8 +477,8 @@ impl FoldMap {
                 let mut old_transforms = self
                     .snapshot
                     .transforms
-                    .cursor::<(InlayOffset, FoldOffset)>();
-                let mut new_transforms = new_transforms.cursor::<(InlayOffset, FoldOffset)>();
+                    .cursor::<(InlayOffset, FoldOffset)>(&());
+                let mut new_transforms = new_transforms.cursor::<(InlayOffset, FoldOffset)>(&());
 
                 for mut edit in inlay_edits {
                     old_transforms.seek(&edit.old.start, Bias::Left, &());
@@ -545,7 +552,7 @@ impl FoldSnapshot {
     pub fn text_summary_for_range(&self, range: Range<FoldPoint>) -> TextSummary {
         let mut summary = TextSummary::default();
 
-        let mut cursor = self.transforms.cursor::<(FoldPoint, InlayPoint)>();
+        let mut cursor = self.transforms.cursor::<(FoldPoint, InlayPoint)>(&());
         cursor.seek(&range.start, Bias::Right, &());
         if let Some(transform) = cursor.item() {
             let start_in_transform = range.start.0 - cursor.start().0 .0;
@@ -594,7 +601,7 @@ impl FoldSnapshot {
     }
 
     pub fn to_fold_point(&self, point: InlayPoint, bias: Bias) -> FoldPoint {
-        let mut cursor = self.transforms.cursor::<(InlayPoint, FoldPoint)>();
+        let mut cursor = self.transforms.cursor::<(InlayPoint, FoldPoint)>(&());
         cursor.seek(&point, Bias::Right, &());
         if cursor.item().map_or(false, |t| t.is_fold()) {
             if bias == Bias::Left || point == cursor.start().0 {
@@ -631,7 +638,7 @@ impl FoldSnapshot {
         }
 
         let fold_point = FoldPoint::new(start_row, 0);
-        let mut cursor = self.transforms.cursor::<(FoldPoint, InlayPoint)>();
+        let mut cursor = self.transforms.cursor::<(FoldPoint, InlayPoint)>(&());
         cursor.seek(&fold_point, Bias::Left, &());
 
         let overshoot = fold_point.0 - cursor.start().0 .0;
@@ -672,7 +679,7 @@ 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>();
+        let mut cursor = self.transforms.cursor::<InlayOffset>(&());
         cursor.seek(&inlay_offset, Bias::Right, &());
         cursor.item().map_or(false, |t| t.placeholder.is_some())
     }
@@ -681,7 +688,7 @@ impl FoldSnapshot {
         let mut inlay_point = self
             .inlay_snapshot
             .to_inlay_point(Point::new(buffer_row.0, 0));
-        let mut cursor = self.transforms.cursor::<InlayPoint>();
+        let mut cursor = self.transforms.cursor::<InlayPoint>(&());
         cursor.seek(&inlay_point, Bias::Right, &());
         loop {
             match cursor.item() {
@@ -711,7 +718,7 @@ impl FoldSnapshot {
         language_aware: bool,
         highlights: Highlights<'a>,
     ) -> FoldChunks<'a> {
-        let mut transform_cursor = self.transforms.cursor::<(FoldOffset, InlayOffset)>();
+        let mut transform_cursor = self.transforms.cursor::<(FoldOffset, InlayOffset)>(&());
         transform_cursor.seek(&range.start, Bias::Right, &());
 
         let inlay_start = {
@@ -766,7 +773,7 @@ impl FoldSnapshot {
     }
 
     pub fn clip_point(&self, point: FoldPoint, bias: Bias) -> FoldPoint {
-        let mut cursor = self.transforms.cursor::<(FoldPoint, InlayPoint)>();
+        let mut cursor = self.transforms.cursor::<(FoldPoint, InlayPoint)>(&());
         cursor.seek(&point, Bias::Right, &());
         if let Some(transform) = cursor.item() {
             let transform_start = cursor.start().0 .0;
@@ -826,7 +833,7 @@ where
     let buffer = &inlay_snapshot.buffer;
     let start = buffer.anchor_before(range.start.to_offset(buffer));
     let end = buffer.anchor_after(range.end.to_offset(buffer));
-    let mut cursor = folds.filter::<_, usize>(move |summary| {
+    let mut cursor = folds.filter::<_, usize>(buffer, move |summary| {
         let start_cmp = start.cmp(&summary.max_end, buffer);
         let end_cmp = end.cmp(&summary.min_start, buffer);
 
@@ -945,6 +952,10 @@ impl sum_tree::Item for Transform {
 impl sum_tree::Summary for TransformSummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, _: &()) {
         self.input += &other.input;
         self.output += &other.output;
@@ -1028,6 +1039,10 @@ impl Default for FoldSummary {
 impl sum_tree::Summary for FoldSummary {
     type Context = MultiBufferSnapshot;
 
+    fn zero(_cx: &MultiBufferSnapshot) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
         if other.min_start.cmp(&self.min_start, buffer) == Ordering::Less {
             self.min_start = other.min_start;
@@ -1052,6 +1067,10 @@ impl sum_tree::Summary for FoldSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, FoldSummary> for FoldRange {
+    fn zero(_cx: &MultiBufferSnapshot) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a FoldSummary, _: &MultiBufferSnapshot) {
         self.0.start = summary.start;
         self.0.end = summary.end;
@@ -1065,6 +1084,10 @@ impl<'a> sum_tree::SeekTarget<'a, FoldSummary, FoldRange> for FoldRange {
 }
 
 impl<'a> sum_tree::Dimension<'a, FoldSummary> for usize {
+    fn zero(_cx: &MultiBufferSnapshot) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a FoldSummary, _: &MultiBufferSnapshot) {
         *self += summary.count;
     }
@@ -1196,7 +1219,7 @@ impl FoldOffset {
     pub fn to_point(self, snapshot: &FoldSnapshot) -> FoldPoint {
         let mut cursor = snapshot
             .transforms
-            .cursor::<(FoldOffset, TransformSummary)>();
+            .cursor::<(FoldOffset, TransformSummary)>(&());
         cursor.seek(&self, Bias::Right, &());
         let overshoot = if cursor.item().map_or(true, |t| t.is_fold()) {
             Point::new(0, (self.0 - cursor.start().0 .0) as u32)
@@ -1210,7 +1233,7 @@ impl FoldOffset {
 
     #[cfg(test)]
     pub fn to_inlay_offset(self, snapshot: &FoldSnapshot) -> InlayOffset {
-        let mut cursor = snapshot.transforms.cursor::<(FoldOffset, InlayOffset)>();
+        let mut cursor = snapshot.transforms.cursor::<(FoldOffset, InlayOffset)>(&());
         cursor.seek(&self, Bias::Right, &());
         let overshoot = self.0 - cursor.start().0 .0;
         InlayOffset(cursor.start().1 .0 + overshoot)
@@ -1240,18 +1263,30 @@ impl Sub for FoldOffset {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for FoldOffset {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         self.0 += &summary.output.len;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayPoint {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         self.0 += &summary.input.lines;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayOffset {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         self.0 += &summary.input.len;
     }

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

@@ -97,6 +97,10 @@ struct TransformSummary {
 impl sum_tree::Summary for TransformSummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, _: &()) {
         self.input += &other.input;
         self.output += &other.output;
@@ -137,6 +141,10 @@ impl SubAssign for InlayOffset {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayOffset {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         self.0 += &summary.output.len;
     }
@@ -162,18 +170,30 @@ impl Sub for InlayPoint {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayPoint {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         self.0 += &summary.output.lines;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for usize {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         *self += &summary.input.len;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for Point {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         *self += &summary.input.lines;
     }
@@ -475,8 +495,8 @@ impl InlayMap {
             (snapshot.clone(), Vec::new())
         } else {
             let mut inlay_edits = Patch::default();
-            let mut new_transforms = SumTree::new();
-            let mut cursor = snapshot.transforms.cursor::<(usize, InlayOffset)>();
+            let mut new_transforms = SumTree::default();
+            let mut cursor = snapshot.transforms.cursor::<(usize, InlayOffset)>(&());
             let mut buffer_edits_iter = buffer_edits.iter().peekable();
             while let Some(buffer_edit) = buffer_edits_iter.next() {
                 new_transforms.append(cursor.slice(&buffer_edit.old.start, Bias::Left, &()), &());
@@ -693,7 +713,7 @@ impl InlaySnapshot {
     pub fn to_point(&self, offset: InlayOffset) -> InlayPoint {
         let mut cursor = self
             .transforms
-            .cursor::<(InlayOffset, (InlayPoint, usize))>();
+            .cursor::<(InlayOffset, (InlayPoint, usize))>(&());
         cursor.seek(&offset, Bias::Right, &());
         let overshoot = offset.0 - cursor.start().0 .0;
         match cursor.item() {
@@ -723,7 +743,7 @@ impl InlaySnapshot {
     pub fn to_offset(&self, point: InlayPoint) -> InlayOffset {
         let mut cursor = self
             .transforms
-            .cursor::<(InlayPoint, (InlayOffset, Point))>();
+            .cursor::<(InlayPoint, (InlayOffset, Point))>(&());
         cursor.seek(&point, Bias::Right, &());
         let overshoot = point.0 - cursor.start().0 .0;
         match cursor.item() {
@@ -741,9 +761,8 @@ impl InlaySnapshot {
             None => self.len(),
         }
     }
-
     pub fn to_buffer_point(&self, point: InlayPoint) -> Point {
-        let mut cursor = self.transforms.cursor::<(InlayPoint, Point)>();
+        let mut cursor = self.transforms.cursor::<(InlayPoint, Point)>(&());
         cursor.seek(&point, Bias::Right, &());
         match cursor.item() {
             Some(Transform::Isomorphic(_)) => {
@@ -754,9 +773,8 @@ impl InlaySnapshot {
             None => self.buffer.max_point(),
         }
     }
-
     pub fn to_buffer_offset(&self, offset: InlayOffset) -> usize {
-        let mut cursor = self.transforms.cursor::<(InlayOffset, usize)>();
+        let mut cursor = self.transforms.cursor::<(InlayOffset, usize)>(&());
         cursor.seek(&offset, Bias::Right, &());
         match cursor.item() {
             Some(Transform::Isomorphic(_)) => {
@@ -769,7 +787,7 @@ impl InlaySnapshot {
     }
 
     pub fn to_inlay_offset(&self, offset: usize) -> InlayOffset {
-        let mut cursor = self.transforms.cursor::<(usize, InlayOffset)>();
+        let mut cursor = self.transforms.cursor::<(usize, InlayOffset)>(&());
         cursor.seek(&offset, Bias::Left, &());
         loop {
             match cursor.item() {
@@ -801,9 +819,8 @@ impl InlaySnapshot {
             }
         }
     }
-
     pub fn to_inlay_point(&self, point: Point) -> InlayPoint {
-        let mut cursor = self.transforms.cursor::<(Point, InlayPoint)>();
+        let mut cursor = self.transforms.cursor::<(Point, InlayPoint)>(&());
         cursor.seek(&point, Bias::Left, &());
         loop {
             match cursor.item() {
@@ -837,7 +854,7 @@ impl InlaySnapshot {
     }
 
     pub fn clip_point(&self, mut point: InlayPoint, mut bias: Bias) -> InlayPoint {
-        let mut cursor = self.transforms.cursor::<(InlayPoint, Point)>();
+        let mut cursor = self.transforms.cursor::<(InlayPoint, Point)>(&());
         cursor.seek(&point, Bias::Left, &());
         loop {
             match cursor.item() {
@@ -934,7 +951,7 @@ impl InlaySnapshot {
     pub fn text_summary_for_range(&self, range: Range<InlayOffset>) -> TextSummary {
         let mut summary = TextSummary::default();
 
-        let mut cursor = self.transforms.cursor::<(InlayOffset, usize)>();
+        let mut cursor = self.transforms.cursor::<(InlayOffset, usize)>(&());
         cursor.seek(&range.start, Bias::Right, &());
 
         let overshoot = range.start.0 - cursor.start().0 .0;
@@ -982,7 +999,7 @@ impl InlaySnapshot {
     }
 
     pub fn buffer_rows(&self, row: u32) -> InlayBufferRows<'_> {
-        let mut cursor = self.transforms.cursor::<(InlayPoint, Point)>();
+        let mut cursor = self.transforms.cursor::<(InlayPoint, Point)>(&());
         let inlay_point = InlayPoint::new(row, 0);
         cursor.seek(&inlay_point, Bias::Left, &());
 
@@ -1024,7 +1041,7 @@ impl InlaySnapshot {
         language_aware: bool,
         highlights: Highlights<'a>,
     ) -> InlayChunks<'a> {
-        let mut cursor = self.transforms.cursor::<(InlayOffset, usize)>();
+        let mut cursor = self.transforms.cursor::<(InlayOffset, usize)>(&());
         cursor.seek(&range.start, Bias::Right, &());
 
         let mut highlight_endpoints = Vec::new();

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

@@ -204,7 +204,7 @@ impl WrapMap {
             }
         } else {
             let old_rows = self.snapshot.transforms.summary().output.lines.row + 1;
-            self.snapshot.transforms = SumTree::new();
+            self.snapshot.transforms = SumTree::default();
             let summary = self.snapshot.tab_snapshot.text_summary();
             if !summary.lines.is_zero() {
                 self.snapshot
@@ -303,7 +303,7 @@ impl WrapMap {
 
 impl WrapSnapshot {
     fn new(tab_snapshot: TabSnapshot) -> Self {
-        let mut transforms = SumTree::new();
+        let mut transforms = SumTree::default();
         let extent = tab_snapshot.text_summary();
         if !extent.lines.is_zero() {
             transforms.push(Transform::isomorphic(extent), &());
@@ -324,7 +324,7 @@ impl WrapSnapshot {
         if tab_edits.is_empty() {
             new_transforms = self.transforms.clone();
         } else {
-            let mut old_cursor = self.transforms.cursor::<TabPoint>();
+            let mut old_cursor = self.transforms.cursor::<TabPoint>(&());
 
             let mut tab_edits_iter = tab_edits.iter().peekable();
             new_transforms =
@@ -424,7 +424,7 @@ impl WrapSnapshot {
             new_transforms = self.transforms.clone();
         } else {
             let mut row_edits = row_edits.into_iter().peekable();
-            let mut old_cursor = self.transforms.cursor::<TabPoint>();
+            let mut old_cursor = self.transforms.cursor::<TabPoint>(&());
 
             new_transforms = old_cursor.slice(
                 &TabPoint::new(row_edits.peek().unwrap().old_rows.start, 0),
@@ -537,8 +537,8 @@ impl WrapSnapshot {
 
     fn compute_edits(&self, tab_edits: &[TabEdit], new_snapshot: &WrapSnapshot) -> Patch<u32> {
         let mut wrap_edits = Vec::new();
-        let mut old_cursor = self.transforms.cursor::<TransformSummary>();
-        let mut new_cursor = new_snapshot.transforms.cursor::<TransformSummary>();
+        let mut old_cursor = self.transforms.cursor::<TransformSummary>(&());
+        let mut new_cursor = new_snapshot.transforms.cursor::<TransformSummary>(&());
         for mut tab_edit in tab_edits.iter().cloned() {
             tab_edit.old.start.0.column = 0;
             tab_edit.old.end.0 += Point::new(1, 0);
@@ -579,7 +579,7 @@ impl WrapSnapshot {
     ) -> WrapChunks<'a> {
         let output_start = WrapPoint::new(rows.start, 0);
         let output_end = WrapPoint::new(rows.end, 0);
-        let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>();
+        let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
         transforms.seek(&output_start, Bias::Right, &());
         let mut input_start = TabPoint(transforms.start().1 .0);
         if transforms.item().map_or(false, |t| t.is_isomorphic()) {
@@ -606,7 +606,7 @@ impl WrapSnapshot {
     }
 
     pub fn line_len(&self, row: u32) -> u32 {
-        let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>();
+        let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
         cursor.seek(&WrapPoint::new(row + 1, 0), Bias::Left, &());
         if cursor
             .item()
@@ -626,7 +626,7 @@ impl WrapSnapshot {
     }
 
     pub fn soft_wrap_indent(&self, row: u32) -> Option<u32> {
-        let mut cursor = self.transforms.cursor::<WrapPoint>();
+        let mut cursor = self.transforms.cursor::<WrapPoint>(&());
         cursor.seek(&WrapPoint::new(row + 1, 0), Bias::Right, &());
         cursor.item().and_then(|transform| {
             if transform.is_isomorphic() {
@@ -642,7 +642,7 @@ impl WrapSnapshot {
     }
 
     pub fn buffer_rows(&self, start_row: u32) -> WrapBufferRows {
-        let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>();
+        let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
         transforms.seek(&WrapPoint::new(start_row, 0), Bias::Left, &());
         let mut input_row = transforms.start().1.row();
         if transforms.item().map_or(false, |t| t.is_isomorphic()) {
@@ -662,7 +662,7 @@ impl WrapSnapshot {
     }
 
     pub fn to_tab_point(&self, point: WrapPoint) -> TabPoint {
-        let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>();
+        let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
         cursor.seek(&point, Bias::Right, &());
         let mut tab_point = cursor.start().1 .0;
         if cursor.item().map_or(false, |t| t.is_isomorphic()) {
@@ -680,14 +680,14 @@ impl WrapSnapshot {
     }
 
     pub fn tab_point_to_wrap_point(&self, point: TabPoint) -> WrapPoint {
-        let mut cursor = self.transforms.cursor::<(TabPoint, WrapPoint)>();
+        let mut cursor = self.transforms.cursor::<(TabPoint, WrapPoint)>(&());
         cursor.seek(&point, Bias::Right, &());
         WrapPoint(cursor.start().1 .0 + (point.0 - cursor.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>();
+            let mut cursor = self.transforms.cursor::<WrapPoint>(&());
             cursor.seek(&point, Bias::Right, &());
             if cursor.item().map_or(false, |t| !t.is_isomorphic()) {
                 point = *cursor.start();
@@ -705,7 +705,7 @@ impl WrapSnapshot {
 
         *point.column_mut() = 0;
 
-        let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>();
+        let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
         cursor.seek(&point, Bias::Right, &());
         if cursor.item().is_none() {
             cursor.prev(&());
@@ -725,7 +725,7 @@ impl WrapSnapshot {
     pub fn next_row_boundary(&self, mut point: WrapPoint) -> Option<u32> {
         point.0 += Point::new(1, 0);
 
-        let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>();
+        let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
         cursor.seek(&point, Bias::Right, &());
         while let Some(transform) = cursor.item() {
             if transform.is_isomorphic() && cursor.start().1.column() == 0 {
@@ -747,7 +747,7 @@ impl WrapSnapshot {
             );
 
             {
-                let mut transforms = self.transforms.cursor::<()>().peekable();
+                let mut transforms = self.transforms.cursor::<()>(&()).peekable();
                 while let Some(transform) = transforms.next() {
                     if let Some(next_transform) = transforms.peek() {
                         assert!(transform.is_isomorphic() != next_transform.is_isomorphic());
@@ -982,6 +982,10 @@ impl WrapPoint {
 impl sum_tree::Summary for TransformSummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, _: &()) {
         self.input += &other.input;
         self.output += &other.output;
@@ -989,6 +993,10 @@ impl sum_tree::Summary for TransformSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for TabPoint {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         self.0 += summary.input.lines;
     }
@@ -1001,6 +1009,10 @@ impl<'a> sum_tree::SeekTarget<'a, TransformSummary, TransformSummary> for TabPoi
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for WrapPoint {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
         self.0 += summary.output.lines;
     }

crates/editor/src/git/blame.rs 🔗

@@ -37,12 +37,20 @@ impl sum_tree::Item for GitBlameEntry {
 impl sum_tree::Summary for GitBlameEntrySummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _cx: &()) {
         self.rows += summary.rows;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, GitBlameEntrySummary> for u32 {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a GitBlameEntrySummary, _cx: &()) {
         *self += summary.rows;
     }
@@ -191,7 +199,7 @@ impl GitBlame {
     ) -> impl 'a + Iterator<Item = Option<BlameEntry>> {
         self.sync(cx);
 
-        let mut cursor = self.entries.cursor::<u32>();
+        let mut cursor = self.entries.cursor::<u32>(&());
         rows.into_iter().map(move |row| {
             let row = row?;
             cursor.seek_forward(&row.0, Bias::Right, &());
@@ -249,8 +257,8 @@ impl GitBlame {
             })
             .peekable();
 
-        let mut new_entries = SumTree::new();
-        let mut cursor = self.entries.cursor::<u32>();
+        let mut new_entries = SumTree::default();
+        let mut cursor = self.entries.cursor::<u32>(&());
 
         while let Some(mut edit) = row_edits.next() {
             while let Some(next_edit) = row_edits.peek() {

crates/git/src/diff.rs 🔗

@@ -48,6 +48,10 @@ pub struct DiffHunkSummary {
 impl sum_tree::Summary for DiffHunkSummary {
     type Context = text::BufferSnapshot;
 
+    fn zero(_cx: &Self::Context) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
         self.buffer_range.start = self
             .buffer_range
@@ -63,17 +67,11 @@ pub struct BufferDiff {
     tree: SumTree<DiffHunk<Anchor>>,
 }
 
-impl Default for BufferDiff {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
 impl BufferDiff {
-    pub fn new() -> BufferDiff {
+    pub fn new(buffer: &BufferSnapshot) -> BufferDiff {
         BufferDiff {
             last_buffer_version: None,
-            tree: SumTree::new(),
+            tree: SumTree::new(buffer),
         }
     }
 
@@ -97,11 +95,13 @@ impl BufferDiff {
         range: Range<Anchor>,
         buffer: &'a BufferSnapshot,
     ) -> impl 'a + Iterator<Item = DiffHunk<u32>> {
-        let mut cursor = self.tree.filter::<_, DiffHunkSummary>(move |summary| {
-            let before_start = summary.buffer_range.end.cmp(&range.start, buffer).is_lt();
-            let after_end = summary.buffer_range.start.cmp(&range.end, buffer).is_gt();
-            !before_start && !after_end
-        });
+        let mut cursor = self
+            .tree
+            .filter::<_, DiffHunkSummary>(buffer, move |summary| {
+                let before_start = summary.buffer_range.end.cmp(&range.start, buffer).is_lt();
+                let after_end = summary.buffer_range.start.cmp(&range.end, buffer).is_gt();
+                !before_start && !after_end
+            });
 
         let anchor_iter = std::iter::from_fn(move || {
             cursor.next(buffer);
@@ -142,11 +142,13 @@ impl BufferDiff {
         range: Range<Anchor>,
         buffer: &'a BufferSnapshot,
     ) -> impl 'a + Iterator<Item = DiffHunk<u32>> {
-        let mut cursor = self.tree.filter::<_, DiffHunkSummary>(move |summary| {
-            let before_start = summary.buffer_range.end.cmp(&range.start, buffer).is_lt();
-            let after_end = summary.buffer_range.start.cmp(&range.end, buffer).is_gt();
-            !before_start && !after_end
-        });
+        let mut cursor = self
+            .tree
+            .filter::<_, DiffHunkSummary>(buffer, move |summary| {
+                let before_start = summary.buffer_range.end.cmp(&range.start, buffer).is_lt();
+                let after_end = summary.buffer_range.start.cmp(&range.end, buffer).is_gt();
+                !before_start && !after_end
+            });
 
         std::iter::from_fn(move || {
             cursor.prev(buffer);
@@ -171,11 +173,11 @@ impl BufferDiff {
     #[cfg(test)]
     fn clear(&mut self, buffer: &text::BufferSnapshot) {
         self.last_buffer_version = Some(buffer.version().clone());
-        self.tree = SumTree::new();
+        self.tree = SumTree::new(buffer);
     }
 
     pub async fn update(&mut self, diff_base: &Rope, buffer: &text::BufferSnapshot) {
-        let mut tree = SumTree::new();
+        let mut tree = SumTree::new(buffer);
 
         let diff_base_text = diff_base.to_string();
         let buffer_text = buffer.as_rope().to_string();
@@ -351,7 +353,7 @@ mod tests {
         .unindent();
 
         let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), buffer_text);
-        let mut diff = BufferDiff::new();
+        let mut diff = BufferDiff::new(&buffer);
         smol::block_on(diff.update(&diff_base_rope, &buffer));
         assert_hunks(
             diff.hunks(&buffer),
@@ -412,7 +414,7 @@ mod tests {
         .unindent();
 
         let buffer = Buffer::new(0, BufferId::new(1).unwrap(), buffer_text);
-        let mut diff = BufferDiff::new();
+        let mut diff = BufferDiff::new(&buffer);
         smol::block_on(diff.update(&diff_base_rope, &buffer));
         assert_eq!(diff.hunks(&buffer).count(), 8);
 

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

@@ -181,7 +181,7 @@ impl ListState {
             last_layout_bounds: None,
             last_padding: None,
             render_item: Box::new(render_item),
-            items: SumTree::new(),
+            items: SumTree::default(),
             logical_scroll_top: None,
             alignment,
             overdraw,
@@ -228,7 +228,7 @@ impl ListState {
     ) {
         let state = &mut *self.0.borrow_mut();
 
-        let mut old_items = state.items.cursor::<Count>();
+        let mut old_items = state.items.cursor::<Count>(&());
         let mut new_items = old_items.slice(&Count(old_range.start), Bias::Right, &());
         old_items.seek_forward(&Count(old_range.end), Bias::Right, &());
 
@@ -297,7 +297,7 @@ impl ListState {
             scroll_top.item_ix = ix;
             scroll_top.offset_in_item = px(0.);
         } else {
-            let mut cursor = state.items.cursor::<ListItemSummary>();
+            let mut cursor = state.items.cursor::<ListItemSummary>(&());
             cursor.seek(&Count(ix + 1), Bias::Right, &());
             let bottom = cursor.start().height + padding.top;
             let goal_top = px(0.).max(bottom - height + padding.bottom);
@@ -326,7 +326,7 @@ impl ListState {
             return None;
         }
 
-        let mut cursor = state.items.cursor::<(Count, Height)>();
+        let mut cursor = state.items.cursor::<(Count, Height)>(&());
         cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
 
         let scroll_top = cursor.start().1 .0 + scroll_top.offset_in_item;
@@ -348,7 +348,7 @@ impl ListState {
 
 impl StateInner {
     fn visible_range(&self, height: Pixels, scroll_top: &ListOffset) -> Range<usize> {
-        let mut cursor = self.items.cursor::<ListItemSummary>();
+        let mut cursor = self.items.cursor::<ListItemSummary>(&());
         cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
         let start_y = cursor.start().height + scroll_top.offset_in_item;
         cursor.seek_forward(&Height(start_y + height), Bias::Left, &());
@@ -378,7 +378,7 @@ 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>();
+            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;
@@ -418,7 +418,7 @@ impl StateInner {
     }
 
     fn scroll_top(&self, logical_scroll_top: &ListOffset) -> Pixels {
-        let mut cursor = self.items.cursor::<ListItemSummary>();
+        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
     }
@@ -445,7 +445,7 @@ impl StateInner {
             AvailableSpace::MinContent,
         );
 
-        let mut cursor = old_items.cursor::<Count>();
+        let mut cursor = old_items.cursor::<Count>(&());
 
         // Render items after the scroll top, including those in the trailing overdraw
         cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
@@ -560,7 +560,7 @@ impl StateInner {
         }
 
         let measured_range = cursor.start().0..(cursor.start().0 + measured_items.len());
-        let mut cursor = old_items.cursor::<Count>();
+        let mut cursor = old_items.cursor::<Count>(&());
         let mut new_items = cursor.slice(&Count(measured_range.start), Bias::Right, &());
         new_items.extend(measured_items, &());
         cursor.seek(&Count(measured_range.end), Bias::Right, &());
@@ -573,7 +573,7 @@ impl StateInner {
         if !rendered_focused_item {
             let mut cursor = self
                 .items
-                .filter::<_, Count>(|summary| summary.has_focus_handles);
+                .filter::<_, Count>(&(), |summary| summary.has_focus_handles);
             cursor.next(&());
             while let Some(item) = cursor.item() {
                 if item.contains_focused(cx) {
@@ -629,7 +629,7 @@ impl StateInner {
                                     offset_in_item: autoscroll_bounds.top() - item_origin.y,
                                 });
                             } else if autoscroll_bounds.bottom() > bounds.bottom() {
-                                let mut cursor = self.items.cursor::<Count>();
+                                let mut cursor = self.items.cursor::<Count>(&());
                                 cursor.seek(&Count(item.index), Bias::Right, &());
                                 let mut height = bounds.size.height - padding.top - padding.bottom;
 
@@ -883,6 +883,10 @@ impl sum_tree::Item for ListItem {
 impl sum_tree::Summary for ListItemSummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &()) {
         self.count += summary.count;
         self.rendered_count += summary.rendered_count;
@@ -893,12 +897,20 @@ impl sum_tree::Summary for ListItemSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, ListItemSummary> for Count {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ListItemSummary, _: &()) {
         self.0 += summary.count;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, ListItemSummary> for Height {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ListItemSummary, _: &()) {
         self.0 += summary.height;
     }

crates/language/src/buffer.rs 🔗

@@ -722,7 +722,9 @@ impl Buffer {
         capability: Capability,
     ) -> Self {
         let saved_mtime = file.as_ref().and_then(|file| file.mtime());
-
+        let snapshot = buffer.snapshot();
+        let git_diff = git::diff::BufferDiff::new(&snapshot);
+        let syntax_map = Mutex::new(SyntaxMap::new(&snapshot));
         Self {
             saved_mtime,
             saved_version: buffer.version(),
@@ -739,10 +741,10 @@ impl Buffer {
                 })
                 .map(Rope::from),
             diff_base_version: 0,
-            git_diff: git::diff::BufferDiff::new(),
+            git_diff,
             file,
             capability,
-            syntax_map: Mutex::new(SyntaxMap::new()),
+            syntax_map,
             parsing_in_background: false,
             non_text_state_update_count: 0,
             sync_parse_timeout: Duration::from_millis(1),
@@ -809,7 +811,7 @@ impl Buffer {
     /// Assign a language to the buffer.
     pub fn set_language(&mut self, language: Option<Arc<Language>>, cx: &mut ModelContext<Self>) {
         self.non_text_state_update_count += 1;
-        self.syntax_map.lock().clear();
+        self.syntax_map.lock().clear(&self.text);
         self.language = language;
         self.reparse(cx);
         cx.emit(BufferEvent::LanguageChanged);

crates/language/src/diagnostic_set.rs 🔗

@@ -15,7 +15,7 @@ use text::{Anchor, FromAnchor, PointUtf16, ToOffset};
 /// The diagnostics are stored in a [`SumTree`], which allows this struct
 /// to be cheaply copied, and allows for efficient retrieval of the
 /// diagnostics that intersect a given range of the buffer.
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug)]
 pub struct DiagnosticSet {
     diagnostics: SumTree<DiagnosticEntry<Anchor>>,
 }
@@ -135,7 +135,7 @@ impl DiagnosticSet {
     {
         let end_bias = if inclusive { Bias::Right } else { Bias::Left };
         let range = buffer.anchor_before(range.start)..buffer.anchor_at(range.end, end_bias);
-        let mut cursor = self.diagnostics.filter::<_, ()>({
+        let mut cursor = self.diagnostics.filter::<_, ()>(buffer, {
             move |summary: &Summary| {
                 let start_cmp = range.start.cmp(&summary.max_end, buffer);
                 let end_cmp = range.end.cmp(&summary.min_start, buffer);
@@ -261,6 +261,10 @@ impl Default for Summary {
 impl sum_tree::Summary for Summary {
     type Context = text::BufferSnapshot;
 
+    fn zero(_cx: &Self::Context) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
         if other.min_start.cmp(&self.min_start, buffer).is_lt() {
             self.min_start = other.min_start;

crates/language/src/syntax_map.rs 🔗

@@ -18,13 +18,12 @@ use sum_tree::{Bias, SeekTarget, SumTree};
 use text::{Anchor, BufferSnapshot, OffsetRangeExt, Point, Rope, ToOffset, ToPoint};
 use tree_sitter::{Node, Query, QueryCapture, QueryCaptures, QueryCursor, QueryMatches, Tree};
 
-#[derive(Default)]
 pub struct SyntaxMap {
     snapshot: SyntaxSnapshot,
     language_registry: Option<Arc<LanguageRegistry>>,
 }
 
-#[derive(Clone, Default)]
+#[derive(Clone)]
 pub struct SyntaxSnapshot {
     layers: SumTree<SyntaxLayerEntry>,
     parsed_version: clock::Global,
@@ -212,8 +211,11 @@ struct ByteChunks<'a>(text::Chunks<'a>);
 pub(crate) struct QueryCursorHandle(Option<QueryCursor>);
 
 impl SyntaxMap {
-    pub fn new() -> Self {
-        Self::default()
+    pub fn new(text: &BufferSnapshot) -> Self {
+        Self {
+            snapshot: SyntaxSnapshot::new(text),
+            language_registry: None,
+        }
     }
 
     pub fn set_language_registry(&mut self, registry: Arc<LanguageRegistry>) {
@@ -242,12 +244,21 @@ impl SyntaxMap {
         self.snapshot = snapshot;
     }
 
-    pub fn clear(&mut self) {
-        self.snapshot = SyntaxSnapshot::default();
+    pub fn clear(&mut self, text: &BufferSnapshot) {
+        self.snapshot = SyntaxSnapshot::new(text);
     }
 }
 
 impl SyntaxSnapshot {
+    fn new(text: &BufferSnapshot) -> Self {
+        Self {
+            layers: SumTree::new(text),
+            parsed_version: clock::Global::default(),
+            interpolated_version: clock::Global::default(),
+            language_registry_version: 0,
+        }
+    }
+
     pub fn is_empty(&self) -> bool {
         self.layers.is_empty()
     }
@@ -262,10 +273,10 @@ impl SyntaxSnapshot {
             return;
         }
 
-        let mut layers = SumTree::new();
+        let mut layers = SumTree::new(text);
         let mut first_edit_ix_for_depth = 0;
         let mut prev_depth = 0;
-        let mut cursor = self.layers.cursor::<SyntaxLayerSummary>();
+        let mut cursor = self.layers.cursor::<SyntaxLayerSummary>(text);
         cursor.next(text);
 
         'outer: loop {
@@ -388,7 +399,7 @@ impl SyntaxSnapshot {
                 let mut resolved_injection_ranges = Vec::new();
                 let mut cursor = self
                     .layers
-                    .filter::<_, ()>(|summary| summary.contains_unknown_injections);
+                    .filter::<_, ()>(text, |summary| summary.contains_unknown_injections);
                 cursor.next(text);
                 while let Some(layer) = cursor.item() {
                     let SyntaxLayerContent::Pending { language_name } = &layer.content else {
@@ -430,9 +441,9 @@ impl SyntaxSnapshot {
         log::trace!("reparse. invalidated ranges:{:?}", invalidated_ranges);
 
         let max_depth = self.layers.summary().max_depth;
-        let mut cursor = self.layers.cursor::<SyntaxLayerSummary>();
+        let mut cursor = self.layers.cursor::<SyntaxLayerSummary>(text);
         cursor.next(text);
-        let mut layers = SumTree::new();
+        let mut layers = SumTree::new(text);
 
         let mut changed_regions = ChangeRegionSet::default();
         let mut queue = BinaryHeap::new();
@@ -823,7 +834,7 @@ impl SyntaxSnapshot {
         let start = buffer.anchor_before(start_offset);
         let end = buffer.anchor_after(end_offset);
 
-        let mut cursor = self.layers.filter::<_, ()>(move |summary| {
+        let mut cursor = self.layers.filter::<_, ()>(buffer, move |summary| {
             if summary.max_depth > summary.min_depth {
                 true
             } else {
@@ -1666,6 +1677,10 @@ impl Default for SyntaxLayerSummary {
 impl sum_tree::Summary for SyntaxLayerSummary {
     type Context = BufferSnapshot;
 
+    fn zero(_cx: &BufferSnapshot) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
         if other.max_depth > self.max_depth {
             self.max_depth = other.max_depth;

crates/language/src/syntax_map/syntax_map_tests.rs 🔗

@@ -103,7 +103,7 @@ fn test_syntax_map_layers_for_range(cx: &mut AppContext) {
         .unindent(),
     );
 
-    let mut syntax_map = SyntaxMap::new();
+    let mut syntax_map = SyntaxMap::new(&buffer);
     syntax_map.set_language_registry(registry.clone());
     syntax_map.reparse(language.clone(), &buffer);
 
@@ -202,7 +202,7 @@ fn test_dynamic_language_injection(cx: &mut AppContext) {
         .unindent(),
     );
 
-    let mut syntax_map = SyntaxMap::new();
+    let mut syntax_map = SyntaxMap::new(&buffer);
     syntax_map.set_language_registry(registry.clone());
     syntax_map.reparse(markdown.clone(), &buffer);
     syntax_map.reparse(markdown_inline.clone(), &buffer);
@@ -897,11 +897,11 @@ fn test_random_edits(
 
     let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), text);
 
-    let mut syntax_map = SyntaxMap::new();
+    let mut syntax_map = SyntaxMap::new(&buffer);
     syntax_map.set_language_registry(registry.clone());
     syntax_map.reparse(language.clone(), &buffer);
 
-    let mut reference_syntax_map = SyntaxMap::new();
+    let mut reference_syntax_map = SyntaxMap::new(&buffer);
     reference_syntax_map.set_language_registry(registry.clone());
 
     log::info!("initial text:\n{}", buffer.text());
@@ -918,7 +918,7 @@ fn test_random_edits(
 
         syntax_map.reparse(language.clone(), &buffer);
 
-        reference_syntax_map.clear();
+        reference_syntax_map.clear(&buffer);
         reference_syntax_map.reparse(language.clone(), &buffer);
     }
 
@@ -931,7 +931,7 @@ fn test_random_edits(
         syntax_map.interpolate(&buffer);
         syntax_map.reparse(language.clone(), &buffer);
 
-        reference_syntax_map.clear();
+        reference_syntax_map.clear(&buffer);
         reference_syntax_map.reparse(language.clone(), &buffer);
         assert_eq!(
             syntax_map.layers(&buffer).len(),
@@ -1082,7 +1082,7 @@ fn test_edit_sequence(
         .unwrap();
     let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), Default::default());
 
-    let mut mutated_syntax_map = SyntaxMap::new();
+    let mut mutated_syntax_map = SyntaxMap::new(&buffer);
     mutated_syntax_map.set_language_registry(registry.clone());
     mutated_syntax_map.reparse(language.clone(), &buffer);
 
@@ -1097,7 +1097,7 @@ fn test_edit_sequence(
 
         // Create a second syntax map from scratch
         log::info!("fresh parse {i}: {marked_string:?}");
-        let mut reference_syntax_map = SyntaxMap::new();
+        let mut reference_syntax_map = SyntaxMap::new(&buffer);
         reference_syntax_map.set_language_registry(registry.clone());
         reference_syntax_map.reparse(language.clone(), &buffer);
 

crates/multi_buffer/src/multi_buffer.rs 🔗

@@ -561,7 +561,7 @@ impl MultiBuffer {
         }
         let mut buffer_edits: HashMap<BufferId, Vec<BufferEdit>> = Default::default();
         let mut edited_excerpt_ids = Vec::new();
-        let mut cursor = snapshot.excerpts.cursor::<usize>();
+        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
         for (ix, (range, new_text)) in edits.enumerate() {
             let new_text: Arc<str> = new_text.into();
             let original_indent_column = original_indent_columns.get(ix).copied().unwrap_or(0);
@@ -841,7 +841,7 @@ impl MultiBuffer {
         let mut ranges = Vec::new();
         let snapshot = self.read(cx);
         let buffers = self.buffers.borrow();
-        let mut cursor = snapshot.excerpts.cursor::<ExcerptSummary>();
+        let mut cursor = snapshot.excerpts.cursor::<ExcerptSummary>(&());
 
         for (buffer_id, buffer_transaction) in &transaction.buffer_transactions {
             let Some(buffer_state) = buffers.get(buffer_id) else {
@@ -957,7 +957,7 @@ impl MultiBuffer {
         let mut selections_by_buffer: HashMap<BufferId, Vec<Selection<text::Anchor>>> =
             Default::default();
         let snapshot = self.read(cx);
-        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>();
+        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>(&());
         for selection in selections {
             let start_locator = snapshot.excerpt_locator_for_id(selection.start.excerpt_id);
             let end_locator = snapshot.excerpt_locator_for_id(selection.end.excerpt_id);
@@ -1281,7 +1281,7 @@ impl MultiBuffer {
 
         let mut prev_locator = snapshot.excerpt_locator_for_id(prev_excerpt_id).clone();
         let mut new_excerpt_ids = mem::take(&mut snapshot.excerpt_ids);
-        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>();
+        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>(&());
         let mut new_excerpts = cursor.slice(&prev_locator, Bias::Right, &());
         prev_locator = cursor.start().unwrap_or(Locator::min_ref()).clone();
 
@@ -1388,7 +1388,7 @@ impl MultiBuffer {
         let mut excerpts = Vec::new();
         let snapshot = self.read(cx);
         let buffers = self.buffers.borrow();
-        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>();
+        let mut cursor = snapshot.excerpts.cursor::<Option<&Locator>>(&());
         for locator in buffers
             .get(&buffer.read(cx).remote_id())
             .map(|state| &state.excerpts)
@@ -1432,7 +1432,7 @@ impl MultiBuffer {
         let snapshot = self.read(cx);
         let position = position.to_offset(&snapshot);
 
-        let mut cursor = snapshot.excerpts.cursor::<usize>();
+        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
         cursor.seek(&position, Bias::Right, &());
         cursor
             .item()
@@ -1459,7 +1459,7 @@ impl MultiBuffer {
     ) -> Option<(Model<Buffer>, usize, ExcerptId)> {
         let snapshot = self.read(cx);
         let offset = point.to_offset(&snapshot);
-        let mut cursor = snapshot.excerpts.cursor::<usize>();
+        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
         cursor.seek(&offset, Bias::Right, &());
         if cursor.item().is_none() {
             cursor.prev(&());
@@ -1482,7 +1482,7 @@ impl MultiBuffer {
     ) -> Option<(Model<Buffer>, Point, ExcerptId)> {
         let snapshot = self.read(cx);
         let point = point.to_point(&snapshot);
-        let mut cursor = snapshot.excerpts.cursor::<Point>();
+        let mut cursor = snapshot.excerpts.cursor::<Point>(&());
         cursor.seek(&point, Bias::Right, &());
         if cursor.item().is_none() {
             cursor.prev(&());
@@ -1507,7 +1507,7 @@ impl MultiBuffer {
         let end = range.end.to_offset(&snapshot);
 
         let mut result = Vec::new();
-        let mut cursor = snapshot.excerpts.cursor::<usize>();
+        let mut cursor = snapshot.excerpts.cursor::<usize>(&());
         cursor.seek(&start, Bias::Right, &());
         if cursor.item().is_none() {
             cursor.prev(&());
@@ -1546,8 +1546,8 @@ impl MultiBuffer {
 
         let mut buffers = self.buffers.borrow_mut();
         let mut snapshot = self.snapshot.borrow_mut();
-        let mut new_excerpts = SumTree::new();
-        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>();
+        let mut new_excerpts = SumTree::default();
+        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
         let mut edits = Vec::new();
         let mut excerpt_ids = ids.iter().copied().peekable();
 
@@ -1801,8 +1801,8 @@ impl MultiBuffer {
         let ids = ids.into_iter().collect::<Vec<_>>();
         let snapshot = self.snapshot(cx);
         let locators = snapshot.excerpt_locators_for_ids(ids.iter().copied());
-        let mut new_excerpts = SumTree::new();
-        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>();
+        let mut new_excerpts = SumTree::default();
+        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
         let mut edits = Vec::<Edit<usize>>::new();
 
         for locator in &locators {
@@ -1927,8 +1927,8 @@ impl MultiBuffer {
         excerpts_to_edit.sort_unstable_by_key(|(locator, _, _)| *locator);
 
         let mut edits = Vec::new();
-        let mut new_excerpts = SumTree::new();
-        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>();
+        let mut new_excerpts = SumTree::default();
+        let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>(&());
 
         for (locator, buffer, buffer_edited) in excerpts_to_edit {
             new_excerpts.append(cursor.slice(&Some(locator), Bias::Left, &()), &());
@@ -2230,7 +2230,7 @@ impl MultiBufferSnapshot {
 
     pub fn reversed_chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
         let mut offset = position.to_offset(self);
-        let mut cursor = self.excerpts.cursor::<usize>();
+        let mut cursor = self.excerpts.cursor::<usize>(&());
         cursor.seek(&offset, Bias::Left, &());
         let mut excerpt_chunks = cursor.item().map(|excerpt| {
             let end_before_footer = cursor.start() + excerpt.text_summary.len;
@@ -2357,7 +2357,7 @@ impl MultiBufferSnapshot {
             return buffer.clip_offset(offset, bias);
         }
 
-        let mut cursor = self.excerpts.cursor::<usize>();
+        let mut cursor = self.excerpts.cursor::<usize>(&());
         cursor.seek(&offset, Bias::Right, &());
         let overshoot = if let Some(excerpt) = cursor.item() {
             let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
@@ -2376,7 +2376,7 @@ impl MultiBufferSnapshot {
             return buffer.clip_point(point, bias);
         }
 
-        let mut cursor = self.excerpts.cursor::<Point>();
+        let mut cursor = self.excerpts.cursor::<Point>(&());
         cursor.seek(&point, Bias::Right, &());
         let overshoot = if let Some(excerpt) = cursor.item() {
             let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
@@ -2395,7 +2395,7 @@ impl MultiBufferSnapshot {
             return buffer.clip_offset_utf16(offset, bias);
         }
 
-        let mut cursor = self.excerpts.cursor::<OffsetUtf16>();
+        let mut cursor = self.excerpts.cursor::<OffsetUtf16>(&());
         cursor.seek(&offset, Bias::Right, &());
         let overshoot = if let Some(excerpt) = cursor.item() {
             let excerpt_start = excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
@@ -2414,7 +2414,7 @@ impl MultiBufferSnapshot {
             return buffer.clip_point_utf16(point, bias);
         }
 
-        let mut cursor = self.excerpts.cursor::<PointUtf16>();
+        let mut cursor = self.excerpts.cursor::<PointUtf16>(&());
         cursor.seek(&point.0, Bias::Right, &());
         let overshoot = if let Some(excerpt) = cursor.item() {
             let excerpt_start = excerpt
@@ -2432,7 +2432,7 @@ impl MultiBufferSnapshot {
 
     pub fn bytes_in_range<T: ToOffset>(&self, range: Range<T>) -> MultiBufferBytes {
         let range = range.start.to_offset(self)..range.end.to_offset(self);
-        let mut excerpts = self.excerpts.cursor::<usize>();
+        let mut excerpts = self.excerpts.cursor::<usize>(&());
         excerpts.seek(&range.start, Bias::Right, &());
 
         let mut chunk = &[][..];
@@ -2457,7 +2457,7 @@ impl MultiBufferSnapshot {
         range: Range<T>,
     ) -> ReversedMultiBufferBytes {
         let range = range.start.to_offset(self)..range.end.to_offset(self);
-        let mut excerpts = self.excerpts.cursor::<usize>();
+        let mut excerpts = self.excerpts.cursor::<usize>(&());
         excerpts.seek(&range.end, Bias::Left, &());
 
         let mut chunk = &[][..];
@@ -2482,7 +2482,7 @@ impl MultiBufferSnapshot {
     pub fn buffer_rows(&self, start_row: MultiBufferRow) -> MultiBufferRows {
         let mut result = MultiBufferRows {
             buffer_row_range: 0..0,
-            excerpts: self.excerpts.cursor(),
+            excerpts: self.excerpts.cursor(&()),
         };
         result.seek(start_row);
         result
@@ -2492,7 +2492,7 @@ impl MultiBufferSnapshot {
         let range = range.start.to_offset(self)..range.end.to_offset(self);
         let mut chunks = MultiBufferChunks {
             range: range.clone(),
-            excerpts: self.excerpts.cursor(),
+            excerpts: self.excerpts.cursor(&()),
             excerpt_chunks: None,
             language_aware,
         };
@@ -2505,7 +2505,7 @@ impl MultiBufferSnapshot {
             return buffer.offset_to_point(offset);
         }
 
-        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
+        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
         cursor.seek(&offset, Bias::Right, &());
         if let Some(excerpt) = cursor.item() {
             let (start_offset, start_point) = cursor.start();
@@ -2526,7 +2526,7 @@ impl MultiBufferSnapshot {
             return buffer.offset_to_point_utf16(offset);
         }
 
-        let mut cursor = self.excerpts.cursor::<(usize, PointUtf16)>();
+        let mut cursor = self.excerpts.cursor::<(usize, PointUtf16)>(&());
         cursor.seek(&offset, Bias::Right, &());
         if let Some(excerpt) = cursor.item() {
             let (start_offset, start_point) = cursor.start();
@@ -2547,7 +2547,7 @@ impl MultiBufferSnapshot {
             return buffer.point_to_point_utf16(point);
         }
 
-        let mut cursor = self.excerpts.cursor::<(Point, PointUtf16)>();
+        let mut cursor = self.excerpts.cursor::<(Point, PointUtf16)>(&());
         cursor.seek(&point, Bias::Right, &());
         if let Some(excerpt) = cursor.item() {
             let (start_offset, start_point) = cursor.start();
@@ -2569,7 +2569,7 @@ impl MultiBufferSnapshot {
             return buffer.point_to_offset(point);
         }
 
-        let mut cursor = self.excerpts.cursor::<(Point, usize)>();
+        let mut cursor = self.excerpts.cursor::<(Point, usize)>(&());
         cursor.seek(&point, Bias::Right, &());
         if let Some(excerpt) = cursor.item() {
             let (start_point, start_offset) = cursor.start();
@@ -2590,7 +2590,7 @@ impl MultiBufferSnapshot {
             return buffer.offset_utf16_to_offset(offset_utf16);
         }
 
-        let mut cursor = self.excerpts.cursor::<(OffsetUtf16, usize)>();
+        let mut cursor = self.excerpts.cursor::<(OffsetUtf16, usize)>(&());
         cursor.seek(&offset_utf16, Bias::Right, &());
         if let Some(excerpt) = cursor.item() {
             let (start_offset_utf16, start_offset) = cursor.start();
@@ -2612,7 +2612,7 @@ impl MultiBufferSnapshot {
             return buffer.offset_to_offset_utf16(offset);
         }
 
-        let mut cursor = self.excerpts.cursor::<(usize, OffsetUtf16)>();
+        let mut cursor = self.excerpts.cursor::<(usize, OffsetUtf16)>(&());
         cursor.seek(&offset, Bias::Right, &());
         if let Some(excerpt) = cursor.item() {
             let (start_offset, start_offset_utf16) = cursor.start();
@@ -2636,7 +2636,7 @@ impl MultiBufferSnapshot {
             return buffer.point_utf16_to_offset(point);
         }
 
-        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>();
+        let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>(&());
         cursor.seek(&point, Bias::Right, &());
         if let Some(excerpt) = cursor.item() {
             let (start_point, start_offset) = cursor.start();
@@ -2659,7 +2659,7 @@ impl MultiBufferSnapshot {
         point: T,
     ) -> Option<(&BufferSnapshot, usize)> {
         let offset = point.to_offset(self);
-        let mut cursor = self.excerpts.cursor::<usize>();
+        let mut cursor = self.excerpts.cursor::<usize>(&());
         cursor.seek(&offset, Bias::Right, &());
         if cursor.item().is_none() {
             cursor.prev(&());
@@ -2680,7 +2680,7 @@ impl MultiBufferSnapshot {
         let mut result = BTreeMap::new();
 
         let mut rows_for_excerpt = Vec::new();
-        let mut cursor = self.excerpts.cursor::<Point>();
+        let mut cursor = self.excerpts.cursor::<Point>(&());
         let mut rows = rows.into_iter().peekable();
         let mut prev_row = u32::MAX;
         let mut prev_language_indent_size = IndentSize::default();
@@ -2769,7 +2769,7 @@ impl MultiBufferSnapshot {
         &self,
         row: MultiBufferRow,
     ) -> Option<(&BufferSnapshot, Range<Point>)> {
-        let mut cursor = self.excerpts.cursor::<Point>();
+        let mut cursor = self.excerpts.cursor::<Point>(&());
         let point = Point::new(row.0, 0);
         cursor.seek(&point, Bias::Right, &());
         if cursor.item().is_none() && *cursor.start() == point {
@@ -2803,9 +2803,9 @@ impl MultiBufferSnapshot {
         D: TextDimension,
         O: ToOffset,
     {
-        let mut summary = D::default();
+        let mut summary = D::zero(&());
         let mut range = range.start.to_offset(self)..range.end.to_offset(self);
-        let mut cursor = self.excerpts.cursor::<usize>();
+        let mut cursor = self.excerpts.cursor::<usize>(&());
         cursor.seek(&range.start, Bias::Right, &());
         if let Some(excerpt) = cursor.item() {
             let mut end_before_newline = cursor.end(&());
@@ -2856,7 +2856,7 @@ impl MultiBufferSnapshot {
     where
         D: TextDimension + Ord + Sub<D, Output = D>,
     {
-        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
+        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
         let locator = self.excerpt_locator_for_id(anchor.excerpt_id);
 
         cursor.seek(locator, Bias::Left, &());
@@ -2894,7 +2894,7 @@ impl MultiBufferSnapshot {
         }
 
         let mut anchors = anchors.into_iter().peekable();
-        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
+        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
         let mut summaries = Vec::new();
         while let Some(anchor) = anchors.peek() {
             let excerpt_id = anchor.excerpt_id;
@@ -2949,7 +2949,7 @@ impl MultiBufferSnapshot {
         I: 'a + IntoIterator<Item = &'a Anchor>,
     {
         let mut anchors = anchors.into_iter().enumerate().peekable();
-        let mut cursor = self.excerpts.cursor::<Option<&Locator>>();
+        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
         cursor.next(&());
 
         let mut result = Vec::new();
@@ -3064,7 +3064,7 @@ impl MultiBufferSnapshot {
             };
         }
 
-        let mut cursor = self.excerpts.cursor::<(usize, Option<ExcerptId>)>();
+        let mut cursor = self.excerpts.cursor::<(usize, Option<ExcerptId>)>(&());
         cursor.seek(&offset, Bias::Right, &());
         if cursor.item().is_none() && offset == cursor.start().0 && bias == Bias::Left {
             cursor.prev(&());
@@ -3099,7 +3099,7 @@ impl MultiBufferSnapshot {
         text_anchor: text::Anchor,
     ) -> Option<Anchor> {
         let locator = self.excerpt_locator_for_id(excerpt_id);
-        let mut cursor = self.excerpts.cursor::<Option<&Locator>>();
+        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
         cursor.seek(locator, Bias::Left, &());
         if let Some(excerpt) = cursor.item() {
             if excerpt.id == excerpt_id {
@@ -3139,7 +3139,7 @@ impl MultiBufferSnapshot {
     ) -> impl Iterator<Item = (&Excerpt, usize)> + '_ {
         let range = range.start.to_offset(self)..range.end.to_offset(self);
 
-        let mut cursor = self.excerpts.cursor::<usize>();
+        let mut cursor = self.excerpts.cursor::<usize>(&());
         cursor.seek(&range.start, Bias::Right, &());
         cursor.prev(&());
 
@@ -3183,7 +3183,7 @@ impl MultiBufferSnapshot {
         };
         let bounds = (start, end);
 
-        let mut cursor = self.excerpts.cursor::<(usize, Point)>();
+        let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
         cursor.seek(&start_offset, Bias::Right, &());
         if cursor.item().is_none() {
             cursor.prev(&());
@@ -3550,7 +3550,7 @@ impl MultiBufferSnapshot {
         &self,
         row_range: Range<MultiBufferRow>,
     ) -> impl Iterator<Item = DiffHunk<MultiBufferRow>> + '_ {
-        let mut cursor = self.excerpts.cursor::<Point>();
+        let mut cursor = self.excerpts.cursor::<Point>(&());
 
         cursor.seek(&Point::new(row_range.end.0, 0), Bias::Left, &());
         if cursor.item().is_none() {
@@ -3617,7 +3617,7 @@ impl MultiBufferSnapshot {
         &self,
         row_range: Range<MultiBufferRow>,
     ) -> impl Iterator<Item = DiffHunk<MultiBufferRow>> + '_ {
-        let mut cursor = self.excerpts.cursor::<Point>();
+        let mut cursor = self.excerpts.cursor::<Point>(&());
 
         cursor.seek(&Point::new(row_range.start.0, 0), Bias::Left, &());
 
@@ -3779,7 +3779,7 @@ impl MultiBufferSnapshot {
         } else if id == ExcerptId::max() {
             Locator::max_ref()
         } else {
-            let mut cursor = self.excerpt_ids.cursor::<ExcerptId>();
+            let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(&());
             cursor.seek(&id, Bias::Left, &());
             if let Some(entry) = cursor.item() {
                 if entry.id == id {
@@ -3814,7 +3814,7 @@ impl MultiBufferSnapshot {
             }
         }
 
-        let mut cursor = self.excerpt_ids.cursor::<ExcerptId>();
+        let mut cursor = self.excerpt_ids.cursor::<ExcerptId>(&());
         for id in sorted_ids {
             if cursor.seek_forward(&id, Bias::Left, &()) {
                 locators.push(cursor.item().unwrap().locator.clone());
@@ -3839,7 +3839,7 @@ impl MultiBufferSnapshot {
         &'a self,
         excerpt_id: ExcerptId,
     ) -> Option<Range<T>> {
-        let mut cursor = self.excerpts.cursor::<(Option<&Locator>, T)>();
+        let mut cursor = self.excerpts.cursor::<(Option<&Locator>, T)>(&());
         let locator = self.excerpt_locator_for_id(excerpt_id);
         if cursor.seek(&Some(locator), Bias::Left, &()) {
             let start = cursor.start().1.clone();
@@ -3851,7 +3851,7 @@ impl MultiBufferSnapshot {
     }
 
     fn excerpt(&self, excerpt_id: ExcerptId) -> Option<&Excerpt> {
-        let mut cursor = self.excerpts.cursor::<Option<&Locator>>();
+        let mut cursor = self.excerpts.cursor::<Option<&Locator>>(&());
         let locator = self.excerpt_locator_for_id(excerpt_id);
         cursor.seek(&Some(locator), Bias::Left, &());
         if let Some(excerpt) = cursor.item() {
@@ -3866,7 +3866,7 @@ impl MultiBufferSnapshot {
     pub fn excerpt_containing<T: ToOffset>(&self, range: Range<T>) -> Option<MultiBufferExcerpt> {
         let range = range.start.to_offset(self)..range.end.to_offset(self);
 
-        let mut cursor = self.excerpts.cursor::<usize>();
+        let mut cursor = self.excerpts.cursor::<usize>(&());
         cursor.seek(&range.start, Bias::Right, &());
         let start_excerpt = cursor.item()?;
 
@@ -3891,7 +3891,7 @@ impl MultiBufferSnapshot {
         I: IntoIterator<Item = Range<Anchor>> + 'a,
     {
         let mut ranges = ranges.into_iter().map(|range| range.to_offset(self));
-        let mut cursor = self.excerpts.cursor::<usize>();
+        let mut cursor = self.excerpts.cursor::<usize>(&());
         cursor.next(&());
         let mut current_range = ranges.next();
         iter::from_fn(move || {
@@ -3943,7 +3943,7 @@ impl MultiBufferSnapshot {
         ranges: impl IntoIterator<Item = Range<Anchor>>,
     ) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, Range<usize>)> {
         let mut ranges = ranges.into_iter().map(|range| range.to_offset(self));
-        let mut cursor = self.excerpts.cursor::<usize>();
+        let mut cursor = self.excerpts.cursor::<usize>(&());
         cursor.next(&());
         let mut current_range = ranges.next();
         iter::from_fn(move || {
@@ -3980,7 +3980,7 @@ impl MultiBufferSnapshot {
         range: &'a Range<Anchor>,
         include_local: bool,
     ) -> impl 'a + Iterator<Item = (ReplicaId, bool, CursorShape, Selection<Anchor>)> {
-        let mut cursor = self.excerpts.cursor::<ExcerptSummary>();
+        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
         let start_locator = self.excerpt_locator_for_id(range.start.excerpt_id);
         let end_locator = self.excerpt_locator_for_id(range.end.excerpt_id);
         cursor.seek(start_locator, Bias::Left, &());
@@ -4519,6 +4519,10 @@ impl sum_tree::KeyedItem for ExcerptIdMapping {
 impl sum_tree::Summary for ExcerptId {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, _: &()) {
         *self = *other;
     }
@@ -4527,6 +4531,10 @@ impl sum_tree::Summary for ExcerptId {
 impl sum_tree::Summary for ExcerptSummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &()) {
         debug_assert!(summary.excerpt_locator > self.excerpt_locator);
         self.excerpt_locator = summary.excerpt_locator.clone();
@@ -4536,12 +4544,20 @@ impl sum_tree::Summary for ExcerptSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
         *self += &summary.text;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
         *self += summary.text.len;
     }
@@ -4566,30 +4582,50 @@ impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Locator {
 }
 
 impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for OffsetUtf16 {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
         *self += summary.text.len_utf16;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
         *self += summary.text.lines;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for PointUtf16 {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
         *self += summary.text.lines_utf16()
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a Locator> {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
         *self = Some(&summary.excerpt_locator);
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<ExcerptId> {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
         *self = Some(summary.excerpt_id);
     }

crates/notifications/src/notification_store.rs 🔗

@@ -137,13 +137,12 @@ impl NotificationStore {
             return None;
         }
         let ix = count - 1 - ix;
-        let mut cursor = self.notifications.cursor::<Count>();
+        let mut cursor = self.notifications.cursor::<Count>(&());
         cursor.seek(&Count(ix), Bias::Right, &());
         cursor.item()
     }
-
     pub fn notification_for_id(&self, id: u64) -> Option<&NotificationEntry> {
-        let mut cursor = self.notifications.cursor::<NotificationId>();
+        let mut cursor = self.notifications.cursor::<NotificationId>(&());
         cursor.seek(&NotificationId(id), Bias::Left, &());
         if let Some(item) = cursor.item() {
             if item.id == id {
@@ -372,8 +371,8 @@ impl NotificationStore {
         is_new: bool,
         cx: &mut ModelContext<'_, NotificationStore>,
     ) {
-        let mut cursor = self.notifications.cursor::<(NotificationId, Count)>();
-        let mut new_notifications = SumTree::new();
+        let mut cursor = self.notifications.cursor::<(NotificationId, Count)>(&());
+        let mut new_notifications = SumTree::default();
         let mut old_range = 0..0;
 
         for (i, (id, new_notification)) in notifications.into_iter().enumerate() {
@@ -468,6 +467,10 @@ impl sum_tree::Item for NotificationEntry {
 impl sum_tree::Summary for NotificationSummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &()) {
         self.max_id = self.max_id.max(summary.max_id);
         self.count += summary.count;
@@ -476,6 +479,10 @@ impl sum_tree::Summary for NotificationSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, NotificationSummary> for NotificationId {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &NotificationSummary, _: &()) {
         debug_assert!(summary.max_id > self.0);
         self.0 = summary.max_id;
@@ -483,6 +490,10 @@ impl<'a> sum_tree::Dimension<'a, NotificationSummary> for NotificationId {
 }
 
 impl<'a> sum_tree::Dimension<'a, NotificationSummary> for Count {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &NotificationSummary, _: &()) {
         self.0 += summary.count;
     }

crates/project/src/lsp_store.rs 🔗

@@ -2753,7 +2753,7 @@ impl LspStore {
             if let Some(language) = buffer.language().cloned() {
                 for adapter in self.languages.lsp_adapters(&language.name()) {
                     if let Some(server_id) = ids.get(&(worktree_id, adapter.name.clone())) {
-                        buffer.update_diagnostics(*server_id, Default::default(), cx);
+                        buffer.update_diagnostics(*server_id, DiagnosticSet::new([], buffer), cx);
                     }
                 }
             }
@@ -5149,7 +5149,11 @@ impl LspStore {
                 self.buffer_store.update(cx, |buffer_store, cx| {
                     for buffer in buffer_store.buffers() {
                         buffer.update(cx, |buffer, cx| {
-                            buffer.update_diagnostics(server_id, Default::default(), cx);
+                            buffer.update_diagnostics(
+                                server_id,
+                                DiagnosticSet::new([], buffer),
+                                cx,
+                            );
                         });
                     }
                 });

crates/rope/src/rope.rs 🔗

@@ -36,7 +36,7 @@ impl Rope {
     }
 
     pub fn append(&mut self, rope: Rope) {
-        let mut chunks = rope.chunks.cursor::<()>();
+        let mut chunks = rope.chunks.cursor::<()>(&());
         chunks.next(&());
         if let Some(chunk) = chunks.item() {
             if self.chunks.last().map_or(false, |c| c.0.len() < CHUNK_BASE)
@@ -175,7 +175,7 @@ impl Rope {
         {
             // Ensure all chunks except maybe the last one are not underflowing.
             // Allow some wiggle room for multibyte characters at chunk boundaries.
-            let mut chunks = self.chunks.cursor::<()>().peekable();
+            let mut chunks = self.chunks.cursor::<()>(&()).peekable();
             while let Some(chunk) = chunks.next() {
                 if chunks.peek().is_some() {
                     assert!(chunk.0.len() + 3 >= CHUNK_BASE);
@@ -245,7 +245,7 @@ impl Rope {
         if offset >= self.summary().len {
             return self.summary().len_utf16;
         }
-        let mut cursor = self.chunks.cursor::<(usize, OffsetUtf16)>();
+        let mut cursor = self.chunks.cursor::<(usize, OffsetUtf16)>(&());
         cursor.seek(&offset, Bias::Left, &());
         let overshoot = offset - cursor.start().0;
         cursor.start().1
@@ -258,7 +258,7 @@ impl Rope {
         if offset >= self.summary().len_utf16 {
             return self.summary().len;
         }
-        let mut cursor = self.chunks.cursor::<(OffsetUtf16, usize)>();
+        let mut cursor = self.chunks.cursor::<(OffsetUtf16, usize)>(&());
         cursor.seek(&offset, Bias::Left, &());
         let overshoot = offset - cursor.start().0;
         cursor.start().1
@@ -271,7 +271,7 @@ impl Rope {
         if offset >= self.summary().len {
             return self.summary().lines;
         }
-        let mut cursor = self.chunks.cursor::<(usize, Point)>();
+        let mut cursor = self.chunks.cursor::<(usize, Point)>(&());
         cursor.seek(&offset, Bias::Left, &());
         let overshoot = offset - cursor.start().0;
         cursor.start().1
@@ -284,7 +284,7 @@ impl Rope {
         if offset >= self.summary().len {
             return self.summary().lines_utf16();
         }
-        let mut cursor = self.chunks.cursor::<(usize, PointUtf16)>();
+        let mut cursor = self.chunks.cursor::<(usize, PointUtf16)>(&());
         cursor.seek(&offset, Bias::Left, &());
         let overshoot = offset - cursor.start().0;
         cursor.start().1
@@ -297,7 +297,7 @@ impl Rope {
         if point >= self.summary().lines {
             return self.summary().lines_utf16();
         }
-        let mut cursor = self.chunks.cursor::<(Point, PointUtf16)>();
+        let mut cursor = self.chunks.cursor::<(Point, PointUtf16)>(&());
         cursor.seek(&point, Bias::Left, &());
         let overshoot = point - cursor.start().0;
         cursor.start().1
@@ -310,7 +310,7 @@ impl Rope {
         if point >= self.summary().lines {
             return self.summary().len;
         }
-        let mut cursor = self.chunks.cursor::<(Point, usize)>();
+        let mut cursor = self.chunks.cursor::<(Point, usize)>(&());
         cursor.seek(&point, Bias::Left, &());
         let overshoot = point - cursor.start().0;
         cursor.start().1
@@ -331,7 +331,7 @@ impl Rope {
         if point >= self.summary().lines_utf16() {
             return self.summary().len;
         }
-        let mut cursor = self.chunks.cursor::<(PointUtf16, usize)>();
+        let mut cursor = self.chunks.cursor::<(PointUtf16, usize)>(&());
         cursor.seek(&point, Bias::Left, &());
         let overshoot = point - cursor.start().0;
         cursor.start().1
@@ -344,7 +344,7 @@ impl Rope {
         if point.0 >= self.summary().lines_utf16() {
             return self.summary().lines;
         }
-        let mut cursor = self.chunks.cursor::<(PointUtf16, Point)>();
+        let mut cursor = self.chunks.cursor::<(PointUtf16, Point)>(&());
         cursor.seek(&point.0, Bias::Left, &());
         let overshoot = Unclipped(point.0 - cursor.start().0);
         cursor.start().1
@@ -354,7 +354,7 @@ impl Rope {
     }
 
     pub fn clip_offset(&self, mut offset: usize, bias: Bias) -> usize {
-        let mut cursor = self.chunks.cursor::<usize>();
+        let mut cursor = self.chunks.cursor::<usize>(&());
         cursor.seek(&offset, Bias::Left, &());
         if let Some(chunk) = cursor.item() {
             let mut ix = offset - cursor.start();
@@ -377,7 +377,7 @@ impl Rope {
     }
 
     pub fn clip_offset_utf16(&self, offset: OffsetUtf16, bias: Bias) -> OffsetUtf16 {
-        let mut cursor = self.chunks.cursor::<OffsetUtf16>();
+        let mut cursor = self.chunks.cursor::<OffsetUtf16>(&());
         cursor.seek(&offset, Bias::Right, &());
         if let Some(chunk) = cursor.item() {
             let overshoot = offset - cursor.start();
@@ -388,7 +388,7 @@ impl Rope {
     }
 
     pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
-        let mut cursor = self.chunks.cursor::<Point>();
+        let mut cursor = self.chunks.cursor::<Point>(&());
         cursor.seek(&point, Bias::Right, &());
         if let Some(chunk) = cursor.item() {
             let overshoot = point - cursor.start();
@@ -399,7 +399,7 @@ impl Rope {
     }
 
     pub fn clip_point_utf16(&self, point: Unclipped<PointUtf16>, bias: Bias) -> PointUtf16 {
-        let mut cursor = self.chunks.cursor::<PointUtf16>();
+        let mut cursor = self.chunks.cursor::<PointUtf16>(&());
         cursor.seek(&point.0, Bias::Right, &());
         if let Some(chunk) = cursor.item() {
             let overshoot = Unclipped(point.0 - cursor.start());
@@ -472,7 +472,7 @@ pub struct Cursor<'a> {
 
 impl<'a> Cursor<'a> {
     pub fn new(rope: &'a Rope, offset: usize) -> Self {
-        let mut chunks = rope.chunks.cursor();
+        let mut chunks = rope.chunks.cursor(&());
         chunks.seek(&offset, Bias::Right, &());
         Self {
             rope,
@@ -521,7 +521,7 @@ impl<'a> Cursor<'a> {
     pub fn summary<D: TextDimension>(&mut self, end_offset: usize) -> D {
         debug_assert!(end_offset >= self.offset);
 
-        let mut summary = D::default();
+        let mut summary = D::zero(&());
         if let Some(start_chunk) = self.chunks.item() {
             let start_ix = self.offset - self.chunks.start();
             let end_ix = cmp::min(end_offset, self.chunks.end(&())) - self.chunks.start();
@@ -563,7 +563,7 @@ pub struct Chunks<'a> {
 
 impl<'a> Chunks<'a> {
     pub fn new(rope: &'a Rope, range: Range<usize>, reversed: bool) -> Self {
-        let mut chunks = rope.chunks.cursor();
+        let mut chunks = rope.chunks.cursor(&());
         let offset = if reversed {
             chunks.seek(&range.end, Bias::Left, &());
             range.end
@@ -774,7 +774,7 @@ pub struct Bytes<'a> {
 
 impl<'a> Bytes<'a> {
     pub fn new(rope: &'a Rope, range: Range<usize>, reversed: bool) -> Self {
-        let mut chunks = rope.chunks.cursor();
+        let mut chunks = rope.chunks.cursor(&());
         if reversed {
             chunks.seek(&range.end, Bias::Left, &());
         } else {
@@ -1180,6 +1180,10 @@ impl<'a> From<&'a str> for ChunkSummary {
 impl sum_tree::Summary for ChunkSummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &()) {
         self.text += &summary.text;
     }
@@ -1263,6 +1267,10 @@ impl<'a> From<&'a str> for TextSummary {
 impl sum_tree::Summary for TextSummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &Self::Context) {
         *self += summary;
     }
@@ -1333,6 +1341,10 @@ impl<D1: TextDimension, D2: TextDimension> TextDimension for (D1, D2) {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChunkSummary> for TextSummary {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
         *self += &summary.text;
     }
@@ -1349,6 +1361,10 @@ impl TextDimension for TextSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChunkSummary> for usize {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
         *self += summary.text.len;
     }
@@ -1365,6 +1381,10 @@ impl TextDimension for usize {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChunkSummary> for OffsetUtf16 {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
         *self += summary.text.len_utf16;
     }
@@ -1381,6 +1401,10 @@ impl TextDimension for OffsetUtf16 {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChunkSummary> for Point {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
         *self += summary.text.lines;
     }
@@ -1397,6 +1421,10 @@ impl TextDimension for Point {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChunkSummary> for PointUtf16 {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
         *self += summary.text.lines_utf16();
     }
@@ -1890,7 +1918,7 @@ mod tests {
     impl Rope {
         fn text(&self) -> String {
             let mut text = String::new();
-            for chunk in self.chunks.cursor::<()>() {
+            for chunk in self.chunks.cursor::<()>(&()) {
                 text.push_str(&chunk.0);
             }
             text

crates/rope/src/unclipped.rs 🔗

@@ -13,6 +13,10 @@ impl<T> From<T> for Unclipped<T> {
 impl<'a, T: sum_tree::Dimension<'a, ChunkSummary>> sum_tree::Dimension<'a, ChunkSummary>
     for Unclipped<T>
 {
+    fn zero(_: &()) -> Self {
+        Self(T::zero(&()))
+    }
+
     fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
         self.0.add_summary(summary, &());
     }

crates/sum_tree/src/cursor.rs 🔗

@@ -28,21 +28,21 @@ where
     T: Item,
     D: Dimension<'a, T::Summary>,
 {
-    pub fn new(tree: &'a SumTree<T>) -> Self {
+    pub fn new(tree: &'a SumTree<T>, cx: &<T::Summary as Summary>::Context) -> Self {
         Self {
             tree,
             stack: ArrayVec::new(),
-            position: D::default(),
+            position: D::zero(cx),
             did_seek: false,
             at_end: tree.is_empty(),
         }
     }
 
-    fn reset(&mut self) {
+    fn reset(&mut self, cx: &<T::Summary as Summary>::Context) {
         self.did_seek = false;
         self.at_end = self.tree.is_empty();
         self.stack.truncate(0);
-        self.position = D::default();
+        self.position = D::zero(cx);
     }
 
     pub fn start(&self) -> &D {
@@ -192,7 +192,7 @@ where
         }
 
         if self.at_end {
-            self.position = D::default();
+            self.position = D::zero(cx);
             self.at_end = self.tree.is_empty();
             if !self.tree.is_empty() {
                 self.stack.push(StackEntry {
@@ -208,7 +208,7 @@ where
             if let Some(StackEntry { position, .. }) = self.stack.iter().rev().nth(1) {
                 self.position = position.clone();
             } else {
-                self.position = D::default();
+                self.position = D::zero(cx);
             }
 
             let entry = self.stack.last_mut().unwrap();
@@ -232,7 +232,7 @@ where
                     if descending {
                         let tree = &child_trees[entry.index];
                         self.stack.push(StackEntry {
-                            position: D::default(),
+                            position: D::zero(cx),
                             tree,
                             index: tree.0.child_summaries().len() - 1,
                         })
@@ -264,7 +264,7 @@ where
                 self.stack.push(StackEntry {
                     tree: self.tree,
                     index: 0,
-                    position: D::default(),
+                    position: D::zero(cx),
                 });
                 descend = true;
             }
@@ -364,7 +364,7 @@ where
     where
         Target: SeekTarget<'a, T::Summary, D>,
     {
-        self.reset();
+        self.reset(cx);
         self.seek_internal(pos, bias, &mut (), cx)
     }
 
@@ -392,10 +392,10 @@ where
         Target: SeekTarget<'a, T::Summary, D>,
     {
         let mut slice = SliceSeekAggregate {
-            tree: SumTree::new(),
+            tree: SumTree::new(cx),
             leaf_items: ArrayVec::new(),
             leaf_item_summaries: ArrayVec::new(),
-            leaf_summary: T::Summary::default(),
+            leaf_summary: <T::Summary as Summary>::zero(cx),
         };
         self.seek_internal(end, bias, &mut slice, cx);
         slice.tree
@@ -417,7 +417,7 @@ where
         Target: SeekTarget<'a, T::Summary, D>,
         Output: Dimension<'a, T::Summary>,
     {
-        let mut summary = SummarySeekAggregate(Output::default());
+        let mut summary = SummarySeekAggregate(Output::zero(cx));
         self.seek_internal(end, bias, &mut summary, cx);
         summary.0
     }
@@ -443,7 +443,7 @@ where
             self.stack.push(StackEntry {
                 tree: self.tree,
                 index: 0,
-                position: Default::default(),
+                position: D::zero(cx),
             });
         }
 
@@ -633,8 +633,12 @@ where
     T: Item,
     D: Dimension<'a, T::Summary>,
 {
-    pub fn new(tree: &'a SumTree<T>, filter_node: F) -> Self {
-        let cursor = tree.cursor::<D>();
+    pub fn new(
+        tree: &'a SumTree<T>,
+        cx: &<T::Summary as Summary>::Context,
+        filter_node: F,
+    ) -> Self {
+        let cursor = tree.cursor::<D>(cx);
         Self {
             cursor,
             filter_node,
@@ -727,7 +731,7 @@ impl<'a, T: Item> SeekAggregate<'a, T> for SliceSeekAggregate<T> {
     fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context) {
         self.tree.append(
             SumTree(Arc::new(Node::Leaf {
-                summary: mem::take(&mut self.leaf_summary),
+                summary: mem::replace(&mut self.leaf_summary, <T::Summary as Summary>::zero(cx)),
                 items: mem::take(&mut self.leaf_items),
                 item_summaries: mem::take(&mut self.leaf_item_summaries),
             })),

crates/sum_tree/src/sum_tree.rs 🔗

@@ -34,9 +34,11 @@ pub trait KeyedItem: Item {
 ///
 /// Each Summary type can have multiple [`Dimensions`] that it measures,
 /// which can be used to navigate the tree
-pub trait Summary: Default + Clone + fmt::Debug {
+pub trait Summary: Clone + fmt::Debug {
     type Context;
 
+    fn zero(cx: &Self::Context) -> Self;
+
     fn add_summary(&mut self, summary: &Self, cx: &Self::Context);
 }
 
@@ -47,17 +49,23 @@ pub trait Summary: Default + Clone + fmt::Debug {
 /// # Example:
 /// Zed's rope has a `TextSummary` type that summarizes lines, characters, and bytes.
 /// Each of these are different dimensions we may want to seek to
-pub trait Dimension<'a, S: Summary>: Clone + fmt::Debug + Default {
-    fn add_summary(&mut self, _summary: &'a S, _: &S::Context);
+pub trait Dimension<'a, S: Summary>: Clone + fmt::Debug {
+    fn zero(cx: &S::Context) -> Self;
+
+    fn add_summary(&mut self, summary: &'a S, cx: &S::Context);
 
     fn from_summary(summary: &'a S, cx: &S::Context) -> Self {
-        let mut dimension = Self::default();
+        let mut dimension = Self::zero(cx);
         dimension.add_summary(summary, cx);
         dimension
     }
 }
 
 impl<'a, T: Summary> Dimension<'a, T> for T {
+    fn zero(cx: &T::Context) -> Self {
+        Summary::zero(cx)
+    }
+
     fn add_summary(&mut self, summary: &'a T, cx: &T::Context) {
         Summary::add_summary(self, summary, cx);
     }
@@ -74,10 +82,18 @@ impl<'a, S: Summary, D: Dimension<'a, S> + Ord> SeekTarget<'a, S, D> for D {
 }
 
 impl<'a, T: Summary> Dimension<'a, T> for () {
+    fn zero(_: &T::Context) -> Self {
+        ()
+    }
+
     fn add_summary(&mut self, _: &'a T, _: &T::Context) {}
 }
 
 impl<'a, T: Summary, D1: Dimension<'a, T>, D2: Dimension<'a, T>> Dimension<'a, T> for (D1, D2) {
+    fn zero(cx: &T::Context) -> Self {
+        (D1::zero(cx), D2::zero(cx))
+    }
+
     fn add_summary(&mut self, summary: &'a T, cx: &T::Context) {
         self.0.add_summary(summary, cx);
         self.1.add_summary(summary, cx);
@@ -161,16 +177,16 @@ impl Bias {
 pub struct SumTree<T: Item>(Arc<Node<T>>);
 
 impl<T: Item> SumTree<T> {
-    pub fn new() -> Self {
+    pub fn new(cx: &<T::Summary as Summary>::Context) -> Self {
         SumTree(Arc::new(Node::Leaf {
-            summary: T::Summary::default(),
+            summary: <T::Summary as Summary>::zero(cx),
             items: ArrayVec::new(),
             item_summaries: ArrayVec::new(),
         }))
     }
 
     pub fn from_item(item: T, cx: &<T::Summary as Summary>::Context) -> Self {
-        let mut tree = Self::new();
+        let mut tree = Self::new(cx);
         tree.push(item, cx);
         tree
     }
@@ -206,7 +222,7 @@ impl<T: Item> SumTree<T> {
             let mut current_parent_node = None;
             for child_node in nodes.drain(..) {
                 let parent_node = current_parent_node.get_or_insert_with(|| Node::Internal {
-                    summary: T::Summary::default(),
+                    summary: <T::Summary as Summary>::zero(cx),
                     height,
                     child_summaries: ArrayVec::new(),
                     child_trees: ArrayVec::new(),
@@ -234,7 +250,7 @@ impl<T: Item> SumTree<T> {
         }
 
         if nodes.is_empty() {
-            Self::new()
+            Self::new(cx)
         } else {
             debug_assert_eq!(nodes.len(), 1);
             Self(Arc::new(nodes.pop().unwrap()))
@@ -296,7 +312,7 @@ impl<T: Item> SumTree<T> {
         }
 
         if nodes.is_empty() {
-            Self::new()
+            Self::new(cx)
         } else {
             debug_assert_eq!(nodes.len(), 1);
             nodes.pop().unwrap()
@@ -306,7 +322,7 @@ impl<T: Item> SumTree<T> {
     #[allow(unused)]
     pub fn items(&self, cx: &<T::Summary as Summary>::Context) -> Vec<T> {
         let mut items = Vec::new();
-        let mut cursor = self.cursor::<()>();
+        let mut cursor = self.cursor::<()>(cx);
         cursor.next(cx);
         while let Some(item) = cursor.item() {
             items.push(item.clone());
@@ -319,21 +335,25 @@ impl<T: Item> SumTree<T> {
         Iter::new(self)
     }
 
-    pub fn cursor<'a, S>(&'a self) -> Cursor<T, S>
+    pub fn cursor<'a, S>(&'a self, cx: &<T::Summary as Summary>::Context) -> Cursor<T, S>
     where
         S: Dimension<'a, T::Summary>,
     {
-        Cursor::new(self)
+        Cursor::new(self, cx)
     }
 
     /// Note: If the summary type requires a non `()` context, then the filter cursor
     /// that is returned cannot be used with Rust's iterators.
-    pub fn filter<'a, F, U>(&'a self, filter_node: F) -> FilterCursor<F, T, U>
+    pub fn filter<'a, F, U>(
+        &'a self,
+        cx: &<T::Summary as Summary>::Context,
+        filter_node: F,
+    ) -> FilterCursor<F, T, U>
     where
         F: FnMut(&T::Summary) -> bool,
         U: Dimension<'a, T::Summary>,
     {
-        FilterCursor::new(self, filter_node)
+        FilterCursor::new(self, cx, filter_node)
     }
 
     #[allow(dead_code)]
@@ -389,7 +409,7 @@ impl<T: Item> SumTree<T> {
         &'a self,
         cx: &<T::Summary as Summary>::Context,
     ) -> D {
-        let mut extent = D::default();
+        let mut extent = D::zero(cx);
         match self.0.as_ref() {
             Node::Internal { summary, .. } | Node::Leaf { summary, .. } => {
                 extent.add_summary(summary, cx);
@@ -636,7 +656,7 @@ impl<T: KeyedItem> SumTree<T> {
     ) -> Option<T> {
         let mut replaced = None;
         *self = {
-            let mut cursor = self.cursor::<T::Key>();
+            let mut cursor = self.cursor::<T::Key>(cx);
             let mut new_tree = cursor.slice(&item.key(), Bias::Left, cx);
             if let Some(cursor_item) = cursor.item() {
                 if cursor_item.key() == item.key() {
@@ -654,7 +674,7 @@ impl<T: KeyedItem> SumTree<T> {
     pub fn remove(&mut self, key: &T::Key, cx: &<T::Summary as Summary>::Context) -> Option<T> {
         let mut removed = None;
         *self = {
-            let mut cursor = self.cursor::<T::Key>();
+            let mut cursor = self.cursor::<T::Key>(cx);
             let mut new_tree = cursor.slice(key, Bias::Left, cx);
             if let Some(item) = cursor.item() {
                 if item.key() == *key {
@@ -681,11 +701,11 @@ impl<T: KeyedItem> SumTree<T> {
         edits.sort_unstable_by_key(|item| item.key());
 
         *self = {
-            let mut cursor = self.cursor::<T::Key>();
-            let mut new_tree = SumTree::new();
+            let mut cursor = self.cursor::<T::Key>(cx);
+            let mut new_tree = SumTree::new(cx);
             let mut buffered_items = Vec::new();
 
-            cursor.seek(&T::Key::default(), Bias::Left, cx);
+            cursor.seek(&T::Key::zero(cx), Bias::Left, cx);
             for edit in edits {
                 let new_key = edit.key();
                 let mut old_item = cursor.item();
@@ -724,7 +744,7 @@ impl<T: KeyedItem> SumTree<T> {
     }
 
     pub fn get(&self, key: &T::Key, cx: &<T::Summary as Summary>::Context) -> Option<&T> {
-        let mut cursor = self.cursor::<T::Key>();
+        let mut cursor = self.cursor::<T::Key>(cx);
         if cursor.seek(key, Bias::Left, cx) {
             cursor.item()
         } else {
@@ -733,9 +753,13 @@ impl<T: KeyedItem> SumTree<T> {
     }
 }
 
-impl<T: Item> Default for SumTree<T> {
+impl<T, S> Default for SumTree<T>
+where
+    T: Item<Summary = S>,
+    S: Summary<Context = ()>,
+{
     fn default() -> Self {
-        Self::new()
+        Self::new(&())
     }
 }
 
@@ -824,7 +848,7 @@ where
     T: 'a + Summary,
     I: Iterator<Item = &'a T>,
 {
-    let mut sum = T::default();
+    let mut sum = T::zero(cx);
     for value in iter {
         sum.add_summary(value, cx);
     }
@@ -846,10 +870,10 @@ mod tests {
 
     #[test]
     fn test_extend_and_push_tree() {
-        let mut tree1 = SumTree::new();
+        let mut tree1 = SumTree::default();
         tree1.extend(0..20, &());
 
-        let mut tree2 = SumTree::new();
+        let mut tree2 = SumTree::default();
         tree2.extend(50..100, &());
 
         tree1.append(tree2, &());
@@ -877,7 +901,7 @@ mod tests {
             let mut rng = StdRng::seed_from_u64(seed);
 
             let rng = &mut rng;
-            let mut tree = SumTree::<u8>::new();
+            let mut tree = SumTree::<u8>::default();
             let count = rng.gen_range(0..10);
             if rng.gen() {
                 tree.extend(rng.sample_iter(distributions::Standard).take(count), &());
@@ -903,7 +927,7 @@ mod tests {
                 reference_items.splice(splice_start..splice_end, new_items.clone());
 
                 tree = {
-                    let mut cursor = tree.cursor::<Count>();
+                    let mut cursor = tree.cursor::<Count>(&());
                     let mut new_tree = cursor.slice(&Count(splice_start), Bias::Right, &());
                     if rng.gen() {
                         new_tree.extend(new_items, &());
@@ -918,12 +942,13 @@ mod tests {
                 assert_eq!(tree.items(&()), reference_items);
                 assert_eq!(
                     tree.iter().collect::<Vec<_>>(),
-                    tree.cursor::<()>().collect::<Vec<_>>()
+                    tree.cursor::<()>(&()).collect::<Vec<_>>()
                 );
 
                 log::info!("tree items: {:?}", tree.items(&()));
 
-                let mut filter_cursor = tree.filter::<_, Count>(|summary| summary.contains_even);
+                let mut filter_cursor =
+                    tree.filter::<_, Count>(&(), |summary| summary.contains_even);
                 let expected_filtered_items = tree
                     .items(&())
                     .into_iter()
@@ -964,7 +989,7 @@ mod tests {
                 assert_eq!(filter_cursor.item(), None);
 
                 let mut before_start = false;
-                let mut cursor = tree.cursor::<Count>();
+                let mut cursor = tree.cursor::<Count>(&());
                 let start_pos = rng.gen_range(0..=reference_items.len());
                 cursor.seek(&Count(start_pos), Bias::Right, &());
                 let mut pos = rng.gen_range(start_pos..=reference_items.len());
@@ -1015,7 +1040,7 @@ mod tests {
                 let start_bias = if rng.gen() { Bias::Left } else { Bias::Right };
                 let end_bias = if rng.gen() { Bias::Left } else { Bias::Right };
 
-                let mut cursor = tree.cursor::<Count>();
+                let mut cursor = tree.cursor::<Count>(&());
                 cursor.seek(&Count(start), start_bias, &());
                 let slice = cursor.slice(&Count(end), end_bias, &());
 
@@ -1030,8 +1055,8 @@ mod tests {
     #[test]
     fn test_cursor() {
         // Empty tree
-        let tree = SumTree::<u8>::new();
-        let mut cursor = tree.cursor::<IntegersSummary>();
+        let tree = SumTree::<u8>::default();
+        let mut cursor = tree.cursor::<IntegersSummary>(&());
         assert_eq!(
             cursor.slice(&Count(0), Bias::Right, &()).items(&()),
             Vec::<u8>::new()
@@ -1052,9 +1077,9 @@ mod tests {
         assert_eq!(cursor.start().sum, 0);
 
         // Single-element tree
-        let mut tree = SumTree::<u8>::new();
+        let mut tree = SumTree::<u8>::default();
         tree.extend(vec![1], &());
-        let mut cursor = tree.cursor::<IntegersSummary>();
+        let mut cursor = tree.cursor::<IntegersSummary>(&());
         assert_eq!(
             cursor.slice(&Count(0), Bias::Right, &()).items(&()),
             Vec::<u8>::new()
@@ -1076,7 +1101,7 @@ mod tests {
         assert_eq!(cursor.next_item(), None);
         assert_eq!(cursor.start().sum, 0);
 
-        let mut cursor = tree.cursor::<IntegersSummary>();
+        let mut cursor = tree.cursor::<IntegersSummary>(&());
         assert_eq!(cursor.slice(&Count(1), Bias::Right, &()).items(&()), [1]);
         assert_eq!(cursor.item(), None);
         assert_eq!(cursor.prev_item(), Some(&1));
@@ -1096,9 +1121,9 @@ mod tests {
         assert_eq!(cursor.start().sum, 1);
 
         // Multiple-element tree
-        let mut tree = SumTree::new();
+        let mut tree = SumTree::default();
         tree.extend(vec![1, 2, 3, 4, 5, 6], &());
-        let mut cursor = tree.cursor::<IntegersSummary>();
+        let mut cursor = tree.cursor::<IntegersSummary>(&());
 
         assert_eq!(cursor.slice(&Count(2), Bias::Right, &()).items(&()), [1, 2]);
         assert_eq!(cursor.item(), Some(&3));
@@ -1179,7 +1204,7 @@ mod tests {
         assert_eq!(cursor.next_item(), Some(&2));
         assert_eq!(cursor.start().sum, 0);
 
-        let mut cursor = tree.cursor::<IntegersSummary>();
+        let mut cursor = tree.cursor::<IntegersSummary>(&());
         assert_eq!(
             cursor
                 .slice(&tree.extent::<Count>(&()), Bias::Right, &())
@@ -1227,7 +1252,7 @@ mod tests {
 
     #[test]
     fn test_edit() {
-        let mut tree = SumTree::<u8>::new();
+        let mut tree = SumTree::<u8>::default();
 
         let removed = tree.edit(vec![Edit::Insert(1), Edit::Insert(2), Edit::Insert(0)], &());
         assert_eq!(tree.items(&()), vec![0, 1, 2]);
@@ -1305,6 +1330,10 @@ mod tests {
     impl Summary for IntegersSummary {
         type Context = ();
 
+        fn zero(_cx: &()) -> Self {
+            Default::default()
+        }
+
         fn add_summary(&mut self, other: &Self, _: &()) {
             self.count += other.count;
             self.sum += other.sum;
@@ -1314,12 +1343,20 @@ mod tests {
     }
 
     impl<'a> Dimension<'a, IntegersSummary> for u8 {
+        fn zero(_cx: &()) -> Self {
+            Default::default()
+        }
+
         fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
             *self = summary.max;
         }
     }
 
     impl<'a> Dimension<'a, IntegersSummary> for Count {
+        fn zero(_cx: &()) -> Self {
+            Default::default()
+        }
+
         fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
             self.0 += summary.count;
         }
@@ -1332,6 +1369,10 @@ mod tests {
     }
 
     impl<'a> Dimension<'a, IntegersSummary> for Sum {
+        fn zero(_cx: &()) -> Self {
+            Default::default()
+        }
+
         fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
             self.0 += summary.sum;
         }

crates/sum_tree/src/tree_map.rs 🔗

@@ -53,7 +53,7 @@ impl<K: Clone + Debug + Ord, V: Clone + Debug> TreeMap<K, V> {
     }
 
     pub fn get(&self, key: &K) -> Option<&V> {
-        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>();
+        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>(&());
         cursor.seek(&MapKeyRef(Some(key)), Bias::Left, &());
         if let Some(item) = cursor.item() {
             if Some(key) == item.key().0.as_ref() {
@@ -72,7 +72,7 @@ impl<K: Clone + Debug + Ord, V: Clone + Debug> TreeMap<K, V> {
 
     pub fn remove(&mut self, key: &K) -> Option<V> {
         let mut removed = None;
-        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>();
+        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>(&());
         let key = MapKeyRef(Some(key));
         let mut new_tree = cursor.slice(&key, Bias::Left, &());
         if key.cmp(&cursor.end(&()), &()) == Ordering::Equal {
@@ -88,7 +88,7 @@ impl<K: Clone + Debug + Ord, V: Clone + Debug> TreeMap<K, V> {
     pub fn remove_range(&mut self, start: &impl MapSeekTarget<K>, end: &impl MapSeekTarget<K>) {
         let start = MapSeekTargetAdaptor(start);
         let end = MapSeekTargetAdaptor(end);
-        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>();
+        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>(&());
         let mut new_tree = cursor.slice(&start, Bias::Left, &());
         cursor.seek(&end, Bias::Left, &());
         new_tree.append(cursor.suffix(&()), &());
@@ -98,7 +98,7 @@ impl<K: Clone + Debug + Ord, V: Clone + Debug> TreeMap<K, V> {
 
     /// Returns the key-value pair with the greatest key less than or equal to the given key.
     pub fn closest(&self, key: &K) -> Option<(&K, &V)> {
-        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>();
+        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>(&());
         let key = MapKeyRef(Some(key));
         cursor.seek(&key, Bias::Right, &());
         cursor.prev(&());
@@ -106,7 +106,7 @@ impl<K: Clone + Debug + Ord, V: Clone + Debug> TreeMap<K, V> {
     }
 
     pub fn iter_from<'a>(&'a self, from: &'a K) -> impl Iterator<Item = (&K, &V)> + '_ {
-        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>();
+        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>(&());
         let from_key = MapKeyRef(Some(from));
         cursor.seek(&from_key, Bias::Left, &());
 
@@ -117,7 +117,7 @@ impl<K: Clone + Debug + Ord, V: Clone + Debug> TreeMap<K, V> {
     where
         F: FnOnce(&mut V) -> T,
     {
-        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>();
+        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>(&());
         let key = MapKeyRef(Some(key));
         let mut new_tree = cursor.slice(&key, Bias::Left, &());
         let mut result = None;
@@ -136,7 +136,7 @@ impl<K: Clone + Debug + Ord, V: Clone + Debug> TreeMap<K, V> {
     pub fn retain<F: FnMut(&K, &V) -> bool>(&mut self, mut predicate: F) {
         let mut new_map = SumTree::<MapEntry<K, V>>::default();
 
-        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>();
+        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>(&());
         cursor.next(&());
         while let Some(item) = cursor.item() {
             if predicate(&item.key, &item.value) {
@@ -247,6 +247,10 @@ where
 {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &()) {
         *self = summary.clone()
     }
@@ -256,6 +260,10 @@ impl<'a, K> Dimension<'a, MapKey<K>> for MapKeyRef<'a, K>
 where
     K: Clone + Debug + Ord,
 {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a MapKey<K>, _: &()) {
         self.0 = summary.0.as_ref();
     }

crates/text/src/anchor.rs 🔗

@@ -100,7 +100,7 @@ impl Anchor {
             false
         } else {
             let fragment_id = buffer.fragment_id_for_anchor(self);
-            let mut fragment_cursor = buffer.fragments.cursor::<(Option<&Locator>, usize)>();
+            let mut fragment_cursor = buffer.fragments.cursor::<(Option<&Locator>, usize)>(&None);
             fragment_cursor.seek(&Some(fragment_id), Bias::Left, &None);
             fragment_cursor
                 .item()

crates/text/src/locator.rs 🔗

@@ -85,6 +85,10 @@ impl sum_tree::KeyedItem for Locator {
 impl sum_tree::Summary for Locator {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &()) {
         self.assign(summary);
     }

crates/text/src/operation_queue.rs 🔗

@@ -34,7 +34,7 @@ impl<T: Operation> Default for OperationQueue<T> {
 
 impl<T: Operation> OperationQueue<T> {
     pub fn new() -> Self {
-        OperationQueue(SumTree::new())
+        OperationQueue(SumTree::default())
     }
 
     pub fn len(&self) -> usize {
@@ -58,7 +58,7 @@ impl<T: Operation> OperationQueue<T> {
 
     pub fn drain(&mut self) -> Self {
         let clone = self.clone();
-        self.0 = SumTree::new();
+        self.0 = SumTree::default();
         clone
     }
 
@@ -70,6 +70,10 @@ impl<T: Operation> OperationQueue<T> {
 impl Summary for OperationSummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, _: &()) {
         assert!(self.key < other.key);
         self.key = other.key;
@@ -90,6 +94,10 @@ impl<'a> Add<&'a Self> for OperationSummary {
 }
 
 impl<'a> Dimension<'a, OperationSummary> for OperationKey {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &OperationSummary, _: &()) {
         assert!(*self <= summary.key);
         *self = summary.key;

crates/text/src/text.rs 🔗

@@ -492,6 +492,10 @@ struct FragmentTextSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentTextSummary {
+    fn zero(_: &Option<clock::Global>) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a FragmentSummary, _: &Option<clock::Global>) {
         self.visible += summary.text.visible;
         self.deleted += summary.text.deleted;
@@ -654,8 +658,8 @@ impl Buffer {
         normalized: Rope,
     ) -> Buffer {
         let history = History::new(normalized);
-        let mut fragments = SumTree::new();
-        let mut insertions = SumTree::new();
+        let mut fragments = SumTree::new(&None);
+        let mut insertions = SumTree::default();
 
         let mut lamport_clock = clock::Lamport::new(replica_id);
         let mut version = clock::Global::new();
@@ -772,7 +776,7 @@ impl Buffer {
 
         let mut new_ropes =
             RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
-        let mut old_fragments = self.fragments.cursor::<FragmentTextSummary>();
+        let mut old_fragments = self.fragments.cursor::<FragmentTextSummary>(&None);
         let mut new_fragments =
             old_fragments.slice(&edits.peek().unwrap().0.start, Bias::Right, &None);
         new_ropes.append(new_fragments.summary().text);
@@ -992,7 +996,7 @@ impl Buffer {
         let mut insertion_offset = 0;
         let mut new_ropes =
             RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
-        let mut old_fragments = self.fragments.cursor::<(VersionedFullOffset, usize)>();
+        let mut old_fragments = self.fragments.cursor::<(VersionedFullOffset, usize)>(&cx);
         let mut new_fragments = old_fragments.slice(
             &VersionedFullOffset::Offset(ranges[0].start),
             Bias::Left,
@@ -1185,7 +1189,7 @@ impl Buffer {
 
         // Get all of the fragments corresponding to these insertion slices.
         let mut fragment_ids = Vec::new();
-        let mut insertions_cursor = self.insertions.cursor::<InsertionFragmentKey>();
+        let mut insertions_cursor = self.insertions.cursor::<InsertionFragmentKey>(&());
         for insertion_slice in &insertion_slices {
             if insertion_slice.insertion_id != insertions_cursor.start().timestamp
                 || insertion_slice.range.start > insertions_cursor.start().split_offset
@@ -1217,8 +1221,8 @@ impl Buffer {
         self.snapshot.undo_map.insert(undo);
 
         let mut edits = Patch::default();
-        let mut old_fragments = self.fragments.cursor::<(Option<&Locator>, usize)>();
-        let mut new_fragments = SumTree::new();
+        let mut old_fragments = self.fragments.cursor::<(Option<&Locator>, usize)>(&None);
+        let mut new_fragments = SumTree::new(&None);
         let mut new_ropes =
             RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
 
@@ -1455,7 +1459,7 @@ impl Buffer {
         D: TextDimension,
     {
         // get fragment ranges
-        let mut cursor = self.fragments.cursor::<(Option<&Locator>, usize)>();
+        let mut cursor = self.fragments.cursor::<(Option<&Locator>, usize)>(&None);
         let offset_ranges = self
             .fragment_ids_for_edits(transaction.edit_ids.iter())
             .into_iter()
@@ -1485,7 +1489,7 @@ impl Buffer {
             });
 
         // convert to the desired text dimension.
-        let mut position = D::default();
+        let mut position = D::zero(&());
         let mut rope_cursor = self.visible_text.cursor(0);
         disjoint_ranges.map(move |range| {
             position.add_assign(&rope_cursor.summary(range.start));
@@ -1665,8 +1669,8 @@ impl Buffer {
             );
         }
 
-        let mut cursor = self.snapshot.fragments.cursor::<Option<&Locator>>();
-        for insertion_fragment in self.snapshot.insertions.cursor::<()>() {
+        let mut cursor = self.snapshot.fragments.cursor::<Option<&Locator>>(&None);
+        for insertion_fragment in self.snapshot.insertions.cursor::<()>(&()) {
             cursor.seek(&Some(&insertion_fragment.fragment_id), Bias::Left, &None);
             let fragment = cursor.item().unwrap();
             assert_eq!(insertion_fragment.fragment_id, fragment.id);
@@ -1783,7 +1787,7 @@ impl BufferSnapshot {
 
         let mut cursor = self
             .fragments
-            .filter::<_, FragmentTextSummary>(move |summary| {
+            .filter::<_, FragmentTextSummary>(&None, move |summary| {
                 !version.observed_all(&summary.max_version)
             });
         cursor.next(&None);
@@ -2110,14 +2114,14 @@ impl BufferSnapshot {
         A: 'a + IntoIterator<Item = (&'a Anchor, T)>,
     {
         let anchors = anchors.into_iter();
-        let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>();
-        let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, usize)>();
+        let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>(&());
+        let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, usize)>(&None);
         let mut text_cursor = self.visible_text.cursor(0);
-        let mut position = D::default();
+        let mut position = D::zero(&());
 
         anchors.map(move |(anchor, payload)| {
             if *anchor == Anchor::MIN {
-                return (D::default(), payload);
+                return (D::zero(&()), payload);
             } else if *anchor == Anchor::MAX {
                 return (D::from_text_summary(&self.visible_text.summary()), payload);
             }
@@ -2159,7 +2163,7 @@ impl BufferSnapshot {
         D: TextDimension,
     {
         if *anchor == Anchor::MIN {
-            D::default()
+            D::zero(&())
         } else if *anchor == Anchor::MAX {
             D::from_text_summary(&self.visible_text.summary())
         } else {
@@ -2167,7 +2171,7 @@ impl BufferSnapshot {
                 timestamp: anchor.timestamp,
                 split_offset: anchor.offset,
             };
-            let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>();
+            let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>(&());
             insertion_cursor.seek(&anchor_key, anchor.bias, &());
             if let Some(insertion) = insertion_cursor.item() {
                 let comparison = sum_tree::KeyedItem::key(insertion).cmp(&anchor_key);
@@ -2192,7 +2196,7 @@ impl BufferSnapshot {
                 );
             };
 
-            let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, usize)>();
+            let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, usize)>(&None);
             fragment_cursor.seek(&Some(&insertion.fragment_id), Bias::Left, &None);
             let fragment = fragment_cursor.item().unwrap();
             let mut fragment_offset = fragment_cursor.start().1;
@@ -2213,7 +2217,7 @@ impl BufferSnapshot {
                 timestamp: anchor.timestamp,
                 split_offset: anchor.offset,
             };
-            let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>();
+            let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>(&());
             insertion_cursor.seek(&anchor_key, anchor.bias, &());
             if let Some(insertion) = insertion_cursor.item() {
                 let comparison = sum_tree::KeyedItem::key(insertion).cmp(&anchor_key);
@@ -2263,7 +2267,7 @@ impl BufferSnapshot {
         } else if bias == Bias::Right && offset == self.len() {
             Anchor::MAX
         } else {
-            let mut fragment_cursor = self.fragments.cursor::<usize>();
+            let mut fragment_cursor = self.fragments.cursor::<usize>(&None);
             fragment_cursor.seek(&offset, bias, &None);
             let fragment = fragment_cursor.item().unwrap();
             let overshoot = offset - *fragment_cursor.start();
@@ -2341,15 +2345,15 @@ impl BufferSnapshot {
         let fragments_cursor = if *since == self.version {
             None
         } else {
-            let mut cursor = self
-                .fragments
-                .filter(move |summary| !since.observed_all(&summary.max_version));
+            let mut cursor = self.fragments.filter(&None, move |summary| {
+                !since.observed_all(&summary.max_version)
+            });
             cursor.next(&None);
             Some(cursor)
         };
         let mut cursor = self
             .fragments
-            .cursor::<(Option<&Locator>, FragmentTextSummary)>();
+            .cursor::<(Option<&Locator>, FragmentTextSummary)>(&None);
 
         let start_fragment_id = self.fragment_id_for_anchor(&range.start);
         cursor.seek(&Some(start_fragment_id), Bias::Left, &None);
@@ -2371,8 +2375,8 @@ impl BufferSnapshot {
             fragments_cursor,
             undos: &self.undo_map,
             since,
-            old_end: Default::default(),
-            new_end: Default::default(),
+            old_end: D::zero(&()),
+            new_end: D::zero(&()),
             range: (start_fragment_id, range.start.offset)..(end_fragment_id, range.end.offset),
             buffer_id: self.remote_id,
         }
@@ -2382,9 +2386,9 @@ impl BufferSnapshot {
         if *since != self.version {
             let start_fragment_id = self.fragment_id_for_anchor(&range.start);
             let end_fragment_id = self.fragment_id_for_anchor(&range.end);
-            let mut cursor = self
-                .fragments
-                .filter::<_, usize>(move |summary| !since.observed_all(&summary.max_version));
+            let mut cursor = self.fragments.filter::<_, usize>(&None, move |summary| {
+                !since.observed_all(&summary.max_version)
+            });
             cursor.next(&None);
             while let Some(fragment) = cursor.item() {
                 if fragment.id > *end_fragment_id {
@@ -2405,9 +2409,9 @@ impl BufferSnapshot {
 
     pub fn has_edits_since(&self, since: &clock::Global) -> bool {
         if *since != self.version {
-            let mut cursor = self
-                .fragments
-                .filter::<_, usize>(move |summary| !since.observed_all(&summary.max_version));
+            let mut cursor = self.fragments.filter::<_, usize>(&None, move |summary| {
+                !since.observed_all(&summary.max_version)
+            });
             cursor.next(&None);
             while let Some(fragment) = cursor.item() {
                 let was_visible = fragment.was_visible(since, &self.undo_map);
@@ -2644,6 +2648,10 @@ impl sum_tree::Item for Fragment {
 impl sum_tree::Summary for FragmentSummary {
     type Context = Option<clock::Global>;
 
+    fn zero(_cx: &Self::Context) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, other: &Self, _: &Self::Context) {
         self.max_id.assign(&other.max_id);
         self.text.visible += &other.text.visible;
@@ -2704,6 +2712,10 @@ impl InsertionFragment {
 impl sum_tree::Summary for InsertionFragmentKey {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &()) {
         *self = *summary;
     }
@@ -2736,18 +2748,30 @@ impl ops::Sub for FullOffset {
 }
 
 impl<'a> sum_tree::Dimension<'a, FragmentSummary> for usize {
+    fn zero(_: &Option<clock::Global>) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) {
         *self += summary.text.visible;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FullOffset {
+    fn zero(_: &Option<clock::Global>) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) {
         self.0 += summary.text.visible + summary.text.deleted;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, FragmentSummary> for Option<&'a Locator> {
+    fn zero(_: &Option<clock::Global>) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a FragmentSummary, _: &Option<clock::Global>) {
         *self = Some(&summary.max_id);
     }
@@ -2786,6 +2810,10 @@ impl Default for VersionedFullOffset {
 }
 
 impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedFullOffset {
+    fn zero(_cx: &Option<clock::Global>) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a FragmentSummary, cx: &Option<clock::Global>) {
         if let Self::Offset(offset) = self {
             let version = cx.as_ref().unwrap();

crates/text/src/undo_map.rs 🔗

@@ -33,6 +33,10 @@ struct UndoMapKey {
 impl sum_tree::Summary for UndoMapKey {
     type Context = ();
 
+    fn zero(_cx: &Self::Context) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &Self::Context) {
         *self = cmp::max(*self, *summary);
     }
@@ -62,9 +66,8 @@ impl UndoMap {
     pub fn is_undone(&self, edit_id: clock::Lamport) -> bool {
         self.undo_count(edit_id) % 2 == 1
     }
-
     pub fn was_undone(&self, edit_id: clock::Lamport, version: &clock::Global) -> bool {
-        let mut cursor = self.0.cursor::<UndoMapKey>();
+        let mut cursor = self.0.cursor::<UndoMapKey>(&());
         cursor.seek(
             &UndoMapKey {
                 edit_id,
@@ -89,7 +92,7 @@ impl UndoMap {
     }
 
     pub fn undo_count(&self, edit_id: clock::Lamport) -> u32 {
-        let mut cursor = self.0.cursor::<UndoMapKey>();
+        let mut cursor = self.0.cursor::<UndoMapKey>(&());
         cursor.seek(
             &UndoMapKey {
                 edit_id,

crates/worktree/src/worktree.rs 🔗

@@ -2049,7 +2049,7 @@ impl Snapshot {
     fn delete_entry(&mut self, entry_id: ProjectEntryId) -> Option<Arc<Path>> {
         let removed_entry = self.entries_by_id.remove(&entry_id, &())?;
         self.entries_by_path = {
-            let mut cursor = self.entries_by_path.cursor::<TraversalProgress>();
+            let mut cursor = self.entries_by_path.cursor::<TraversalProgress>(&());
             let mut new_entries_by_path =
                 cursor.slice(&TraversalTarget::Path(&removed_entry.path), Bias::Left, &());
             while let Some(entry) = cursor.item() {
@@ -2192,7 +2192,7 @@ impl Snapshot {
         include_ignored: bool,
         start_offset: usize,
     ) -> Traversal {
-        let mut cursor = self.entries_by_path.cursor();
+        let mut cursor = self.entries_by_path.cursor(&());
         cursor.seek(
             &TraversalTarget::Count {
                 count: start_offset,
@@ -2302,7 +2302,7 @@ impl Snapshot {
     pub fn propagate_git_statuses(&self, result: &mut [Entry]) {
         let mut cursor = self
             .entries_by_path
-            .cursor::<(TraversalProgress, GitStatuses)>();
+            .cursor::<(TraversalProgress, GitStatuses)>(&());
         let mut entry_stack = Vec::<(usize, GitStatuses)>::new();
 
         let mut result_ix = 0;
@@ -2358,13 +2358,13 @@ impl Snapshot {
     pub fn paths(&self) -> impl Iterator<Item = &Arc<Path>> {
         let empty_path = Path::new("");
         self.entries_by_path
-            .cursor::<()>()
+            .cursor::<()>(&())
             .filter(move |entry| entry.path.as_ref() != empty_path)
             .map(|entry| &entry.path)
     }
 
     pub fn child_entries<'a>(&'a self, parent_path: &'a Path) -> ChildEntriesIter<'a> {
-        let mut cursor = self.entries_by_path.cursor();
+        let mut cursor = self.entries_by_path.cursor(&());
         cursor.seek(&TraversalTarget::Path(parent_path), Bias::Right, &());
         let traversal = Traversal {
             cursor,
@@ -2581,7 +2581,7 @@ impl LocalSnapshot {
     #[cfg(test)]
     pub(crate) fn expanded_entries(&self) -> impl Iterator<Item = &Entry> {
         self.entries_by_path
-            .cursor::<()>()
+            .cursor::<()>(&())
             .filter(|entry| entry.kind == EntryKind::Dir && (entry.is_external || entry.is_ignored))
     }
 
@@ -2591,11 +2591,11 @@ impl LocalSnapshot {
 
         assert_eq!(
             self.entries_by_path
-                .cursor::<()>()
+                .cursor::<()>(&())
                 .map(|e| (&e.path, e.id))
                 .collect::<Vec<_>>(),
             self.entries_by_id
-                .cursor::<()>()
+                .cursor::<()>(&())
                 .map(|e| (&e.path, e.id))
                 .collect::<collections::BTreeSet<_>>()
                 .into_iter()
@@ -2605,7 +2605,7 @@ impl LocalSnapshot {
 
         let mut files = self.files(true, 0);
         let mut visible_files = self.files(false, 0);
-        for entry in self.entries_by_path.cursor::<()>() {
+        for entry in self.entries_by_path.cursor::<()>(&()) {
             if entry.is_file() {
                 assert_eq!(files.next().unwrap().inode, entry.inode);
                 if !entry.is_ignored && !entry.is_external {
@@ -2633,7 +2633,7 @@ impl LocalSnapshot {
 
         let dfs_paths_via_iter = self
             .entries_by_path
-            .cursor::<()>()
+            .cursor::<()>(&())
             .map(|e| e.path.as_ref())
             .collect::<Vec<_>>();
         assert_eq!(bfs_paths, dfs_paths_via_iter);
@@ -2679,7 +2679,7 @@ impl LocalSnapshot {
     #[cfg(test)]
     pub fn entries_without_ids(&self, include_ignored: bool) -> Vec<(&Path, u64, bool)> {
         let mut paths = Vec::new();
-        for entry in self.entries_by_path.cursor::<()>() {
+        for entry in self.entries_by_path.cursor::<()>(&()) {
             if include_ignored || !entry.is_ignored {
                 paths.push((entry.path.as_ref(), entry.inode, entry.is_ignored));
             }
@@ -2839,7 +2839,10 @@ impl BackgroundScannerState {
         let mut new_entries;
         let removed_entries;
         {
-            let mut cursor = self.snapshot.entries_by_path.cursor::<TraversalProgress>();
+            let mut cursor = self
+                .snapshot
+                .entries_by_path
+                .cursor::<TraversalProgress>(&());
             new_entries = cursor.slice(&TraversalTarget::Path(path), Bias::Left, &());
             removed_entries = cursor.slice(&TraversalTarget::PathSuccessor(path), Bias::Left, &());
             new_entries.append(cursor.suffix(&()), &());
@@ -2847,7 +2850,7 @@ impl BackgroundScannerState {
         self.snapshot.entries_by_path = new_entries;
 
         let mut removed_ids = Vec::with_capacity(removed_entries.summary().count);
-        for entry in removed_entries.cursor::<()>() {
+        for entry in removed_entries.cursor::<()>(&()) {
             match self.removed_entries.entry(entry.inode) {
                 hash_map::Entry::Occupied(mut e) => {
                     let prev_removed_entry = e.get_mut();
@@ -3403,6 +3406,10 @@ impl Default for EntrySummary {
 impl sum_tree::Summary for EntrySummary {
     type Context = ();
 
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, rhs: &Self, _: &()) {
         self.max_path = rhs.max_path.clone();
         self.count += rhs.count;
@@ -3445,12 +3452,20 @@ struct PathEntrySummary {
 impl sum_tree::Summary for PathEntrySummary {
     type Context = ();
 
+    fn zero(_cx: &Self::Context) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &Self, _: &Self::Context) {
         self.max_id = summary.max_id;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, PathEntrySummary> for ProjectEntryId {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a PathEntrySummary, _: &()) {
         *self = summary.max_id;
     }
@@ -3466,6 +3481,10 @@ impl Default for PathKey {
 }
 
 impl<'a> sum_tree::Dimension<'a, EntrySummary> for PathKey {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
         self.0 = summary.max_path.clone();
     }
@@ -4629,8 +4648,8 @@ impl BackgroundScanner {
         // Identify which paths have changed. Use the known set of changed
         // parent paths to optimize the search.
         let mut changes = Vec::new();
-        let mut old_paths = old_snapshot.entries_by_path.cursor::<PathKey>();
-        let mut new_paths = new_snapshot.entries_by_path.cursor::<PathKey>();
+        let mut old_paths = old_snapshot.entries_by_path.cursor::<PathKey>(&());
+        let mut new_paths = new_snapshot.entries_by_path.cursor::<PathKey>(&());
         let mut last_newly_loaded_dir_path = None;
         old_paths.next(&());
         new_paths.next(&());
@@ -4981,6 +5000,10 @@ impl<'a> TraversalProgress<'a> {
 }
 
 impl<'a> sum_tree::Dimension<'a, EntrySummary> for TraversalProgress<'a> {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
         self.max_path = summary.max_path.as_ref();
         self.count += summary.count;
@@ -5030,6 +5053,10 @@ impl Sub for GitStatuses {
 }
 
 impl<'a> sum_tree::Dimension<'a, EntrySummary> for GitStatuses {
+    fn zero(_cx: &()) -> Self {
+        Default::default()
+    }
+
     fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
         *self += summary.statuses
     }
@@ -5050,7 +5077,7 @@ impl<'a> Traversal<'a> {
         include_ignored: bool,
         start_path: &Path,
     ) -> Self {
-        let mut cursor = entries.cursor();
+        let mut cursor = entries.cursor(&());
         cursor.seek(&TraversalTarget::Path(start_path), Bias::Left, &());
         let mut traversal = Self {
             cursor,