sum_tree: Reduce `Cursor` size for contextless summary types (#38776)

Lukas Wirth created

This reduces the size of cursor by a usize when the summary does not
require a context making Cursor usages and constructions slightly more
efficient.

This change is a bit annoying though, as Rust has no means of
specializing, so this uses a `ContextlessSummary` trait with a blanket
impl while turning the `Context` into a GAT `Context<'a>`. This means
`Summary` implies are a bit more verbose now while contextless ones are
slimmer. It does come with the downside that the lifetime in the GAT is
always considered invariant, so some lifetime splitting occurred due to
that.


 ```
push/4096               time:   [352.65 µs 360.87 µs 367.80 µs]
                        thrpt:  [10.621 MiB/s 10.825 MiB/s 11.077 MiB/s]
                 change:
time: [-2.6633% -1.3640% -0.0561%] (p = 0.05 < 0.05)
                        thrpt:  [+0.0561% +1.3828% +2.7361%]
                        Change within noise threshold.
Found 16 outliers among 100 measurements (16.00%)
  7 (7.00%) low severe
  3 (3.00%) low mild
  2 (2.00%) high mild
  4 (4.00%) high severe
push/65536              time:   [1.2917 ms 1.2949 ms 1.2979 ms]
                        thrpt:  [48.156 MiB/s 48.267 MiB/s 48.387 MiB/s]
                 change:
time: [+1.4428% +1.9844% +2.5299%] (p = 0.00 < 0.05)
                        thrpt:  [-2.4675% -1.9458% -1.4223%]
                        Performance has regressed.
Found 3 outliers among 100 measurements (3.00%)
  1 (1.00%) low severe
  1 (1.00%) low mild
  1 (1.00%) high severe

append/4096             time:   [677.87 ns 678.87 ns 679.83 ns]
                        thrpt:  [5.6112 GiB/s 5.6192 GiB/s 5.6274 GiB/s]
                 change:
time: [-0.8924% -0.5017% -0.1705%] (p = 0.00 < 0.05)
                        thrpt:  [+0.1708% +0.5043% +0.9004%]
                        Change within noise threshold.
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) low mild
  1 (1.00%) high mild
append/65536            time:   [9.3275 µs 9.3406 µs 9.3536 µs]
                        thrpt:  [6.5253 GiB/s 6.5344 GiB/s 6.5435 GiB/s]
                 change:
time: [+0.5409% +0.7215% +0.9054%] (p = 0.00 < 0.05)
                        thrpt:  [-0.8973% -0.7163% -0.5380%]
                        Change within noise threshold.

slice/4096              time:   [27.673 µs 27.791 µs 27.907 µs]
                        thrpt:  [139.97 MiB/s 140.56 MiB/s 141.16 MiB/s]
                 change:
time: [-1.1065% -0.6725% -0.2429%] (p = 0.00 < 0.05)
                        thrpt:  [+0.2435% +0.6770% +1.1189%]
                        Change within noise threshold.
Found 5 outliers among 100 measurements (5.00%)
  4 (4.00%) low mild
  1 (1.00%) high mild
slice/65536             time:   [507.55 µs 517.40 µs 535.60 µs]
                        thrpt:  [116.69 MiB/s 120.80 MiB/s 123.14 MiB/s]
                 change:
time: [-1.3489% +0.0599% +2.2591%] (p = 0.96 > 0.05)
                        thrpt:  [-2.2092% -0.0598% +1.3674%]
                        No change in performance detected.
Found 8 outliers among 100 measurements (8.00%)
  5 (5.00%) low mild
  2 (2.00%) high mild
  1 (1.00%) high severe

bytes_in_range/4096     time:   [3.3917 µs 3.4108 µs 3.4313 µs]
                        thrpt:  [1.1117 GiB/s 1.1184 GiB/s 1.1247 GiB/s]
                 change:
time: [-5.3466% -4.7193% -4.1262%] (p = 0.00 < 0.05)
                        thrpt:  [+4.3038% +4.9531% +5.6487%]
                        Performance has improved.
Found 6 outliers among 100 measurements (6.00%)
  1 (1.00%) low mild
  5 (5.00%) high mild
bytes_in_range/65536    time:   [88.175 µs 88.613 µs 89.111 µs]
                        thrpt:  [701.37 MiB/s 705.31 MiB/s 708.82 MiB/s]
                 change:
time: [-0.6935% +0.3769% +1.4655%] (p = 0.50 > 0.05)
                        thrpt:  [-1.4443% -0.3755% +0.6984%]
                        No change in performance detected.
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild

chars/4096              time:   [678.70 ns 680.38 ns 682.08 ns]
                        thrpt:  [5.5927 GiB/s 5.6067 GiB/s 5.6206 GiB/s]
                 change:
time: [-0.6969% -0.2755% +0.1485%] (p = 0.20 > 0.05)
                        thrpt:  [-0.1483% +0.2763% +0.7018%]
                        No change in performance detected.
Found 9 outliers among 100 measurements (9.00%)
  5 (5.00%) low mild
  4 (4.00%) high mild
chars/65536             time:   [12.720 µs 12.775 µs 12.830 µs]
                        thrpt:  [4.7573 GiB/s 4.7778 GiB/s 4.7983 GiB/s]
                 change:
time: [-0.6172% -0.1110% +0.4179%] (p = 0.68 > 0.05)
                        thrpt:  [-0.4162% +0.1112% +0.6211%]
                        No change in performance detected.
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) low mild
  1 (1.00%) high mild

clip_point/4096         time:   [33.240 µs 33.310 µs 33.394 µs]
                        thrpt:  [116.98 MiB/s 117.27 MiB/s 117.52 MiB/s]
                 change:
time: [-2.8892% -2.6305% -2.3438%] (p = 0.00 < 0.05)
                        thrpt:  [+2.4000% +2.7015% +2.9751%]
                        Performance has improved.
Found 12 outliers among 100 measurements (12.00%)
  1 (1.00%) low mild
  4 (4.00%) high mild
  7 (7.00%) high severe
clip_point/65536        time:   [1.6531 ms 1.6586 ms 1.6640 ms]
                        thrpt:  [37.560 MiB/s 37.683 MiB/s 37.808 MiB/s]
                 change:
time: [-6.6381% -5.9395% -5.2680%] (p = 0.00 < 0.05)
                        thrpt:  [+5.5610% +6.3146% +7.1100%]
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  1 (1.00%) low mild
  2 (2.00%) high mild
  4 (4.00%) high severe

point_to_offset/4096    time:   [11.586 µs 11.603 µs 11.621 µs]
                        thrpt:  [336.15 MiB/s 336.67 MiB/s 337.16 MiB/s]
                 change:
time: [-14.289% -14.111% -13.939%] (p = 0.00 < 0.05)
                        thrpt:  [+16.197% +16.429% +16.672%]
                        Performance has improved.
Found 12 outliers among 100 measurements (12.00%)
  3 (3.00%) low severe
  5 (5.00%) low mild
  4 (4.00%) high mild
point_to_offset/65536   time:   [527.74 µs 532.08 µs 536.51 µs]
                        thrpt:  [116.49 MiB/s 117.46 MiB/s 118.43 MiB/s]
                 change:
time: [-6.7825% -4.6235% -2.3533%] (p = 0.00 < 0.05)
                        thrpt:  [+2.4100% +4.8477% +7.2760%]
                        Performance has improved.
Found 8 outliers among 100 measurements (8.00%)
  4 (4.00%) high mild
  4 (4.00%) high severe

cursor/4096             time:   [16.154 µs 16.192 µs 16.232 µs]
                        thrpt:  [240.66 MiB/s 241.24 MiB/s 241.81 MiB/s]
                 change:
time: [-3.2536% -2.9145% -2.5526%] (p = 0.00 < 0.05)
                        thrpt:  [+2.6194% +3.0019% +3.3630%]
                        Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
  1 (1.00%) low mild
  2 (2.00%) high mild
  2 (2.00%) high severe
cursor/65536            time:   [509.60 µs 511.24 µs 512.93 µs]
                        thrpt:  [121.85 MiB/s 122.25 MiB/s 122.65 MiB/s]
                 change:
time: [-7.3677% -6.6017% -5.7840%] (p = 0.00 < 0.05)
                        thrpt:  [+6.1391% +7.0683% +7.9537%]
                        Performance has improved.
Found 6 outliers among 100 measurements (6.00%)
  3 (3.00%) high mild
  3 (3.00%) high severe
```
Release Notes:

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

Change summary

crates/buffer_diff/src/buffer_diff.rs          |   6 
crates/editor/src/display_map/block_map.rs     |  70 ++--
crates/editor/src/display_map/crease_map.rs    |   4 
crates/editor/src/display_map/fold_map.rs      |  84 +++---
crates/editor/src/display_map/inlay_map.rs     |  74 ++---
crates/editor/src/display_map/wrap_map.rs      |  74 ++--
crates/editor/src/git/blame.rs                 |  32 +-
crates/git/src/status.rs                       |   8 
crates/gpui/src/elements/list.rs               |  58 ++--
crates/language/src/diagnostic_set.rs          |   6 
crates/language/src/syntax_map.rs              |   4 
crates/multi_buffer/src/multi_buffer.rs        | 252 +++++++++---------
crates/notifications/src/notification_store.rs |  30 +-
crates/project/src/git_store.rs                |  14 
crates/project/src/git_store/git_traversal.rs  |   7 
crates/rope/benches/rope_benchmark.rs          |  30 ++
crates/rope/src/rope.rs                        | 118 ++++----
crates/rope/src/unclipped.rs                   |   8 
crates/sum_tree/src/cursor.rs                  | 133 +++++----
crates/sum_tree/src/sum_tree.rs                | 272 ++++++++++---------
crates/sum_tree/src/tree_map.rs                |  56 +--
crates/text/src/locator.rs                     |  10 
crates/text/src/operation_queue.rs             |  18 
crates/text/src/text.rs                        |  48 +-
crates/text/src/undo_map.rs                    |  16 
crates/worktree/src/worktree.rs                | 160 +++++------
26 files changed, 809 insertions(+), 783 deletions(-)

Detailed changes

crates/buffer_diff/src/buffer_diff.rs 🔗

@@ -111,13 +111,13 @@ impl sum_tree::Item for PendingHunk {
 }
 
 impl sum_tree::Summary for DiffHunkSummary {
-    type Context = text::BufferSnapshot;
+    type Context<'a> = &'a text::BufferSnapshot;
 
-    fn zero(_cx: &Self::Context) -> Self {
+    fn zero(_cx: Self::Context<'_>) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
+    fn add_summary(&mut self, other: &Self, buffer: Self::Context<'_>) {
         self.buffer_range.start = self
             .buffer_range
             .start

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

@@ -22,7 +22,7 @@ use std::{
         atomic::{AtomicUsize, Ordering::SeqCst},
     },
 };
-use sum_tree::{Bias, Dimensions, SumTree, Summary, TreeMap};
+use sum_tree::{Bias, ContextLessSummary, Dimensions, SumTree, TreeMap};
 use text::{BufferId, Edit};
 use ui::ElementId;
 
@@ -433,7 +433,7 @@ struct TransformSummary {
 }
 
 pub struct BlockChunks<'a> {
-    transforms: sum_tree::Cursor<'a, Transform, Dimensions<BlockRow, WrapRow>>,
+    transforms: sum_tree::Cursor<'a, 'static, Transform, Dimensions<BlockRow, WrapRow>>,
     input_chunks: wrap_map::WrapChunks<'a>,
     input_chunk: Chunk<'a>,
     output_row: u32,
@@ -443,7 +443,7 @@ pub struct BlockChunks<'a> {
 
 #[derive(Clone)]
 pub struct BlockRows<'a> {
-    transforms: sum_tree::Cursor<'a, Transform, Dimensions<BlockRow, WrapRow>>,
+    transforms: sum_tree::Cursor<'a, 'static, Transform, Dimensions<BlockRow, WrapRow>>,
     input_rows: wrap_map::WrapRows<'a>,
     output_row: BlockRow,
     started: bool,
@@ -527,7 +527,7 @@ impl BlockMap {
 
         let mut transforms = self.transforms.borrow_mut();
         let mut new_transforms = SumTree::default();
-        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();
@@ -541,20 +541,20 @@ impl BlockMap {
             // * Isomorphic transforms that end *at* the start of the edit
             // * Below blocks that end at the start of the edit
             // However, if we hit a replace block that ends at the start of the edit we want to reconstruct it.
-            new_transforms.append(cursor.slice(&old_start, Bias::Left), &());
+            new_transforms.append(cursor.slice(&old_start, Bias::Left), ());
             if let Some(transform) = cursor.item()
                 && transform.summary.input_rows > 0
                 && cursor.end() == old_start
                 && transform.block.as_ref().is_none_or(|b| !b.is_replacement())
             {
                 // Preserve the transform (push and next)
-                new_transforms.push(transform.clone(), &());
+                new_transforms.push(transform.clone(), ());
                 cursor.next();
 
                 // Preserve below blocks at end of edit
                 while let Some(transform) = cursor.item() {
                     if transform.block.as_ref().is_some_and(|b| b.place_below()) {
-                        new_transforms.push(transform.clone(), &());
+                        new_transforms.push(transform.clone(), ());
                         cursor.next();
                     } else {
                         break;
@@ -720,7 +720,7 @@ impl BlockMap {
                         summary,
                         block: Some(block),
                     },
-                    &(),
+                    (),
                 );
             }
 
@@ -731,7 +731,7 @@ impl BlockMap {
             push_isomorphic(&mut new_transforms, rows_after_last_block, wrap_snapshot);
         }
 
-        new_transforms.append(cursor.suffix(), &());
+        new_transforms.append(cursor.suffix(), ());
         debug_assert_eq!(
             new_transforms.summary().input_rows,
             wrap_snapshot.max_point().row() + 1
@@ -925,11 +925,11 @@ fn push_isomorphic(tree: &mut SumTree<Transform>, rows: u32, wrap_snapshot: &Wra
     tree.update_last(
         |last_transform| {
             if last_transform.block.is_none() {
-                last_transform.summary.add_summary(&summary, &());
+                last_transform.summary.add_summary(&summary);
                 merged = true;
             }
         },
-        &(),
+        (),
     );
     if !merged {
         tree.push(
@@ -937,7 +937,7 @@ fn push_isomorphic(tree: &mut SumTree<Transform>, rows: u32, wrap_snapshot: &Wra
                 summary,
                 block: None,
             },
-            &(),
+            (),
         );
     }
 }
@@ -997,7 +997,7 @@ impl BlockMapReader<'_> {
                 .unwrap_or(self.wrap_snapshot.max_point().row() + 1),
         );
 
-        let mut cursor = self.transforms.cursor::<Dimensions<WrapRow, BlockRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<WrapRow, BlockRow>>(());
         cursor.seek(&start_wrap_row, Bias::Left);
         while let Some(transform) = cursor.item() {
             if cursor.start().0 > end_wrap_row {
@@ -1313,7 +1313,7 @@ impl BlockSnapshot {
     ) -> BlockChunks<'a> {
         let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows);
 
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
         cursor.seek(&BlockRow(rows.start), Bias::Right);
         let transform_output_start = cursor.start().0.0;
         let transform_input_start = cursor.start().1.0;
@@ -1345,7 +1345,7 @@ impl BlockSnapshot {
     }
 
     pub(super) fn row_infos(&self, start_row: BlockRow) -> BlockRows<'_> {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
         cursor.seek(&start_row, Bias::Right);
         let Dimensions(output_start, input_start, _) = cursor.start();
         let overshoot = if cursor
@@ -1366,7 +1366,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();
@@ -1397,7 +1397,7 @@ impl BlockSnapshot {
 
     pub fn sticky_header_excerpt(&self, position: f32) -> Option<StickyHeaderExcerpt<'_>> {
         let top_row = position as u32;
-        let mut cursor = self.transforms.cursor::<BlockRow>(&());
+        let mut cursor = self.transforms.cursor::<BlockRow>(());
         cursor.seek(&BlockRow(top_row), Bias::Right);
 
         while let Some(transform) = cursor.item() {
@@ -1436,7 +1436,7 @@ impl BlockSnapshot {
         };
         let wrap_row = WrapRow(wrap_point.row());
 
-        let mut cursor = self.transforms.cursor::<WrapRow>(&());
+        let mut cursor = self.transforms.cursor::<WrapRow>(());
         cursor.seek(&wrap_row, Bias::Left);
 
         while let Some(transform) = cursor.item() {
@@ -1464,7 +1464,7 @@ impl BlockSnapshot {
     }
 
     pub fn longest_row_in_range(&self, range: Range<BlockRow>) -> BlockRow {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
         cursor.seek(&range.start, Bias::Right);
 
         let mut longest_row = range.start;
@@ -1515,7 +1515,7 @@ impl BlockSnapshot {
     }
 
     pub(super) fn line_len(&self, row: BlockRow) -> u32 {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
         cursor.seek(&BlockRow(row.0), Bias::Right);
         if let Some(transform) = cursor.item() {
             let Dimensions(output_start, input_start, _) = cursor.start();
@@ -1533,13 +1533,13 @@ impl BlockSnapshot {
     }
 
     pub(super) fn is_block_line(&self, row: BlockRow) -> bool {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
         cursor.seek(&row, Bias::Right);
         cursor.item().is_some_and(|t| t.block.is_some())
     }
 
     pub(super) fn is_folded_buffer_header(&self, row: BlockRow) -> bool {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
         cursor.seek(&row, Bias::Right);
         let Some(transform) = cursor.item() else {
             return false;
@@ -1551,7 +1551,7 @@ impl BlockSnapshot {
         let wrap_point = self
             .wrap_snapshot
             .make_wrap_point(Point::new(row.0, 0), Bias::Left);
-        let mut cursor = self.transforms.cursor::<Dimensions<WrapRow, BlockRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<WrapRow, BlockRow>>(());
         cursor.seek(&WrapRow(wrap_point.row()), Bias::Right);
         cursor.item().is_some_and(|transform| {
             transform
@@ -1562,7 +1562,7 @@ impl BlockSnapshot {
     }
 
     pub fn clip_point(&self, point: BlockPoint, bias: Bias) -> BlockPoint {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
         cursor.seek(&BlockRow(point.row), Bias::Right);
 
         let max_input_row = WrapRow(self.transforms.summary().input_rows);
@@ -1621,7 +1621,7 @@ impl BlockSnapshot {
     }
 
     pub fn to_block_point(&self, wrap_point: WrapPoint) -> BlockPoint {
-        let mut cursor = self.transforms.cursor::<Dimensions<WrapRow, BlockRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<WrapRow, BlockRow>>(());
         cursor.seek(&WrapRow(wrap_point.row()), Bias::Right);
         if let Some(transform) = cursor.item() {
             if transform.block.is_some() {
@@ -1639,7 +1639,7 @@ impl BlockSnapshot {
     }
 
     pub fn to_wrap_point(&self, block_point: BlockPoint, bias: Bias) -> WrapPoint {
-        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
         cursor.seek(&BlockRow(block_point.row), Bias::Right);
         if let Some(transform) = cursor.item() {
             match transform.block.as_ref() {
@@ -1848,19 +1848,17 @@ impl Iterator for BlockRows<'_> {
 impl sum_tree::Item for Transform {
     type Summary = TransformSummary;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         self.summary.clone()
     }
 }
 
-impl sum_tree::Summary for TransformSummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for TransformSummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &()) {
+    fn add_summary(&mut self, summary: &Self) {
         if summary.longest_row_chars > self.longest_row_chars {
             self.longest_row = self.output_rows + summary.longest_row;
             self.longest_row_chars = summary.longest_row_chars;
@@ -1871,21 +1869,21 @@ impl sum_tree::Summary for TransformSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for WrapRow {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    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 {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
         self.0 += summary.output_rows;
     }
 }

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

@@ -365,9 +365,9 @@ impl Default for ItemSummary {
 }
 
 impl sum_tree::Summary for ItemSummary {
-    type Context = MultiBufferSnapshot;
+    type Context<'a> = &'a MultiBufferSnapshot;
 
-    fn zero(_cx: &Self::Context) -> Self {
+    fn zero(_cx: Self::Context<'_>) -> Self {
         Default::default()
     }
 

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

@@ -100,7 +100,7 @@ impl FoldPoint {
     pub fn to_inlay_point(self, snapshot: &FoldSnapshot) -> InlayPoint {
         let mut cursor = snapshot
             .transforms
-            .cursor::<Dimensions<FoldPoint, InlayPoint>>(&());
+            .cursor::<Dimensions<FoldPoint, InlayPoint>>(());
         cursor.seek(&self, Bias::Right);
         let overshoot = self.0 - cursor.start().0.0;
         InlayPoint(cursor.start().1.0 + overshoot)
@@ -109,7 +109,7 @@ impl FoldPoint {
     pub fn to_offset(self, snapshot: &FoldSnapshot) -> FoldOffset {
         let mut cursor = snapshot
             .transforms
-            .cursor::<Dimensions<FoldPoint, TransformSummary>>(&());
+            .cursor::<Dimensions<FoldPoint, TransformSummary>>(());
         cursor.seek(&self, Bias::Right);
         let overshoot = self.0 - cursor.start().1.output.lines;
         let mut offset = cursor.start().1.output.len;
@@ -126,11 +126,11 @@ impl FoldPoint {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for FoldPoint {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
         self.0 += &summary.output.lines;
     }
 }
@@ -338,9 +338,9 @@ impl FoldMap {
                         },
                         placeholder: None,
                     },
-                    &(),
+                    (),
                 ),
-                inlay_snapshot: inlay_snapshot.clone(),
+                inlay_snapshot: inlay_snapshot,
                 version: 0,
                 fold_metadata_by_id: TreeMap::default(),
             },
@@ -382,7 +382,7 @@ impl FoldMap {
                 if !transform.is_fold() && prev_transform_isomorphic {
                     panic!(
                         "found adjacent isomorphic transforms: {:?}",
-                        self.snapshot.transforms.items(&())
+                        self.snapshot.transforms.items(())
                     );
                 }
                 prev_transform_isomorphic = !transform.is_fold();
@@ -413,7 +413,7 @@ impl FoldMap {
             let mut inlay_edits_iter = inlay_edits.iter().cloned().peekable();
 
             let mut new_transforms = SumTree::<Transform>::default();
-            let mut cursor = self.snapshot.transforms.cursor::<InlayOffset>(&());
+            let mut cursor = self.snapshot.transforms.cursor::<InlayOffset>(());
             cursor.seek(&InlayOffset(0), Bias::Right);
 
             while let Some(mut edit) = inlay_edits_iter.next() {
@@ -423,14 +423,14 @@ impl FoldMap {
                     new_transforms.update_last(
                         |transform| {
                             if !transform.is_fold() {
-                                transform.summary.add_summary(&item.summary, &());
+                                transform.summary.add_summary(&item.summary, ());
                                 cursor.next();
                             }
                         },
-                        &(),
+                        (),
                     );
                 }
-                new_transforms.append(cursor.slice(&edit.old.start, Bias::Left), &());
+                new_transforms.append(cursor.slice(&edit.old.start, Bias::Left), ());
                 edit.new.start -= edit.old.start - *cursor.start();
                 edit.old.start = *cursor.start();
 
@@ -544,7 +544,7 @@ impl FoldMap {
                                     },
                                 }),
                             },
-                            &(),
+                            (),
                         );
                     }
                 }
@@ -557,7 +557,7 @@ impl FoldMap {
                 }
             }
 
-            new_transforms.append(cursor.suffix(), &());
+            new_transforms.append(cursor.suffix(), ());
             if new_transforms.is_empty() {
                 let text_summary = inlay_snapshot.text_summary();
                 push_isomorphic(&mut new_transforms, text_summary);
@@ -570,9 +570,9 @@ impl FoldMap {
                 let mut old_transforms = self
                     .snapshot
                     .transforms
-                    .cursor::<Dimensions<InlayOffset, FoldOffset>>(&());
+                    .cursor::<Dimensions<InlayOffset, FoldOffset>>(());
                 let mut new_transforms =
-                    new_transforms.cursor::<Dimensions<InlayOffset, FoldOffset>>(&());
+                    new_transforms.cursor::<Dimensions<InlayOffset, FoldOffset>>(());
 
                 for mut edit in inlay_edits {
                     old_transforms.seek(&edit.old.start, Bias::Left);
@@ -657,7 +657,7 @@ impl FoldSnapshot {
 
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<FoldPoint, InlayPoint>>(&());
+            .cursor::<Dimensions<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;
@@ -708,7 +708,7 @@ impl FoldSnapshot {
     pub fn to_fold_point(&self, point: InlayPoint, bias: Bias) -> FoldPoint {
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<InlayPoint, FoldPoint>>(&());
+            .cursor::<Dimensions<InlayPoint, FoldPoint>>(());
         cursor.seek(&point, Bias::Right);
         if cursor.item().is_some_and(|t| t.is_fold()) {
             if bias == Bias::Left || point == cursor.start().0 {
@@ -744,7 +744,7 @@ impl FoldSnapshot {
         let fold_point = FoldPoint::new(start_row, 0);
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<FoldPoint, InlayPoint>>(&());
+            .cursor::<Dimensions<FoldPoint, InlayPoint>>(());
         cursor.seek(&fold_point, Bias::Left);
 
         let overshoot = fold_point.0 - cursor.start().0.0;
@@ -787,7 +787,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().is_some_and(|t| t.placeholder.is_some())
     }
@@ -796,7 +796,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() {
@@ -828,7 +828,7 @@ impl FoldSnapshot {
     ) -> FoldChunks<'a> {
         let mut transform_cursor = self
             .transforms
-            .cursor::<Dimensions<FoldOffset, InlayOffset>>(&());
+            .cursor::<Dimensions<FoldOffset, InlayOffset>>(());
         transform_cursor.seek(&range.start, Bias::Right);
 
         let inlay_start = {
@@ -893,7 +893,7 @@ impl FoldSnapshot {
     pub fn clip_point(&self, point: FoldPoint, bias: Bias) -> FoldPoint {
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<FoldPoint, InlayPoint>>(&());
+            .cursor::<Dimensions<FoldPoint, InlayPoint>>(());
         cursor.seek(&point, Bias::Right);
         if let Some(transform) = cursor.item() {
             let transform_start = cursor.start().0.0;
@@ -925,7 +925,7 @@ fn push_isomorphic(transforms: &mut SumTree<Transform>, summary: TextSummary) {
                 did_merge = true;
             }
         },
-        &(),
+        (),
     );
     if !did_merge {
         transforms.push(
@@ -936,7 +936,7 @@ fn push_isomorphic(transforms: &mut SumTree<Transform>, summary: TextSummary) {
                 },
                 placeholder: None,
             },
-            &(),
+            (),
         )
     }
 }
@@ -946,7 +946,7 @@ fn intersecting_folds<'a>(
     folds: &'a SumTree<Fold>,
     range: Range<usize>,
     inclusive: bool,
-) -> FilterCursor<'a, impl 'a + FnMut(&FoldSummary) -> bool, Fold, usize> {
+) -> FilterCursor<'a, 'a, impl 'a + FnMut(&FoldSummary) -> bool, Fold, usize> {
     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));
@@ -1062,19 +1062,17 @@ struct TransformSummary {
 impl sum_tree::Item for Transform {
     type Summary = TransformSummary;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         self.summary.clone()
     }
 }
 
-impl sum_tree::Summary for TransformSummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for TransformSummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, other: &Self, _: &()) {
+    fn add_summary(&mut self, other: &Self) {
         self.input += &other.input;
         self.output += &other.output;
     }
@@ -1161,13 +1159,13 @@ impl Default for FoldSummary {
 }
 
 impl sum_tree::Summary for FoldSummary {
-    type Context = MultiBufferSnapshot;
+    type Context<'a> = &'a MultiBufferSnapshot;
 
     fn zero(_cx: &MultiBufferSnapshot) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
+    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;
         }
@@ -1219,7 +1217,7 @@ impl<'a> sum_tree::Dimension<'a, FoldSummary> for usize {
 
 #[derive(Clone)]
 pub struct FoldRows<'a> {
-    cursor: Cursor<'a, Transform, Dimensions<FoldPoint, InlayPoint>>,
+    cursor: Cursor<'a, 'static, Transform, Dimensions<FoldPoint, InlayPoint>>,
     input_rows: InlayBufferRows<'a>,
     fold_point: FoldPoint,
 }
@@ -1340,7 +1338,7 @@ impl DerefMut for ChunkRendererContext<'_, '_> {
 }
 
 pub struct FoldChunks<'a> {
-    transform_cursor: Cursor<'a, Transform, Dimensions<FoldOffset, InlayOffset>>,
+    transform_cursor: Cursor<'a, 'static, Transform, Dimensions<FoldOffset, InlayOffset>>,
     inlay_chunks: InlayChunks<'a>,
     inlay_chunk: Option<(InlayOffset, InlayChunk<'a>)>,
     inlay_offset: InlayOffset,
@@ -1488,7 +1486,7 @@ impl FoldOffset {
     pub fn to_point(self, snapshot: &FoldSnapshot) -> FoldPoint {
         let mut cursor = snapshot
             .transforms
-            .cursor::<Dimensions<FoldOffset, TransformSummary>>(&());
+            .cursor::<Dimensions<FoldOffset, TransformSummary>>(());
         cursor.seek(&self, Bias::Right);
         let overshoot = if cursor.item().is_none_or(|t| t.is_fold()) {
             Point::new(0, (self.0 - cursor.start().0.0) as u32)
@@ -1504,7 +1502,7 @@ impl FoldOffset {
     pub fn to_inlay_offset(self, snapshot: &FoldSnapshot) -> InlayOffset {
         let mut cursor = snapshot
             .transforms
-            .cursor::<Dimensions<FoldOffset, InlayOffset>>(&());
+            .cursor::<Dimensions<FoldOffset, InlayOffset>>(());
         cursor.seek(&self, Bias::Right);
         let overshoot = self.0 - cursor.start().0.0;
         InlayOffset(cursor.start().1.0 + overshoot)
@@ -1534,31 +1532,31 @@ impl Sub for FoldOffset {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for FoldOffset {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    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 {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    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 {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
         self.0 += &summary.input.len;
     }
 }

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

@@ -108,7 +108,7 @@ impl Inlay {
 impl sum_tree::Item for Transform {
     type Summary = TransformSummary;
 
-    fn summary(&self, _: &()) -> Self::Summary {
+    fn summary(&self, _: ()) -> Self::Summary {
         match self {
             Transform::Isomorphic(summary) => TransformSummary {
                 input: *summary,
@@ -128,14 +128,12 @@ struct TransformSummary {
     output: TextSummary,
 }
 
-impl sum_tree::Summary for TransformSummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for TransformSummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, other: &Self, _: &()) {
+    fn add_summary(&mut self, other: &Self) {
         self.input += &other.input;
         self.output += &other.output;
     }
@@ -175,11 +173,11 @@ impl SubAssign for InlayOffset {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayOffset {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
         self.0 += &summary.output.len;
     }
 }
@@ -204,45 +202,45 @@ impl Sub for InlayPoint {
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayPoint {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    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 {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    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 {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
         *self += &summary.input.lines;
     }
 }
 
 #[derive(Clone)]
 pub struct InlayBufferRows<'a> {
-    transforms: Cursor<'a, Transform, Dimensions<InlayPoint, Point>>,
+    transforms: Cursor<'a, 'static, Transform, Dimensions<InlayPoint, Point>>,
     buffer_rows: MultiBufferRows<'a>,
     inlay_row: u32,
     max_buffer_row: MultiBufferRow,
 }
 
 pub struct InlayChunks<'a> {
-    transforms: Cursor<'a, Transform, Dimensions<InlayOffset, usize>>,
+    transforms: Cursor<'a, 'static, Transform, Dimensions<InlayOffset, usize>>,
     buffer_chunks: CustomHighlightsChunks<'a>,
     buffer_chunk: Option<Chunk<'a>>,
     inlay_chunks: Option<text::ChunkWithBitmaps<'a>>,
@@ -542,7 +540,7 @@ impl InlayMap {
         let version = 0;
         let snapshot = InlaySnapshot {
             buffer: buffer.clone(),
-            transforms: SumTree::from_iter(Some(Transform::Isomorphic(buffer.text_summary())), &()),
+            transforms: SumTree::from_iter(Some(Transform::Isomorphic(buffer.text_summary())), ()),
             version,
         };
 
@@ -589,10 +587,10 @@ impl InlayMap {
             let mut new_transforms = SumTree::default();
             let mut cursor = snapshot
                 .transforms
-                .cursor::<Dimensions<usize, InlayOffset>>(&());
+                .cursor::<Dimensions<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), &());
+                new_transforms.append(cursor.slice(&buffer_edit.old.start, Bias::Left), ());
                 if let Some(Transform::Isomorphic(transform)) = cursor.item()
                     && cursor.end().0 == buffer_edit.old.start
                 {
@@ -642,7 +640,7 @@ impl InlayMap {
                         buffer_snapshot.text_summary_for_range(prefix_start..prefix_end),
                     );
 
-                    new_transforms.push(Transform::Inlay(inlay.clone()), &());
+                    new_transforms.push(Transform::Inlay(inlay.clone()), ());
                 }
 
                 // Apply the rest of the edit.
@@ -674,9 +672,9 @@ impl InlayMap {
                 }
             }
 
-            new_transforms.append(cursor.suffix(), &());
+            new_transforms.append(cursor.suffix(), ());
             if new_transforms.is_empty() {
-                new_transforms.push(Transform::Isomorphic(Default::default()), &());
+                new_transforms.push(Transform::Isomorphic(Default::default()), ());
             }
 
             drop(cursor);
@@ -812,7 +810,7 @@ impl InlaySnapshot {
     pub fn to_point(&self, offset: InlayOffset) -> InlayPoint {
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<InlayOffset, InlayPoint, usize>>(&());
+            .cursor::<Dimensions<InlayOffset, InlayPoint, usize>>(());
         cursor.seek(&offset, Bias::Right);
         let overshoot = offset.0 - cursor.start().0.0;
         match cursor.item() {
@@ -842,7 +840,7 @@ impl InlaySnapshot {
     pub fn to_offset(&self, point: InlayPoint) -> InlayOffset {
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<InlayPoint, InlayOffset, Point>>(&());
+            .cursor::<Dimensions<InlayPoint, InlayOffset, Point>>(());
         cursor.seek(&point, Bias::Right);
         let overshoot = point.0 - cursor.start().0.0;
         match cursor.item() {
@@ -861,7 +859,7 @@ impl InlaySnapshot {
         }
     }
     pub fn to_buffer_point(&self, point: InlayPoint) -> Point {
-        let mut cursor = self.transforms.cursor::<Dimensions<InlayPoint, Point>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<InlayPoint, Point>>(());
         cursor.seek(&point, Bias::Right);
         match cursor.item() {
             Some(Transform::Isomorphic(_)) => {
@@ -873,9 +871,7 @@ impl InlaySnapshot {
         }
     }
     pub fn to_buffer_offset(&self, offset: InlayOffset) -> usize {
-        let mut cursor = self
-            .transforms
-            .cursor::<Dimensions<InlayOffset, usize>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<InlayOffset, usize>>(());
         cursor.seek(&offset, Bias::Right);
         match cursor.item() {
             Some(Transform::Isomorphic(_)) => {
@@ -888,9 +884,7 @@ impl InlaySnapshot {
     }
 
     pub fn to_inlay_offset(&self, offset: usize) -> InlayOffset {
-        let mut cursor = self
-            .transforms
-            .cursor::<Dimensions<usize, InlayOffset>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<usize, InlayOffset>>(());
         cursor.seek(&offset, Bias::Left);
         loop {
             match cursor.item() {
@@ -923,7 +917,7 @@ impl InlaySnapshot {
         }
     }
     pub fn to_inlay_point(&self, point: Point) -> InlayPoint {
-        let mut cursor = self.transforms.cursor::<Dimensions<Point, InlayPoint>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<Point, InlayPoint>>(());
         cursor.seek(&point, Bias::Left);
         loop {
             match cursor.item() {
@@ -957,7 +951,7 @@ impl InlaySnapshot {
     }
 
     pub fn clip_point(&self, mut point: InlayPoint, mut bias: Bias) -> InlayPoint {
-        let mut cursor = self.transforms.cursor::<Dimensions<InlayPoint, Point>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<InlayPoint, Point>>(());
         cursor.seek(&point, Bias::Left);
         loop {
             match cursor.item() {
@@ -1054,9 +1048,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::<Dimensions<InlayOffset, usize>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<InlayOffset, usize>>(());
         cursor.seek(&range.start, Bias::Right);
 
         let overshoot = range.start.0 - cursor.start().0.0;
@@ -1104,7 +1096,7 @@ impl InlaySnapshot {
     }
 
     pub fn row_infos(&self, row: u32) -> InlayBufferRows<'_> {
-        let mut cursor = self.transforms.cursor::<Dimensions<InlayPoint, Point>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<InlayPoint, Point>>(());
         let inlay_point = InlayPoint::new(row, 0);
         cursor.seek(&inlay_point, Bias::Left);
 
@@ -1146,9 +1138,7 @@ impl InlaySnapshot {
         language_aware: bool,
         highlights: Highlights<'a>,
     ) -> InlayChunks<'a> {
-        let mut cursor = self
-            .transforms
-            .cursor::<Dimensions<InlayOffset, usize>>(&());
+        let mut cursor = self.transforms.cursor::<Dimensions<InlayOffset, usize>>(());
         cursor.seek(&range.start, Bias::Right);
 
         let buffer_range = self.to_buffer_offset(range.start)..self.to_buffer_offset(range.end);
@@ -1212,11 +1202,11 @@ fn push_isomorphic(sum_tree: &mut SumTree<Transform>, summary: TextSummary) {
                 *transform += summary.take().unwrap();
             }
         },
-        &(),
+        (),
     );
 
     if let Some(summary) = summary {
-        sum_tree.push(Transform::Isomorphic(summary), &());
+        sum_tree.push(Transform::Isomorphic(summary), ());
     }
 }
 

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

@@ -55,7 +55,7 @@ pub struct WrapChunks<'a> {
     input_chunk: Chunk<'a>,
     output_position: WrapPoint,
     max_output_row: u32,
-    transforms: Cursor<'a, Transform, Dimensions<WrapPoint, TabPoint>>,
+    transforms: Cursor<'a, 'static, Transform, Dimensions<WrapPoint, TabPoint>>,
     snapshot: &'a WrapSnapshot,
 }
 
@@ -66,7 +66,7 @@ pub struct WrapRows<'a> {
     output_row: u32,
     soft_wrapped: bool,
     max_output_row: u32,
-    transforms: Cursor<'a, Transform, Dimensions<WrapPoint, TabPoint>>,
+    transforms: Cursor<'a, 'static, Transform, Dimensions<WrapPoint, TabPoint>>,
 }
 
 impl WrapRows<'_> {
@@ -221,7 +221,7 @@ impl WrapMap {
             if !summary.lines.is_zero() {
                 self.snapshot
                     .transforms
-                    .push(Transform::isomorphic(summary), &());
+                    .push(Transform::isomorphic(summary), ());
             }
             let new_rows = self.snapshot.transforms.summary().output.lines.row + 1;
             self.snapshot.interpolated = false;
@@ -318,7 +318,7 @@ impl WrapSnapshot {
         let mut transforms = SumTree::default();
         let extent = tab_snapshot.text_summary();
         if !extent.lines.is_zero() {
-            transforms.push(Transform::isomorphic(extent), &());
+            transforms.push(Transform::isomorphic(extent), ());
         }
         Self {
             transforms,
@@ -336,7 +336,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 =
@@ -368,7 +368,7 @@ impl WrapSnapshot {
 
                         old_cursor.next();
                         new_transforms
-                            .append(old_cursor.slice(&next_edit.old.start, Bias::Right), &());
+                            .append(old_cursor.slice(&next_edit.old.start, Bias::Right), ());
                     }
                 } else {
                     if old_cursor.end() > edit.old.end {
@@ -378,7 +378,7 @@ impl WrapSnapshot {
                         new_transforms.push_or_extend(Transform::isomorphic(summary));
                     }
                     old_cursor.next();
-                    new_transforms.append(old_cursor.suffix(), &());
+                    new_transforms.append(old_cursor.suffix(), ());
                 }
             }
         }
@@ -434,7 +434,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),
@@ -511,7 +511,7 @@ impl WrapSnapshot {
                 if let Some(transform) = edit_transforms.next() {
                     new_transforms.push_or_extend(transform);
                 }
-                new_transforms.extend(edit_transforms, &());
+                new_transforms.extend(edit_transforms, ());
 
                 old_cursor.seek_forward(&TabPoint::new(edit.old_rows.end, 0), Bias::Right);
                 if let Some(next_edit) = row_edits.peek() {
@@ -526,7 +526,7 @@ impl WrapSnapshot {
                         new_transforms.append(
                             old_cursor
                                 .slice(&TabPoint::new(next_edit.old_rows.start, 0), Bias::Right),
-                            &(),
+                            (),
                         );
                     }
                 } else {
@@ -537,7 +537,7 @@ impl WrapSnapshot {
                         new_transforms.push_or_extend(Transform::isomorphic(summary));
                     }
                     old_cursor.next();
-                    new_transforms.append(old_cursor.suffix(), &());
+                    new_transforms.append(old_cursor.suffix(), ());
                 }
             }
         }
@@ -556,8 +556,8 @@ impl WrapSnapshot {
 
     fn compute_edits(&self, tab_edits: &[TabEdit], new_snapshot: &WrapSnapshot) -> Patch<u32> {
         let mut wrap_edits = Vec::with_capacity(tab_edits.len());
-        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);
@@ -600,7 +600,7 @@ impl WrapSnapshot {
         let output_end = WrapPoint::new(rows.end, 0);
         let mut transforms = self
             .transforms
-            .cursor::<Dimensions<WrapPoint, TabPoint>>(&());
+            .cursor::<Dimensions<WrapPoint, TabPoint>>(());
         transforms.seek(&output_start, Bias::Right);
         let mut input_start = TabPoint(transforms.start().1.0);
         if transforms.item().is_some_and(|t| t.is_isomorphic()) {
@@ -630,7 +630,7 @@ impl WrapSnapshot {
     pub fn line_len(&self, row: u32) -> u32 {
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<WrapPoint, TabPoint>>(&());
+            .cursor::<Dimensions<WrapPoint, TabPoint>>(());
         cursor.seek(&WrapPoint::new(row + 1, 0), Bias::Left);
         if cursor
             .item()
@@ -657,7 +657,7 @@ impl WrapSnapshot {
 
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<WrapPoint, TabPoint>>(&());
+            .cursor::<Dimensions<WrapPoint, TabPoint>>(());
         cursor.seek(&start, Bias::Right);
         if let Some(transform) = cursor.item() {
             let start_in_transform = start.0 - cursor.start().0.0;
@@ -711,7 +711,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() {
@@ -729,7 +729,7 @@ impl WrapSnapshot {
     pub fn row_infos(&self, start_row: u32) -> WrapRows<'_> {
         let mut transforms = self
             .transforms
-            .cursor::<Dimensions<WrapPoint, TabPoint>>(&());
+            .cursor::<Dimensions<WrapPoint, TabPoint>>(());
         transforms.seek(&WrapPoint::new(start_row, 0), Bias::Left);
         let mut input_row = transforms.start().1.row();
         if transforms.item().is_some_and(|t| t.is_isomorphic()) {
@@ -751,7 +751,7 @@ impl WrapSnapshot {
     pub fn to_tab_point(&self, point: WrapPoint) -> TabPoint {
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<WrapPoint, TabPoint>>(&());
+            .cursor::<Dimensions<WrapPoint, TabPoint>>(());
         cursor.seek(&point, Bias::Right);
         let mut tab_point = cursor.start().1.0;
         if cursor.item().is_some_and(|t| t.is_isomorphic()) {
@@ -771,14 +771,14 @@ impl WrapSnapshot {
     pub fn tab_point_to_wrap_point(&self, point: TabPoint) -> WrapPoint {
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<TabPoint, WrapPoint>>(&());
+            .cursor::<Dimensions<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().is_some_and(|t| !t.is_isomorphic()) {
                 point = *cursor.start();
@@ -798,7 +798,7 @@ impl WrapSnapshot {
 
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<WrapPoint, TabPoint>>(&());
+            .cursor::<Dimensions<WrapPoint, TabPoint>>(());
         cursor.seek(&point, Bias::Right);
         if cursor.item().is_none() {
             cursor.prev();
@@ -820,7 +820,7 @@ impl WrapSnapshot {
 
         let mut cursor = self
             .transforms
-            .cursor::<Dimensions<WrapPoint, TabPoint>>(&());
+            .cursor::<Dimensions<WrapPoint, TabPoint>>(());
         cursor.seek(&point, Bias::Right);
         while let Some(transform) = cursor.item() {
             if transform.is_isomorphic() && cursor.start().1.column() == 0 {
@@ -857,7 +857,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());
@@ -1075,7 +1075,7 @@ impl Transform {
 impl sum_tree::Item for Transform {
     type Summary = TransformSummary;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         self.summary.clone()
     }
 }
@@ -1106,11 +1106,11 @@ impl SumTreeExt for SumTree<Transform> {
                     last_transform.summary.output += &transform.summary.output;
                 }
             },
-            &(),
+            (),
         );
 
         if let Some(transform) = transform {
-            self.push(transform, &());
+            self.push(transform, ());
         }
     }
 }
@@ -1137,41 +1137,39 @@ impl WrapPoint {
     }
 }
 
-impl sum_tree::Summary for TransformSummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for TransformSummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, other: &Self, _: &()) {
+    fn add_summary(&mut self, other: &Self) {
         self.input += &other.input;
         self.output += &other.output;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for TabPoint {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
         self.0 += summary.input.lines;
     }
 }
 
 impl sum_tree::SeekTarget<'_, TransformSummary, TransformSummary> for TabPoint {
-    fn cmp(&self, cursor_location: &TransformSummary, _: &()) -> std::cmp::Ordering {
+    fn cmp(&self, cursor_location: &TransformSummary, _: ()) -> std::cmp::Ordering {
         Ord::cmp(&self.0, &cursor_location.input.lines)
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, TransformSummary> for WrapPoint {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
         self.0 += summary.output.lines;
     }
 }
@@ -1385,7 +1383,7 @@ mod tests {
                 let mut summary = TextSummary::default();
                 for (ix, item) in wrapped_snapshot
                     .transforms
-                    .items(&())
+                    .items(())
                     .into_iter()
                     .enumerate()
                 {

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

@@ -38,29 +38,27 @@ pub struct GitBlameEntrySummary {
 impl sum_tree::Item for GitBlameEntry {
     type Summary = GitBlameEntrySummary;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         GitBlameEntrySummary { rows: self.rows }
     }
 }
 
-impl sum_tree::Summary for GitBlameEntrySummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for GitBlameEntrySummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _cx: &()) {
+    fn add_summary(&mut self, summary: &Self) {
         self.rows += summary.rows;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, GitBlameEntrySummary> for u32 {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a GitBlameEntrySummary, _cx: &()) {
+    fn add_summary(&mut self, summary: &'a GitBlameEntrySummary, _cx: ()) {
         *self += summary.rows;
     }
 }
@@ -298,7 +296,7 @@ impl GitBlame {
             self.sync(cx, buffer_id);
 
             let buffer_row = info.buffer_row?;
-            let mut cursor = self.buffers.get(&buffer_id)?.entries.cursor::<u32>(&());
+            let mut cursor = self.buffers.get(&buffer_id)?.entries.cursor::<u32>(());
             cursor.seek_forward(&buffer_row, Bias::Right);
             Some((buffer_id, cursor.item()?.blame.clone()?))
         })
@@ -406,7 +404,7 @@ impl GitBlame {
             .peekable();
 
         let mut new_entries = SumTree::default();
-        let mut cursor = blame_buffer.entries.cursor::<u32>(&());
+        let mut cursor = blame_buffer.entries.cursor::<u32>(());
 
         while let Some(mut edit) = row_edits.next() {
             while let Some(next_edit) = row_edits.peek() {
@@ -419,7 +417,7 @@ impl GitBlame {
                 }
             }
 
-            new_entries.append(cursor.slice(&edit.old.start, Bias::Right), &());
+            new_entries.append(cursor.slice(&edit.old.start, Bias::Right), ());
 
             if edit.new.start > new_entries.summary().rows {
                 new_entries.push(
@@ -427,7 +425,7 @@ impl GitBlame {
                         rows: edit.new.start - new_entries.summary().rows,
                         blame: cursor.item().and_then(|entry| entry.blame.clone()),
                     },
-                    &(),
+                    (),
                 );
             }
 
@@ -438,7 +436,7 @@ impl GitBlame {
                         rows: edit.new.len() as u32,
                         blame: None,
                     },
-                    &(),
+                    (),
                 );
             }
 
@@ -454,14 +452,14 @@ impl GitBlame {
                             rows: cursor.end() - edit.old.end,
                             blame: entry.blame.clone(),
                         },
-                        &(),
+                        (),
                     );
                 }
 
                 cursor.next();
             }
         }
-        new_entries.append(cursor.suffix(), &());
+        new_entries.append(cursor.suffix(), ());
         drop(cursor);
 
         blame_buffer.buffer_snapshot = new_snapshot;
@@ -632,7 +630,7 @@ fn build_blame_entry_sum_tree(entries: Vec<BlameEntry>, max_row: u32) -> SumTree
             current_row = entry.range.end;
             entries
         }),
-        &(),
+        (),
     );
 
     if max_row >= current_row {
@@ -641,7 +639,7 @@ fn build_blame_entry_sum_tree(entries: Vec<BlameEntry>, max_row: u32) -> SumTree
                 rows: (max_row + 1) - current_row,
                 blame: None,
             },
-            &(),
+            (),
         );
     }
 

crates/git/src/status.rs 🔗

@@ -378,14 +378,12 @@ impl From<FileStatus> for GitSummary {
     }
 }
 
-impl sum_tree::Summary for GitSummary {
-    type Context = ();
-
-    fn zero(_: &Self::Context) -> Self {
+impl sum_tree::ContextLessSummary for GitSummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, rhs: &Self, _: &Self::Context) {
+    fn add_summary(&mut self, rhs: &Self) {
         *self += *rhs;
     }
 }

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

@@ -245,7 +245,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);
 
@@ -255,9 +255,9 @@ impl ListState {
                 spliced_count += 1;
                 ListItem::Unmeasured { focus_handle }
             }),
-            &(),
+            (),
         );
-        new_items.append(old_items.suffix(), &());
+        new_items.append(old_items.suffix(), ());
         drop(old_items);
         state.items = new_items;
 
@@ -296,7 +296,7 @@ impl ListState {
 
         let current_offset = self.logical_scroll_top();
         let state = &mut *self.0.borrow_mut();
-        let mut cursor = state.items.cursor::<ListItemSummary>(&());
+        let mut cursor = state.items.cursor::<ListItemSummary>(());
         cursor.seek(&Count(current_offset.item_ix), Bias::Right);
 
         let start_pixel_offset = cursor.start().height + current_offset.offset_in_item;
@@ -339,7 +339,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);
@@ -368,7 +368,7 @@ impl ListState {
             return None;
         }
 
-        let mut cursor = state.items.cursor::<Dimensions<Count, Height>>(&());
+        let mut cursor = state.items.cursor::<Dimensions<Count, Height>>(());
         cursor.seek(&Count(scroll_top.item_ix), Bias::Right);
 
         let scroll_top = cursor.start().1.0 + scroll_top.offset_in_item;
@@ -426,7 +426,7 @@ impl ListState {
         let state = &self.0.borrow();
         let logical_scroll_top = state.logical_scroll_top();
 
-        let mut cursor = state.items.cursor::<ListItemSummary>(&());
+        let mut cursor = state.items.cursor::<ListItemSummary>(());
         let summary: ListItemSummary =
             cursor.summary(&Count(logical_scroll_top.item_ix), Bias::Right);
         let content_height = state.items.summary().height;
@@ -446,7 +446,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);
@@ -478,7 +478,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;
@@ -519,7 +519,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
     }
@@ -548,7 +548,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);
@@ -663,11 +663,11 @@ 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, &());
+        new_items.extend(measured_items, ());
         cursor.seek(&Count(measured_range.end), Bias::Right);
-        new_items.append(cursor.suffix(), &());
+        new_items.append(cursor.suffix(), ());
         self.items = new_items;
 
         // If none of the visible items are focused, check if an off-screen item is focused
@@ -676,7 +676,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(window, cx) {
@@ -741,7 +741,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;
 
@@ -802,7 +802,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;
@@ -946,7 +946,7 @@ impl Element for List {
                 state.items.iter().map(|item| ListItem::Unmeasured {
                     focus_handle: item.focus_handle(),
                 }),
-                &(),
+                (),
             );
 
             state.items = new_items;
@@ -1027,7 +1027,7 @@ impl Styled for List {
 impl sum_tree::Item for ListItem {
     type Summary = ListItemSummary;
 
-    fn summary(&self, _: &()) -> Self::Summary {
+    fn summary(&self, _: ()) -> Self::Summary {
         match self {
             ListItem::Unmeasured { focus_handle } => ListItemSummary {
                 count: 1,
@@ -1049,14 +1049,12 @@ impl sum_tree::Item for ListItem {
     }
 }
 
-impl sum_tree::Summary for ListItemSummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for ListItemSummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &()) {
+    fn add_summary(&mut self, summary: &Self) {
         self.count += summary.count;
         self.rendered_count += summary.rendered_count;
         self.unrendered_count += summary.unrendered_count;
@@ -1066,33 +1064,33 @@ impl sum_tree::Summary for ListItemSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, ListItemSummary> for Count {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ListItemSummary, _: &()) {
+    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 {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ListItemSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a ListItemSummary, _: ()) {
         self.0 += summary.height;
     }
 }
 
 impl sum_tree::SeekTarget<'_, ListItemSummary, ListItemSummary> for Count {
-    fn cmp(&self, other: &ListItemSummary, _: &()) -> std::cmp::Ordering {
+    fn cmp(&self, other: &ListItemSummary, _: ()) -> std::cmp::Ordering {
         self.0.partial_cmp(&other.count).unwrap()
     }
 }
 
 impl sum_tree::SeekTarget<'_, ListItemSummary, ListItemSummary> for Height {
-    fn cmp(&self, other: &ListItemSummary, _: &()) -> std::cmp::Ordering {
+    fn cmp(&self, other: &ListItemSummary, _: ()) -> std::cmp::Ordering {
         self.0.partial_cmp(&other.height).unwrap()
     }
 }

crates/language/src/diagnostic_set.rs 🔗

@@ -269,13 +269,13 @@ impl Default for Summary {
 }
 
 impl sum_tree::Summary for Summary {
-    type Context = text::BufferSnapshot;
+    type Context<'a> = &'a text::BufferSnapshot;
 
-    fn zero(_cx: &Self::Context) -> Self {
+    fn zero(_cx: Self::Context<'_>) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
+    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 🔗

@@ -1775,13 +1775,13 @@ impl Default for SyntaxLayerSummary {
 }
 
 impl sum_tree::Summary for SyntaxLayerSummary {
-    type Context = BufferSnapshot;
+    type Context<'a> = &'a BufferSnapshot;
 
     fn zero(_cx: &BufferSnapshot) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
+    fn add_summary(&mut self, other: &Self, buffer: Self::Context<'_>) {
         if other.max_depth > self.max_depth {
             self.max_depth = other.max_depth;
             self.range = other.range.clone();

crates/multi_buffer/src/multi_buffer.rs 🔗

@@ -412,7 +412,7 @@ struct Excerpt {
 #[derive(Clone)]
 pub struct MultiBufferExcerpt<'a> {
     excerpt: &'a Excerpt,
-    diff_transforms: sum_tree::Cursor<'a, DiffTransform, DiffTransforms<usize>>,
+    diff_transforms: sum_tree::Cursor<'a, 'static, DiffTransform, DiffTransforms<usize>>,
     offset: usize,
     excerpt_offset: ExcerptDimension<usize>,
     buffer_offset: usize,
@@ -468,8 +468,8 @@ pub struct MultiBufferRows<'a> {
 }
 
 pub struct MultiBufferChunks<'a> {
-    excerpts: Cursor<'a, Excerpt, ExcerptOffset>,
-    diff_transforms: Cursor<'a, DiffTransform, Dimensions<usize, ExcerptOffset>>,
+    excerpts: Cursor<'a, 'static, Excerpt, ExcerptOffset>,
+    diff_transforms: Cursor<'a, 'static, DiffTransform, Dimensions<usize, ExcerptOffset>>,
     diffs: &'a TreeMap<BufferId, BufferDiffSnapshot>,
     diff_base_chunks: Option<(BufferId, BufferChunks<'a>)>,
     buffer_chunk: Option<Chunk<'a>>,
@@ -507,7 +507,7 @@ struct DiffTransforms<D> {
 }
 
 impl<'a, D: TextDimension> Dimension<'a, DiffTransformSummary> for DiffTransforms<D> {
-    fn zero(cx: &<DiffTransformSummary as sum_tree::Summary>::Context) -> Self {
+    fn zero(cx: <DiffTransformSummary as sum_tree::Summary>::Context<'_>) -> Self {
         Self {
             output_dimension: OutputDimension::zero(cx),
             excerpt_dimension: <ExcerptDimension<D> as Dimension<'a, DiffTransformSummary>>::zero(
@@ -519,7 +519,7 @@ impl<'a, D: TextDimension> Dimension<'a, DiffTransformSummary> for DiffTransform
     fn add_summary(
         &mut self,
         summary: &'a DiffTransformSummary,
-        cx: &<DiffTransformSummary as sum_tree::Summary>::Context,
+        cx: <DiffTransformSummary as sum_tree::Summary>::Context<'_>,
     ) {
         self.output_dimension.add_summary(summary, cx);
         self.excerpt_dimension.add_summary(summary, cx);
@@ -528,8 +528,8 @@ impl<'a, D: TextDimension> Dimension<'a, DiffTransformSummary> for DiffTransform
 
 #[derive(Clone)]
 struct MultiBufferCursor<'a, D: TextDimension> {
-    excerpts: Cursor<'a, Excerpt, ExcerptDimension<D>>,
-    diff_transforms: Cursor<'a, DiffTransform, DiffTransforms<D>>,
+    excerpts: Cursor<'a, 'static, Excerpt, ExcerptDimension<D>>,
+    diff_transforms: Cursor<'a, 'static, DiffTransform, DiffTransforms<D>>,
     diffs: &'a TreeMap<BufferId, BufferDiffSnapshot>,
     cached_region: Option<MultiBufferRegion<'a, D>>,
 }
@@ -1196,7 +1196,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 {
@@ -1311,7 +1311,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);
@@ -1762,7 +1762,7 @@ impl MultiBuffer {
 
         let mut next_excerpt_id = move || ExcerptId(post_inc(&mut next_excerpt_id));
 
-        let mut excerpts_cursor = snapshot.excerpts.cursor::<Option<&Locator>>(&());
+        let mut excerpts_cursor = snapshot.excerpts.cursor::<Option<&Locator>>(());
         excerpts_cursor.next();
 
         loop {
@@ -1963,7 +1963,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();
 
@@ -1972,7 +1972,7 @@ impl MultiBuffer {
             |excerpt| {
                 excerpt.has_trailing_newline = true;
             },
-            &(),
+            (),
         );
 
         let next_locator = if let Some(excerpt) = cursor.item() {
@@ -2002,20 +2002,20 @@ impl MultiBuffer {
                 range,
                 ranges.peek().is_some() || cursor.item().is_some(),
             );
-            new_excerpts.push(excerpt, &());
+            new_excerpts.push(excerpt, ());
             prev_locator = locator.clone();
 
             if let Some(last_mapping_entry) = new_excerpt_ids.last() {
                 assert!(id > last_mapping_entry.id, "excerpt ids must be increasing");
             }
-            new_excerpt_ids.push(ExcerptIdMapping { id, locator }, &());
+            new_excerpt_ids.push(ExcerptIdMapping { id, locator }, ());
         }
 
         let edit_end = ExcerptOffset::new(new_excerpts.summary().text.len);
 
         let suffix = cursor.suffix();
         let changed_trailing_excerpt = suffix.is_empty();
-        new_excerpts.append(suffix, &());
+        new_excerpts.append(suffix, ());
         drop(cursor);
         snapshot.excerpts = new_excerpts;
         snapshot.excerpt_ids = new_excerpt_ids;
@@ -2091,7 +2091,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>>(());
         if let Some(locators) = buffers.get(&buffer_id).map(|state| &state.excerpts) {
             for locator in locators {
                 cursor.seek_forward(&Some(locator), Bias::Left);
@@ -2111,10 +2111,10 @@ impl MultiBuffer {
         let buffers = self.buffers.borrow();
         let mut excerpts = snapshot
             .excerpts
-            .cursor::<Dimensions<Option<&Locator>, ExcerptDimension<Point>>>(&());
+            .cursor::<Dimensions<Option<&Locator>, ExcerptDimension<Point>>>(());
         let mut diff_transforms = snapshot
             .diff_transforms
-            .cursor::<Dimensions<ExcerptDimension<Point>, OutputDimension<Point>>>(&());
+            .cursor::<Dimensions<ExcerptDimension<Point>, OutputDimension<Point>>>(());
         diff_transforms.next();
         let locators = buffers
             .get(&buffer_id)
@@ -2280,7 +2280,7 @@ impl MultiBuffer {
         let mut new_excerpts = SumTree::default();
         let mut cursor = snapshot
             .excerpts
-            .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(&());
+            .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(());
         let mut edits = Vec::new();
         let mut excerpt_ids = ids.iter().copied().peekable();
         let mut removed_buffer_ids = Vec::new();
@@ -2289,7 +2289,7 @@ impl MultiBuffer {
             self.paths_by_excerpt.remove(&excerpt_id);
             // Seek to the next excerpt to remove, preserving any preceding excerpts.
             let locator = snapshot.excerpt_locator_for_id(excerpt_id);
-            new_excerpts.append(cursor.slice(&Some(locator), Bias::Left), &());
+            new_excerpts.append(cursor.slice(&Some(locator), Bias::Left), ());
 
             if let Some(mut excerpt) = cursor.item() {
                 if excerpt.id != excerpt_id {
@@ -2331,7 +2331,7 @@ impl MultiBuffer {
                 // the previous excerpt.
                 if cursor.item().is_none() && old_start.value > 0 {
                     old_start.value -= 1;
-                    new_excerpts.update_last(|e| e.has_trailing_newline = false, &());
+                    new_excerpts.update_last(|e| e.has_trailing_newline = false, ());
                 }
 
                 // Push an edit for the removal of this run of excerpts.
@@ -2345,7 +2345,7 @@ impl MultiBuffer {
         }
         let suffix = cursor.suffix();
         let changed_trailing_excerpt = suffix.is_empty();
-        new_excerpts.append(suffix, &());
+        new_excerpts.append(suffix, ());
         drop(cursor);
         snapshot.excerpts = new_excerpts;
         for buffer_id in &removed_buffer_ids {
@@ -2487,7 +2487,7 @@ impl MultiBuffer {
         for locator in &buffer_state.excerpts {
             let mut cursor = snapshot
                 .excerpts
-                .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(&());
+                .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(());
             cursor.seek_forward(&Some(locator), Bias::Left);
             if let Some(excerpt) = cursor.item()
                 && excerpt.locator == *locator
@@ -2721,7 +2721,7 @@ impl MultiBuffer {
 
     pub fn single_hunk_is_expanded(&self, range: Range<Anchor>, cx: &App) -> bool {
         let snapshot = self.read(cx);
-        let mut cursor = snapshot.diff_transforms.cursor::<usize>(&());
+        let mut cursor = snapshot.diff_transforms.cursor::<usize>(());
         let offset_range = range.to_offset(&snapshot);
         cursor.seek(&offset_range.start, Bias::Left);
         while let Some(item) = cursor.item() {
@@ -2738,7 +2738,7 @@ impl MultiBuffer {
 
     pub fn has_expanded_diff_hunks_in_ranges(&self, ranges: &[Range<Anchor>], cx: &App) -> bool {
         let snapshot = self.read(cx);
-        let mut cursor = snapshot.diff_transforms.cursor::<usize>(&());
+        let mut cursor = snapshot.diff_transforms.cursor::<usize>(());
         for range in ranges {
             let range = range.to_point(&snapshot);
             let start = snapshot.point_to_offset(Point::new(range.start.row, 0));
@@ -2844,11 +2844,11 @@ impl MultiBuffer {
         let mut new_excerpts = SumTree::default();
         let mut cursor = snapshot
             .excerpts
-            .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(&());
+            .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(());
         let mut edits = Vec::<Edit<ExcerptOffset>>::new();
 
         let prefix = cursor.slice(&Some(locator), Bias::Left);
-        new_excerpts.append(prefix, &());
+        new_excerpts.append(prefix, ());
 
         let mut excerpt = cursor.item().unwrap().clone();
         let old_text_len = ExcerptOffset::new(excerpt.text_summary.len);
@@ -2880,11 +2880,11 @@ impl MultiBuffer {
             edits.push(edit);
         }
 
-        new_excerpts.push(excerpt, &());
+        new_excerpts.push(excerpt, ());
 
         cursor.next();
 
-        new_excerpts.append(cursor.suffix(), &());
+        new_excerpts.append(cursor.suffix(), ());
 
         drop(cursor);
         snapshot.excerpts = new_excerpts;
@@ -2920,12 +2920,12 @@ impl MultiBuffer {
         let mut new_excerpts = SumTree::default();
         let mut cursor = snapshot
             .excerpts
-            .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(&());
+            .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(());
         let mut edits = Vec::<Edit<ExcerptOffset>>::new();
 
         for locator in &locators {
             let prefix = cursor.slice(&Some(locator), Bias::Left);
-            new_excerpts.append(prefix, &());
+            new_excerpts.append(prefix, ());
 
             let mut excerpt = cursor.item().unwrap().clone();
             let old_text_len = ExcerptOffset::new(excerpt.text_summary.len);
@@ -2984,12 +2984,12 @@ impl MultiBuffer {
                 edits.push(edit);
             }
 
-            new_excerpts.push(excerpt, &());
+            new_excerpts.push(excerpt, ());
 
             cursor.next();
         }
 
-        new_excerpts.append(cursor.suffix(), &());
+        new_excerpts.append(cursor.suffix(), ());
 
         drop(cursor);
         snapshot.excerpts = new_excerpts;
@@ -3066,10 +3066,10 @@ impl MultiBuffer {
         let mut new_excerpts = SumTree::default();
         let mut cursor = snapshot
             .excerpts
-            .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(&());
+            .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(());
 
         for (locator, buffer, buffer_edited) in excerpts_to_edit {
-            new_excerpts.append(cursor.slice(&Some(locator), Bias::Left), &());
+            new_excerpts.append(cursor.slice(&Some(locator), Bias::Left), ());
             let old_excerpt = cursor.item().unwrap();
             let buffer = buffer.read(cx);
             let buffer_id = buffer.remote_id();
@@ -3110,10 +3110,10 @@ impl MultiBuffer {
                 new_excerpt.buffer = buffer.snapshot();
             }
 
-            new_excerpts.push(new_excerpt, &());
+            new_excerpts.push(new_excerpt, ());
             cursor.next();
         }
-        new_excerpts.append(cursor.suffix(), &());
+        new_excerpts.append(cursor.suffix(), ());
 
         drop(cursor);
         snapshot.excerpts = new_excerpts;
@@ -3131,10 +3131,10 @@ impl MultiBuffer {
             return;
         }
 
-        let mut excerpts = snapshot.excerpts.cursor::<ExcerptOffset>(&());
+        let mut excerpts = snapshot.excerpts.cursor::<ExcerptOffset>(());
         let mut old_diff_transforms = snapshot
             .diff_transforms
-            .cursor::<Dimensions<ExcerptOffset, usize>>(&());
+            .cursor::<Dimensions<ExcerptOffset, usize>>(());
         let mut new_diff_transforms = SumTree::default();
         let mut old_expanded_hunks = HashSet::default();
         let mut output_edits = Vec::new();
@@ -3241,7 +3241,7 @@ impl MultiBuffer {
                     summary: Default::default(),
                     inserted_hunk_info: None,
                 },
-                &(),
+                (),
             );
         }
 
@@ -3399,7 +3399,7 @@ impl MultiBuffer {
                                     hunk_info,
                                     has_trailing_newline,
                                 },
-                                &(),
+                                (),
                             );
                         }
 
@@ -3436,13 +3436,13 @@ impl MultiBuffer {
                 *summary,
             )
         {
-            let mut cursor = subtree.cursor::<()>(&());
+            let mut cursor = subtree.cursor::<()>(());
             cursor.next();
             cursor.next();
-            new_transforms.append(cursor.suffix(), &());
+            new_transforms.append(cursor.suffix(), ());
             return;
         }
-        new_transforms.append(subtree, &());
+        new_transforms.append(subtree, ());
     }
 
     fn push_diff_transform(
@@ -3462,7 +3462,7 @@ impl MultiBuffer {
         {
             return;
         }
-        new_transforms.push(transform, &());
+        new_transforms.push(transform, ());
     }
 
     fn push_buffer_content_transform(
@@ -3496,7 +3496,7 @@ impl MultiBuffer {
                         summary: summary_to_add,
                         inserted_hunk_info,
                     },
-                    &(),
+                    (),
                 )
             }
         }
@@ -3521,7 +3521,7 @@ impl MultiBuffer {
                     did_extend = true;
                 }
             },
-            &(),
+            (),
         );
         did_extend
     }
@@ -4033,7 +4033,7 @@ impl MultiBufferSnapshot {
         cursor.seek(&query_range.start);
 
         if let Some(region) = cursor.region().filter(|region| !region.is_main_buffer)
-            && region.range.start > D::zero(&())
+            && region.range.start > D::zero(())
         {
             cursor.prev()
         }
@@ -4368,8 +4368,8 @@ impl MultiBufferSnapshot {
         let mut chunks = MultiBufferChunks {
             excerpt_offset_range: ExcerptOffset::new(0)..ExcerptOffset::new(0),
             range: 0..0,
-            excerpts: self.excerpts.cursor(&()),
-            diff_transforms: self.diff_transforms.cursor(&()),
+            excerpts: self.excerpts.cursor(()),
+            diff_transforms: self.diff_transforms.cursor(()),
             diffs: &self.diffs,
             diff_base_chunks: None,
             excerpt_chunks: None,
@@ -4706,7 +4706,7 @@ impl MultiBufferSnapshot {
         let range = range.start.to_offset(self)..range.end.to_offset(self);
         let mut cursor = self
             .diff_transforms
-            .cursor::<Dimensions<usize, ExcerptOffset>>(&());
+            .cursor::<Dimensions<usize, ExcerptOffset>>(());
         cursor.seek(&range.start, Bias::Right);
 
         let Some(first_transform) = cursor.item() else {
@@ -4801,8 +4801,8 @@ impl MultiBufferSnapshot {
         D: TextDimension,
     {
         // let mut range = range.start..range.end;
-        let mut summary = D::zero(&());
-        let mut cursor = self.excerpts.cursor::<ExcerptOffset>(&());
+        let mut summary = D::zero(());
+        let mut cursor = self.excerpts.cursor::<ExcerptOffset>(());
         cursor.seek(&range.start, Bias::Right);
         if let Some(excerpt) = cursor.item() {
             let mut end_before_newline = cursor.end();
@@ -4920,7 +4920,7 @@ impl MultiBufferSnapshot {
     fn excerpt_offset_for_anchor(&self, anchor: &Anchor) -> ExcerptOffset {
         let mut cursor = self
             .excerpts
-            .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(&());
+            .cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(());
         let locator = self.excerpt_locator_for_id(anchor.excerpt_id);
 
         cursor.seek(&Some(locator), Bias::Left);
@@ -4960,10 +4960,10 @@ impl MultiBufferSnapshot {
         I: 'a + IntoIterator<Item = &'a Anchor>,
     {
         let mut anchors = anchors.into_iter().peekable();
-        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
+        let mut cursor = self.excerpts.cursor::<ExcerptSummary>(());
         let mut diff_transforms_cursor = self
             .diff_transforms
-            .cursor::<Dimensions<ExcerptDimension<D>, OutputDimension<D>>>(&());
+            .cursor::<Dimensions<ExcerptDimension<D>, OutputDimension<D>>>(());
         diff_transforms_cursor.next();
 
         let mut summaries = Vec::new();
@@ -5081,7 +5081,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();
@@ -5195,7 +5195,7 @@ impl MultiBufferSnapshot {
         // offset in the excerpts, and whether the position is within a deleted hunk.
         let mut diff_transforms = self
             .diff_transforms
-            .cursor::<Dimensions<usize, ExcerptOffset>>(&());
+            .cursor::<Dimensions<usize, ExcerptOffset>>(());
         diff_transforms.seek(&offset, Bias::Right);
 
         if offset == diff_transforms.start().0
@@ -5232,7 +5232,7 @@ impl MultiBufferSnapshot {
 
         let mut excerpts = self
             .excerpts
-            .cursor::<Dimensions<ExcerptOffset, Option<ExcerptId>>>(&());
+            .cursor::<Dimensions<ExcerptOffset, Option<ExcerptId>>>(());
         excerpts.seek(&excerpt_offset, Bias::Right);
         if excerpts.item().is_none() && excerpt_offset == excerpts.start().0 && bias == Bias::Left {
             excerpts.prev();
@@ -5277,7 +5277,7 @@ impl MultiBufferSnapshot {
     ) -> Option<Anchor> {
         let excerpt_id = self.latest_excerpt_id(excerpt_id);
         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()
             && excerpt.id == excerpt_id
@@ -5317,8 +5317,8 @@ impl MultiBufferSnapshot {
     }
 
     fn cursor<D: TextDimension + Default>(&self) -> MultiBufferCursor<'_, D> {
-        let excerpts = self.excerpts.cursor(&());
-        let diff_transforms = self.diff_transforms.cursor(&());
+        let excerpts = self.excerpts.cursor(());
+        let diff_transforms = self.diff_transforms.cursor(());
         MultiBufferCursor {
             excerpts,
             diff_transforms,
@@ -5331,11 +5331,11 @@ impl MultiBufferSnapshot {
         let start_locator = self.excerpt_locator_for_id(id);
         let mut excerpts = self
             .excerpts
-            .cursor::<Dimensions<Option<&Locator>, ExcerptDimension<usize>>>(&());
+            .cursor::<Dimensions<Option<&Locator>, ExcerptDimension<usize>>>(());
         excerpts.seek(&Some(start_locator), Bias::Left);
         excerpts.prev();
 
-        let mut diff_transforms = self.diff_transforms.cursor::<DiffTransforms<usize>>(&());
+        let mut diff_transforms = self.diff_transforms.cursor::<DiffTransforms<usize>>(());
         diff_transforms.seek(&excerpts.start().1, Bias::Left);
         if diff_transforms.end().excerpt_dimension < excerpts.start().1 {
             diff_transforms.next();
@@ -6188,7 +6188,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()
                 && entry.id == id
@@ -6223,7 +6223,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());
@@ -6247,14 +6247,14 @@ impl MultiBufferSnapshot {
     pub fn range_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<Range<Point>> {
         let mut cursor = self
             .excerpts
-            .cursor::<Dimensions<Option<&Locator>, ExcerptDimension<Point>>>(&());
+            .cursor::<Dimensions<Option<&Locator>, ExcerptDimension<Point>>>(());
         let locator = self.excerpt_locator_for_id(excerpt_id);
         if cursor.seek(&Some(locator), Bias::Left) {
             let start = cursor.start().1.clone();
             let end = cursor.end().1;
             let mut diff_transforms = self
                 .diff_transforms
-                .cursor::<Dimensions<ExcerptDimension<Point>, OutputDimension<Point>>>(&());
+                .cursor::<Dimensions<ExcerptDimension<Point>, OutputDimension<Point>>>(());
             diff_transforms.seek(&start, Bias::Left);
             let overshoot = start.0 - diff_transforms.start().0.0;
             let start = diff_transforms.start().1.0 + overshoot;
@@ -6268,7 +6268,7 @@ impl MultiBufferSnapshot {
     }
 
     pub fn buffer_range_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<Range<text::Anchor>> {
-        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);
         if cursor.seek(&Some(locator), Bias::Left)
             && let Some(excerpt) = cursor.item()
@@ -6279,7 +6279,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()
@@ -6334,7 +6334,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);
@@ -6448,8 +6448,8 @@ impl MultiBufferSnapshot {
 
     #[cfg(any(test, feature = "test-support"))]
     fn check_invariants(&self) {
-        let excerpts = self.excerpts.items(&());
-        let excerpt_ids = self.excerpt_ids.items(&());
+        let excerpts = self.excerpts.items(());
+        let excerpt_ids = self.excerpt_ids.items(());
 
         for (ix, excerpt) in excerpts.iter().enumerate() {
             if ix == 0 {
@@ -6476,7 +6476,7 @@ impl MultiBufferSnapshot {
                 "incorrect input summary. expected {:?}, got {:?}. transforms: {:+?}",
                 self.excerpts.summary().text.len,
                 self.diff_transforms.summary().input,
-                self.diff_transforms.items(&()),
+                self.diff_transforms.items(()),
             );
         }
 
@@ -6495,7 +6495,7 @@ impl MultiBufferSnapshot {
                 {
                     panic!(
                         "multiple adjacent buffer content transforms with is_inserted_hunk = {inserted_hunk_info:?}. transforms: {:+?}",
-                        self.diff_transforms.items(&())
+                        self.diff_transforms.items(())
                     );
                 }
                 if summary.len == 0 && !self.is_empty() {
@@ -7243,7 +7243,7 @@ impl fmt::Debug for Excerpt {
 impl sum_tree::Item for Excerpt {
     type Summary = ExcerptSummary;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         let mut text = self.text_summary;
         if self.has_trailing_newline {
             text += TextSummary::from("\n");
@@ -7260,7 +7260,7 @@ impl sum_tree::Item for Excerpt {
 impl sum_tree::Item for ExcerptIdMapping {
     type Summary = ExcerptId;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         self.id
     }
 }
@@ -7287,7 +7287,7 @@ impl DiffTransform {
 impl sum_tree::Item for DiffTransform {
     type Summary = DiffTransformSummary;
 
-    fn summary(&self, _: &<Self::Summary as sum_tree::Summary>::Context) -> Self::Summary {
+    fn summary(&self, _: <Self::Summary as sum_tree::Summary>::Context<'_>) -> Self::Summary {
         match self {
             DiffTransform::BufferContent { summary, .. } => DiffTransformSummary {
                 input: *summary,
@@ -7307,83 +7307,77 @@ impl DiffTransformSummary {
     }
 }
 
-impl sum_tree::Summary for DiffTransformSummary {
-    type Context = ();
-
-    fn zero(_: &Self::Context) -> Self {
+impl sum_tree::ContextLessSummary for DiffTransformSummary {
+    fn zero() -> Self {
         DiffTransformSummary {
             input: TextSummary::default(),
             output: TextSummary::default(),
         }
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &Self::Context) {
-        self.input += &summary.input;
-        self.output += &summary.output;
+    fn add_summary(&mut self, other: &Self) {
+        self.input += other.input;
+        self.output += other.output;
     }
 }
 
-impl sum_tree::Summary for ExcerptId {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
-        Default::default()
+impl sum_tree::ContextLessSummary for ExcerptId {
+    fn zero() -> Self {
+        Self(0)
     }
 
-    fn add_summary(&mut self, other: &Self, _: &()) {
-        *self = *other;
+    fn add_summary(&mut self, summary: &Self) {
+        *self = cmp::max(*self, *summary);
     }
 }
 
-impl sum_tree::Summary for ExcerptSummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
-        Default::default()
+impl sum_tree::ContextLessSummary for ExcerptSummary {
+    fn zero() -> Self {
+        Self::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &()) {
+    fn add_summary(&mut self, summary: &Self) {
         debug_assert!(summary.excerpt_locator > self.excerpt_locator);
         self.excerpt_locator = summary.excerpt_locator.clone();
-        Summary::add_summary(&mut self.text, &summary.text, &());
+        Summary::add_summary(&mut self.text, &summary.text, ());
         self.widest_line_number = cmp::max(self.widest_line_number, summary.widest_line_number);
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for ExcerptOffset {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: ()) {
         self.value += summary.text.len;
     }
 }
 
 impl sum_tree::SeekTarget<'_, ExcerptSummary, ExcerptSummary> for ExcerptOffset {
-    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
+    fn cmp(&self, cursor_location: &ExcerptSummary, _: ()) -> cmp::Ordering {
         Ord::cmp(&self.value, &cursor_location.text.len)
     }
 }
 
 impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, Option<&'a Locator>> for Locator {
-    fn cmp(&self, cursor_location: &Option<&'a Locator>, _: &()) -> cmp::Ordering {
+    fn cmp(&self, cursor_location: &Option<&'a Locator>, _: ()) -> cmp::Ordering {
         Ord::cmp(&Some(self), cursor_location)
     }
 }
 
 impl sum_tree::SeekTarget<'_, ExcerptSummary, ExcerptSummary> for Locator {
-    fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
+    fn cmp(&self, cursor_location: &ExcerptSummary, _: ()) -> cmp::Ordering {
         Ord::cmp(self, &cursor_location.excerpt_locator)
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for ExcerptPoint {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: ()) {
         self.value += summary.text.lines;
     }
 }
@@ -7391,31 +7385,31 @@ impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for ExcerptPoint {
 impl<'a, D: TextDimension + Default> sum_tree::Dimension<'a, ExcerptSummary>
     for ExcerptDimension<D>
 {
-    fn zero(_: &()) -> Self {
+    fn zero(_: ()) -> Self {
         ExcerptDimension(D::default())
     }
 
-    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: ()) {
         self.0.add_assign(&D::from_text_summary(&summary.text))
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a Locator> {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
+    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 {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a ExcerptSummary, _: ()) {
         *self = Some(summary.excerpt_id);
     }
 }
@@ -7427,21 +7421,21 @@ struct ExcerptDimension<T>(T);
 struct OutputDimension<T>(T);
 
 impl<'a> sum_tree::Dimension<'a, DiffTransformSummary> for ExcerptOffset {
-    fn zero(_: &()) -> Self {
+    fn zero(_: ()) -> Self {
         ExcerptOffset::new(0)
     }
 
-    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: ()) {
         self.value += summary.input.len;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, DiffTransformSummary> for ExcerptPoint {
-    fn zero(_: &()) -> Self {
+    fn zero(_: ()) -> Self {
         ExcerptPoint::new(0, 0)
     }
 
-    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: ()) {
         self.value += summary.input.lines;
     }
 }
@@ -7449,7 +7443,7 @@ impl<'a> sum_tree::Dimension<'a, DiffTransformSummary> for ExcerptPoint {
 impl<D: TextDimension + Ord> sum_tree::SeekTarget<'_, DiffTransformSummary, DiffTransformSummary>
     for ExcerptDimension<D>
 {
-    fn cmp(&self, cursor_location: &DiffTransformSummary, _: &()) -> cmp::Ordering {
+    fn cmp(&self, cursor_location: &DiffTransformSummary, _: ()) -> cmp::Ordering {
         Ord::cmp(&self.0, &D::from_text_summary(&cursor_location.input))
     }
 }
@@ -7457,17 +7451,17 @@ impl<D: TextDimension + Ord> sum_tree::SeekTarget<'_, DiffTransformSummary, Diff
 impl<D: TextDimension + Ord> sum_tree::SeekTarget<'_, DiffTransformSummary, DiffTransforms<D>>
     for ExcerptDimension<D>
 {
-    fn cmp(&self, cursor_location: &DiffTransforms<D>, _: &()) -> cmp::Ordering {
+    fn cmp(&self, cursor_location: &DiffTransforms<D>, _: ()) -> cmp::Ordering {
         Ord::cmp(&self.0, &cursor_location.excerpt_dimension.0)
     }
 }
 
 impl<'a, D: TextDimension> sum_tree::Dimension<'a, DiffTransformSummary> for ExcerptDimension<D> {
-    fn zero(_: &()) -> Self {
+    fn zero(_: ()) -> Self {
         ExcerptDimension(D::default())
     }
 
-    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: ()) {
         self.0.add_assign(&D::from_text_summary(&summary.input))
     }
 }
@@ -7475,47 +7469,47 @@ impl<'a, D: TextDimension> sum_tree::Dimension<'a, DiffTransformSummary> for Exc
 impl<D: TextDimension + Ord> sum_tree::SeekTarget<'_, DiffTransformSummary, DiffTransforms<D>>
     for OutputDimension<D>
 {
-    fn cmp(&self, cursor_location: &DiffTransforms<D>, _: &()) -> cmp::Ordering {
+    fn cmp(&self, cursor_location: &DiffTransforms<D>, _: ()) -> cmp::Ordering {
         Ord::cmp(&self.0, &cursor_location.output_dimension.0)
     }
 }
 
 impl<'a, D: TextDimension> sum_tree::Dimension<'a, DiffTransformSummary> for OutputDimension<D> {
-    fn zero(_: &()) -> Self {
+    fn zero(_: ()) -> Self {
         OutputDimension(D::default())
     }
 
-    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: ()) {
         self.0.add_assign(&D::from_text_summary(&summary.output))
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, DiffTransformSummary> for TextSummary {
-    fn zero(_: &()) -> Self {
+    fn zero(_: ()) -> Self {
         TextSummary::default()
     }
 
-    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: ()) {
         *self += summary.output
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, DiffTransformSummary> for usize {
-    fn zero(_: &()) -> Self {
+    fn zero(_: ()) -> Self {
         0
     }
 
-    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: ()) {
         *self += summary.output.len
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, DiffTransformSummary> for Point {
-    fn zero(_: &()) -> Self {
+    fn zero(_: ()) -> Self {
         Point::new(0, 0)
     }
 
-    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a DiffTransformSummary, _: ()) {
         *self += summary.output.lines
     }
 }

crates/notifications/src/notification_store.rs 🔗

@@ -123,12 +123,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()
             && item.id == id
@@ -297,12 +297,12 @@ impl NotificationStore {
     ) {
         let mut cursor = self
             .notifications
-            .cursor::<Dimensions<NotificationId, Count>>(&());
+            .cursor::<Dimensions<NotificationId, Count>>(());
         let mut new_notifications = SumTree::default();
         let mut old_range = 0..0;
 
         for (i, (id, new_notification)) in notifications.into_iter().enumerate() {
-            new_notifications.append(cursor.slice(&NotificationId(id), Bias::Left), &());
+            new_notifications.append(cursor.slice(&NotificationId(id), Bias::Left), ());
 
             if i == 0 {
                 old_range.start = cursor.start().1.0;
@@ -334,13 +334,13 @@ impl NotificationStore {
             }
 
             if let Some(notification) = new_notification {
-                new_notifications.push(notification, &());
+                new_notifications.push(notification, ());
             }
         }
 
         old_range.end = cursor.start().1.0;
         let new_count = new_notifications.summary().count - old_range.start;
-        new_notifications.append(cursor.suffix(), &());
+        new_notifications.append(cursor.suffix(), ());
         drop(cursor);
 
         self.notifications = new_notifications;
@@ -381,7 +381,7 @@ impl EventEmitter<NotificationEvent> for NotificationStore {}
 impl sum_tree::Item for NotificationEntry {
     type Summary = NotificationSummary;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         NotificationSummary {
             max_id: self.id,
             count: 1,
@@ -390,14 +390,12 @@ impl sum_tree::Item for NotificationEntry {
     }
 }
 
-impl sum_tree::Summary for NotificationSummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for NotificationSummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &()) {
+    fn add_summary(&mut self, summary: &Self) {
         self.max_id = self.max_id.max(summary.max_id);
         self.count += summary.count;
         self.unread_count += summary.unread_count;
@@ -405,22 +403,22 @@ impl sum_tree::Summary for NotificationSummary {
 }
 
 impl sum_tree::Dimension<'_, NotificationSummary> for NotificationId {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &NotificationSummary, _: &()) {
+    fn add_summary(&mut self, summary: &NotificationSummary, _: ()) {
         debug_assert!(summary.max_id > self.0);
         self.0 = summary.max_id;
     }
 }
 
 impl sum_tree::Dimension<'_, NotificationSummary> for Count {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &NotificationSummary, _: &()) {
+    fn add_summary(&mut self, summary: &NotificationSummary, _: ()) {
         self.0 += summary.count;
     }
 }

crates/project/src/git_store.rs 🔗

@@ -209,7 +209,7 @@ impl TryFrom<proto::StatusEntry> for StatusEntry {
 impl sum_tree::Item for StatusEntry {
     type Summary = PathSummary<GitSummary>;
 
-    fn summary(&self, _: &<Self::Summary as sum_tree::Summary>::Context) -> Self::Summary {
+    fn summary(&self, _: <Self::Summary as sum_tree::Summary>::Context<'_>) -> Self::Summary {
         PathSummary {
             max_path: self.repo_path.0.clone(),
             item_summary: self.status.summary(),
@@ -2890,7 +2890,7 @@ impl RepositorySnapshot {
 
     pub fn status_for_path(&self, path: &RepoPath) -> Option<StatusEntry> {
         self.statuses_by_path
-            .get(&PathKey(path.0.clone()), &())
+            .get(&PathKey(path.0.clone()), ())
             .cloned()
     }
 
@@ -4470,7 +4470,7 @@ impl Repository {
                     }),
             )
             .collect::<Vec<_>>();
-        self.snapshot.statuses_by_path.edit(edits, &());
+        self.snapshot.statuses_by_path.edit(edits, ());
         if update.is_last_update {
             self.snapshot.scan_id = update.scan_id;
         }
@@ -4771,7 +4771,7 @@ impl Repository {
                     .background_spawn(async move {
                         let mut changed_path_statuses = Vec::new();
                         let prev_statuses = prev_snapshot.statuses_by_path.clone();
-                        let mut cursor = prev_statuses.cursor::<PathProgress>(&());
+                        let mut cursor = prev_statuses.cursor::<PathProgress>(());
 
                         for (repo_path, status) in &*statuses.entries {
                             changed_paths.remove(repo_path);
@@ -4786,7 +4786,7 @@ impl Repository {
                                 status: *status,
                             }));
                         }
-                        let mut cursor = prev_statuses.cursor::<PathProgress>(&());
+                        let mut cursor = prev_statuses.cursor::<PathProgress>(());
                         for path in changed_paths.into_iter() {
                             if cursor.seek_forward(&PathTarget::Path(&path), Bias::Left) {
                                 changed_path_statuses.push(Edit::Remove(PathKey(path.0)));
@@ -4803,7 +4803,7 @@ impl Repository {
                     if !changed_path_statuses.is_empty() {
                         this.snapshot
                             .statuses_by_path
-                            .edit(changed_path_statuses, &());
+                            .edit(changed_path_statuses, ());
                         this.snapshot.scan_id += 1;
                     }
 
@@ -5072,7 +5072,7 @@ async fn compute_snapshot(
                 repo_path: repo_path.clone(),
                 status: *status,
             }),
-        &(),
+        (),
     );
     let (merge_details, merge_heads_changed) =
         MergeDetails::load(&backend, &statuses_by_path, &prev_snapshot).await?;

crates/project/src/git_store/git_traversal.rs 🔗

@@ -12,7 +12,10 @@ pub struct GitTraversal<'a> {
     traversal: Traversal<'a>,
     current_entry_summary: Option<GitSummary>,
     repo_root_to_snapshot: BTreeMap<&'a Path, &'a RepositorySnapshot>,
-    repo_location: Option<(RepositoryId, Cursor<'a, StatusEntry, PathProgress<'a>>)>,
+    repo_location: Option<(
+        RepositoryId,
+        Cursor<'a, 'static, StatusEntry, PathProgress<'a>>,
+    )>,
 }
 
 impl<'a> GitTraversal<'a> {
@@ -85,7 +88,7 @@ impl<'a> GitTraversal<'a> {
                 .map(|(prev_repo_id, _)| *prev_repo_id)
                 != Some(repo.id)
         {
-            self.repo_location = Some((repo.id, repo.statuses_by_path.cursor::<PathProgress>(&())));
+            self.repo_location = Some((repo.id, repo.statuses_by_path.cursor::<PathProgress>(())));
         }
 
         let Some((_, statuses)) = &mut self.repo_location else {

crates/rope/benches/rope_benchmark.rs 🔗

@@ -144,7 +144,7 @@ fn rope_benchmarks(c: &mut Criterion) {
         group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
             let rope = generate_random_rope(rng.clone(), *size);
 
-            b.iter_with_large_drop(|| {
+            b.iter(|| {
                 let chars = rope.chars().count();
                 assert!(chars > 0);
             });
@@ -190,6 +190,34 @@ fn rope_benchmarks(c: &mut Criterion) {
         });
     }
     group.finish();
+
+    let mut group = c.benchmark_group("cursor");
+    for size in sizes.iter() {
+        group.throughput(Throughput::Bytes(*size as u64));
+        group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
+            let rope = generate_random_rope(rng.clone(), *size);
+
+            b.iter_batched(
+                || {
+                    let mut rng = rng.clone();
+                    let num_points = rope.len() / 10;
+
+                    let mut points = Vec::new();
+                    for _ in 0..num_points {
+                        points.push(rng.random_range(0..rope.len()));
+                    }
+                    points
+                },
+                |offsets| {
+                    for offset in offsets.iter() {
+                        black_box(rope.cursor(*offset));
+                    }
+                },
+                BatchSize::SmallInput,
+            );
+        });
+    }
+    group.finish();
 }
 
 criterion_group!(benches, rope_benchmarks);

crates/rope/src/rope.rs 🔗

@@ -34,7 +34,7 @@ impl Rope {
         if self.chunks.is_empty() {
             return offset == 0;
         }
-        let mut cursor = self.chunks.cursor::<usize>(&());
+        let mut cursor = self.chunks.cursor::<usize>(());
         cursor.seek(&offset, Bias::Left);
         let chunk_offset = offset - cursor.start();
         cursor
@@ -53,7 +53,7 @@ impl Rope {
                 (u8 as i8) >= -0x40
             }
 
-            let mut cursor = self.chunks.cursor::<usize>(&());
+            let mut cursor = self.chunks.cursor::<usize>(());
             cursor.seek(&index, Bias::Left);
             let chunk_offset = index - cursor.start();
             let lower_idx = cursor.item().map(|chunk| {
@@ -85,7 +85,7 @@ impl Rope {
                 (u8 as i8) >= -0x40
             }
 
-            let mut cursor = self.chunks.cursor::<usize>(&());
+            let mut cursor = self.chunks.cursor::<usize>(());
             cursor.seek(&index, Bias::Left);
             let chunk_offset = index - cursor.start();
             let upper_idx = cursor.item().map(|chunk| {
@@ -110,15 +110,15 @@ impl Rope {
         {
             self.push_chunk(chunk.as_slice());
 
-            let mut chunks = rope.chunks.cursor::<()>(&());
+            let mut chunks = rope.chunks.cursor::<()>(());
             chunks.next();
             chunks.next();
-            self.chunks.append(chunks.suffix(), &());
+            self.chunks.append(chunks.suffix(), ());
             self.check_invariants();
             return;
         }
 
-        self.chunks.append(rope.chunks.clone(), &());
+        self.chunks.append(rope.chunks.clone(), ());
         self.check_invariants();
     }
 
@@ -165,7 +165,7 @@ impl Rope {
                 last_chunk.push_str(suffix);
                 text = remainder;
             },
-            &(),
+            (),
         );
 
         if text.len() > 2048 {
@@ -190,10 +190,10 @@ impl Rope {
 
         if new_chunks.len() >= PARALLEL_THRESHOLD {
             self.chunks
-                .par_extend(new_chunks.into_vec().into_par_iter().map(Chunk::new), &());
+                .par_extend(new_chunks.into_vec().into_par_iter().map(Chunk::new), ());
         } else {
             self.chunks
-                .extend(new_chunks.into_iter().map(Chunk::new), &());
+                .extend(new_chunks.into_iter().map(Chunk::new), ());
         }
 
         self.check_invariants();
@@ -234,10 +234,10 @@ impl Rope {
 
         if new_chunks.len() >= PARALLEL_THRESHOLD {
             self.chunks
-                .par_extend(new_chunks.into_par_iter().map(Chunk::new), &());
+                .par_extend(new_chunks.into_par_iter().map(Chunk::new), ());
         } else {
             self.chunks
-                .extend(new_chunks.into_iter().map(Chunk::new), &());
+                .extend(new_chunks.into_iter().map(Chunk::new), ());
         }
 
         self.check_invariants();
@@ -263,11 +263,11 @@ impl Rope {
                 last_chunk.append(suffix);
                 chunk = remainder;
             },
-            &(),
+            (),
         );
 
         if !chunk.is_empty() {
-            self.chunks.push(chunk.into(), &());
+            self.chunks.push(chunk.into(), ());
         }
     }
 
@@ -281,7 +281,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.text.len() + 3 >= chunk::MIN_BASE);
@@ -295,7 +295,7 @@ impl Rope {
     }
 
     pub fn len(&self) -> usize {
-        self.chunks.extent(&())
+        self.chunks.extent(())
     }
 
     pub fn is_empty(&self) -> bool {
@@ -303,11 +303,11 @@ impl Rope {
     }
 
     pub fn max_point(&self) -> Point {
-        self.chunks.extent(&())
+        self.chunks.extent(())
     }
 
     pub fn max_point_utf16(&self) -> PointUtf16 {
-        self.chunks.extent(&())
+        self.chunks.extent(())
     }
 
     pub fn cursor(&self, offset: usize) -> Cursor<'_> {
@@ -351,7 +351,7 @@ impl Rope {
         if offset >= self.summary().len {
             return self.summary().len_utf16;
         }
-        let mut cursor = self.chunks.cursor::<Dimensions<usize, OffsetUtf16>>(&());
+        let mut cursor = self.chunks.cursor::<Dimensions<usize, OffsetUtf16>>(());
         cursor.seek(&offset, Bias::Left);
         let overshoot = offset - cursor.start().0;
         cursor.start().1
@@ -364,7 +364,7 @@ impl Rope {
         if offset >= self.summary().len_utf16 {
             return self.summary().len;
         }
-        let mut cursor = self.chunks.cursor::<Dimensions<OffsetUtf16, usize>>(&());
+        let mut cursor = self.chunks.cursor::<Dimensions<OffsetUtf16, usize>>(());
         cursor.seek(&offset, Bias::Left);
         let overshoot = offset - cursor.start().0;
         cursor.start().1
@@ -377,7 +377,7 @@ impl Rope {
         if offset >= self.summary().len {
             return self.summary().lines;
         }
-        let mut cursor = self.chunks.cursor::<Dimensions<usize, Point>>(&());
+        let mut cursor = self.chunks.cursor::<Dimensions<usize, Point>>(());
         cursor.seek(&offset, Bias::Left);
         let overshoot = offset - cursor.start().0;
         cursor.start().1
@@ -390,7 +390,7 @@ impl Rope {
         if offset >= self.summary().len {
             return self.summary().lines_utf16();
         }
-        let mut cursor = self.chunks.cursor::<Dimensions<usize, PointUtf16>>(&());
+        let mut cursor = self.chunks.cursor::<Dimensions<usize, PointUtf16>>(());
         cursor.seek(&offset, Bias::Left);
         let overshoot = offset - cursor.start().0;
         cursor.start().1
@@ -403,7 +403,7 @@ impl Rope {
         if point >= self.summary().lines {
             return self.summary().lines_utf16();
         }
-        let mut cursor = self.chunks.cursor::<Dimensions<Point, PointUtf16>>(&());
+        let mut cursor = self.chunks.cursor::<Dimensions<Point, PointUtf16>>(());
         cursor.seek(&point, Bias::Left);
         let overshoot = point - cursor.start().0;
         cursor.start().1
@@ -416,7 +416,7 @@ impl Rope {
         if point >= self.summary().lines {
             return self.summary().len;
         }
-        let mut cursor = self.chunks.cursor::<Dimensions<Point, usize>>(&());
+        let mut cursor = self.chunks.cursor::<Dimensions<Point, usize>>(());
         cursor.seek(&point, Bias::Left);
         let overshoot = point - cursor.start().0;
         cursor.start().1
@@ -437,7 +437,7 @@ impl Rope {
         if point >= self.summary().lines_utf16() {
             return self.summary().len;
         }
-        let mut cursor = self.chunks.cursor::<Dimensions<PointUtf16, usize>>(&());
+        let mut cursor = self.chunks.cursor::<Dimensions<PointUtf16, usize>>(());
         cursor.seek(&point, Bias::Left);
         let overshoot = point - cursor.start().0;
         cursor.start().1
@@ -450,7 +450,7 @@ impl Rope {
         if point.0 >= self.summary().lines_utf16() {
             return self.summary().lines;
         }
-        let mut cursor = self.chunks.cursor::<Dimensions<PointUtf16, Point>>(&());
+        let mut cursor = self.chunks.cursor::<Dimensions<PointUtf16, Point>>(());
         cursor.seek(&point.0, Bias::Left);
         let overshoot = Unclipped(point.0 - cursor.start().0);
         cursor.start().1
@@ -467,7 +467,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();
@@ -478,7 +478,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();
@@ -489,7 +489,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());
@@ -564,13 +564,13 @@ impl fmt::Debug for Rope {
 
 pub struct Cursor<'a> {
     rope: &'a Rope,
-    chunks: sum_tree::Cursor<'a, Chunk, usize>,
+    chunks: sum_tree::Cursor<'a, 'static, Chunk, usize>,
     offset: usize,
 }
 
 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,
@@ -619,7 +619,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::zero(&());
+        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();
@@ -640,7 +640,7 @@ impl<'a> Cursor<'a> {
     }
 
     pub fn suffix(mut self) -> Rope {
-        self.slice(self.rope.chunks.extent(&()))
+        self.slice(self.rope.chunks.extent(()))
     }
 
     pub fn offset(&self) -> usize {
@@ -659,7 +659,7 @@ pub struct ChunkBitmaps<'a> {
 
 #[derive(Clone)]
 pub struct Chunks<'a> {
-    chunks: sum_tree::Cursor<'a, Chunk, usize>,
+    chunks: sum_tree::Cursor<'a, 'static, Chunk, usize>,
     range: Range<usize>,
     offset: usize,
     reversed: bool,
@@ -667,7 +667,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
@@ -994,14 +994,14 @@ impl<'a> Iterator for Chunks<'a> {
 }
 
 pub struct Bytes<'a> {
-    chunks: sum_tree::Cursor<'a, Chunk, usize>,
+    chunks: sum_tree::Cursor<'a, 'static, Chunk, usize>,
     range: Range<usize>,
     reversed: bool,
 }
 
 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 {
@@ -1079,7 +1079,7 @@ pub struct Lines<'a> {
     reversed: bool,
 }
 
-impl Lines<'_> {
+impl<'a> Lines<'a> {
     pub fn next(&mut self) -> Option<&str> {
         if self.done {
             return None;
@@ -1144,7 +1144,7 @@ impl Lines<'_> {
 impl sum_tree::Item for Chunk {
     type Summary = ChunkSummary;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         ChunkSummary {
             text: self.as_slice().text_summary(),
         }
@@ -1156,14 +1156,12 @@ pub struct ChunkSummary {
     text: TextSummary,
 }
 
-impl sum_tree::Summary for ChunkSummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for ChunkSummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &()) {
+    fn add_summary(&mut self, summary: &Self) {
         self.text += &summary.text;
     }
 }
@@ -1273,14 +1271,12 @@ impl<'a> From<&'a str> for TextSummary {
     }
 }
 
-impl sum_tree::Summary for TextSummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for TextSummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &Self::Context) {
+    fn add_summary(&mut self, summary: &Self) {
         *self += summary;
     }
 }
@@ -1359,11 +1355,11 @@ impl<D1: TextDimension, D2: TextDimension> TextDimension for Dimensions<D1, D2,
 }
 
 impl<'a> sum_tree::Dimension<'a, ChunkSummary> for TextSummary {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a ChunkSummary, _: ()) {
         *self += &summary.text;
     }
 }
@@ -1383,11 +1379,11 @@ impl TextDimension for TextSummary {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChunkSummary> for usize {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a ChunkSummary, _: ()) {
         *self += summary.text.len;
     }
 }
@@ -1407,11 +1403,11 @@ impl TextDimension for usize {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChunkSummary> for OffsetUtf16 {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a ChunkSummary, _: ()) {
         *self += summary.text.len_utf16;
     }
 }
@@ -1431,11 +1427,11 @@ impl TextDimension for OffsetUtf16 {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChunkSummary> for Point {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a ChunkSummary, _: ()) {
         *self += summary.text.lines;
     }
 }
@@ -1455,11 +1451,11 @@ impl TextDimension for Point {
 }
 
 impl<'a> sum_tree::Dimension<'a, ChunkSummary> for PointUtf16 {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a ChunkSummary, _: ()) {
         *self += summary.text.lines_utf16();
     }
 }
@@ -1547,14 +1543,14 @@ where
     K: sum_tree::Dimension<'a, ChunkSummary>,
     V: sum_tree::Dimension<'a, ChunkSummary>,
 {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Self {
             key: K::zero(_cx),
             value: Some(V::zero(_cx)),
         }
     }
 
-    fn add_summary(&mut self, summary: &'a ChunkSummary, _cx: &()) {
+    fn add_summary(&mut self, summary: &'a ChunkSummary, _cx: ()) {
         self.key.add_summary(summary, _cx);
         if let Some(value) = &mut self.value {
             value.add_summary(summary, _cx);
@@ -2233,7 +2229,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.text);
             }
             text

crates/rope/src/unclipped.rs 🔗

@@ -13,12 +13,12 @@ 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 zero(_: ()) -> Self {
+        Self(T::zero(()))
     }
 
-    fn add_summary(&mut self, summary: &'a ChunkSummary, _: &()) {
-        self.0.add_summary(summary, &());
+    fn add_summary(&mut self, summary: &'a ChunkSummary, _: ()) {
+        self.0.add_summary(summary, ());
     }
 }
 

crates/sum_tree/src/cursor.rs 🔗

@@ -5,10 +5,17 @@ use std::{cmp::Ordering, mem, sync::Arc};
 #[derive(Clone)]
 struct StackEntry<'a, T: Item, D> {
     tree: &'a SumTree<T>,
-    index: usize,
+    index: u32,
     position: D,
 }
 
+impl<'a, T: Item, D> StackEntry<'a, T, D> {
+    #[inline]
+    fn index(&self) -> usize {
+        self.index as usize
+    }
+}
+
 impl<T: Item + fmt::Debug, D: fmt::Debug> fmt::Debug for StackEntry<'_, T, D> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("StackEntry")
@@ -19,16 +26,16 @@ impl<T: Item + fmt::Debug, D: fmt::Debug> fmt::Debug for StackEntry<'_, T, D> {
 }
 
 #[derive(Clone)]
-pub struct Cursor<'a, T: Item, D> {
+pub struct Cursor<'a, 'b, T: Item, D> {
     tree: &'a SumTree<T>,
     stack: ArrayVec<StackEntry<'a, T, D>, 16>,
     position: D,
     did_seek: bool,
     at_end: bool,
-    cx: &'a <T::Summary as Summary>::Context,
+    cx: <T::Summary as Summary>::Context<'b>,
 }
 
-impl<T: Item + fmt::Debug, D: fmt::Debug> fmt::Debug for Cursor<'_, T, D>
+impl<T: Item + fmt::Debug, D: fmt::Debug> fmt::Debug for Cursor<'_, '_, T, D>
 where
     T::Summary: fmt::Debug,
 {
@@ -48,12 +55,12 @@ pub struct Iter<'a, T: Item> {
     stack: ArrayVec<StackEntry<'a, T, ()>, 16>,
 }
 
-impl<'a, T, D> Cursor<'a, T, D>
+impl<'a, 'b, T, D> Cursor<'a, 'b, T, D>
 where
     T: Item,
     D: Dimension<'a, T::Summary>,
 {
-    pub fn new(tree: &'a SumTree<T>, cx: &'a <T::Summary as Summary>::Context) -> Self {
+    pub fn new(tree: &'a SumTree<T>, cx: <T::Summary as Summary>::Context<'b>) -> Self {
         Self {
             tree,
             stack: ArrayVec::new(),
@@ -93,10 +100,10 @@ where
         if let Some(entry) = self.stack.last() {
             match *entry.tree.0 {
                 Node::Leaf { ref items, .. } => {
-                    if entry.index == items.len() {
+                    if entry.index() == items.len() {
                         None
                     } else {
-                        Some(&items[entry.index])
+                        Some(&items[entry.index()])
                     }
                 }
                 _ => unreachable!(),
@@ -114,10 +121,10 @@ where
                 Node::Leaf {
                     ref item_summaries, ..
                 } => {
-                    if entry.index == item_summaries.len() {
+                    if entry.index() == item_summaries.len() {
                         None
                     } else {
-                        Some(&item_summaries[entry.index])
+                        Some(&item_summaries[entry.index()])
                     }
                 }
                 _ => unreachable!(),
@@ -131,7 +138,7 @@ where
     pub fn next_item(&self) -> Option<&'a T> {
         self.assert_did_seek();
         if let Some(entry) = self.stack.last() {
-            if entry.index == entry.tree.0.items().len() - 1 {
+            if entry.index() == entry.tree.0.items().len() - 1 {
                 if let Some(next_leaf) = self.next_leaf() {
                     Some(next_leaf.0.items().first().unwrap())
                 } else {
@@ -139,7 +146,7 @@ where
                 }
             } else {
                 match *entry.tree.0 {
-                    Node::Leaf { ref items, .. } => Some(&items[entry.index + 1]),
+                    Node::Leaf { ref items, .. } => Some(&items[entry.index() + 1]),
                     _ => unreachable!(),
                 }
             }
@@ -153,11 +160,11 @@ where
     #[track_caller]
     fn next_leaf(&self) -> Option<&'a SumTree<T>> {
         for entry in self.stack.iter().rev().skip(1) {
-            if entry.index < entry.tree.0.child_trees().len() - 1 {
+            if entry.index() < entry.tree.0.child_trees().len() - 1 {
                 match *entry.tree.0 {
                     Node::Internal {
                         ref child_trees, ..
-                    } => return Some(child_trees[entry.index + 1].leftmost_leaf()),
+                    } => return Some(child_trees[entry.index() + 1].leftmost_leaf()),
                     Node::Leaf { .. } => unreachable!(),
                 };
             }
@@ -169,7 +176,7 @@ where
     pub fn prev_item(&self) -> Option<&'a T> {
         self.assert_did_seek();
         if let Some(entry) = self.stack.last() {
-            if entry.index == 0 {
+            if entry.index() == 0 {
                 if let Some(prev_leaf) = self.prev_leaf() {
                     Some(prev_leaf.0.items().last().unwrap())
                 } else {
@@ -177,7 +184,7 @@ where
                 }
             } else {
                 match *entry.tree.0 {
-                    Node::Leaf { ref items, .. } => Some(&items[entry.index - 1]),
+                    Node::Leaf { ref items, .. } => Some(&items[entry.index() - 1]),
                     _ => unreachable!(),
                 }
             }
@@ -191,11 +198,11 @@ where
     #[track_caller]
     fn prev_leaf(&self) -> Option<&'a SumTree<T>> {
         for entry in self.stack.iter().rev().skip(1) {
-            if entry.index != 0 {
+            if entry.index() != 0 {
                 match *entry.tree.0 {
                     Node::Internal {
                         ref child_trees, ..
-                    } => return Some(child_trees[entry.index - 1].rightmost_leaf()),
+                    } => return Some(child_trees[entry.index() - 1].rightmost_leaf()),
                     Node::Leaf { .. } => unreachable!(),
                 };
             }
@@ -224,7 +231,7 @@ where
             if !self.tree.is_empty() {
                 self.stack.push(StackEntry {
                     tree: self.tree,
-                    index: self.tree.0.child_summaries().len(),
+                    index: self.tree.0.child_summaries().len() as u32,
                     position: D::from_summary(self.tree.summary(), self.cx),
                 });
             }
@@ -240,7 +247,7 @@ where
 
             let entry = self.stack.last_mut().unwrap();
             if !descending {
-                if entry.index == 0 {
+                if entry.index() == 0 {
                     self.stack.pop();
                     continue;
                 } else {
@@ -248,20 +255,20 @@ where
                 }
             }
 
-            for summary in &entry.tree.0.child_summaries()[..entry.index] {
+            for summary in &entry.tree.0.child_summaries()[..entry.index()] {
                 self.position.add_summary(summary, self.cx);
             }
             entry.position = self.position.clone();
 
-            descending = filter_node(&entry.tree.0.child_summaries()[entry.index]);
+            descending = filter_node(&entry.tree.0.child_summaries()[entry.index()]);
             match entry.tree.0.as_ref() {
                 Node::Internal { child_trees, .. } => {
                     if descending {
-                        let tree = &child_trees[entry.index];
+                        let tree = &child_trees[entry.index()];
                         self.stack.push(StackEntry {
                             position: D::zero(self.cx),
                             tree,
-                            index: tree.0.child_summaries().len() - 1,
+                            index: tree.0.child_summaries().len() as u32 - 1,
                         })
                     }
                 }
@@ -312,8 +319,8 @@ where
                             entry.position = self.position.clone();
                         }
 
-                        while entry.index < child_summaries.len() {
-                            let next_summary = &child_summaries[entry.index];
+                        while entry.index() < child_summaries.len() {
+                            let next_summary = &child_summaries[entry.index()];
                             if filter_node(next_summary) {
                                 break;
                             } else {
@@ -323,18 +330,18 @@ where
                             }
                         }
 
-                        child_trees.get(entry.index)
+                        child_trees.get(entry.index())
                     }
                     Node::Leaf { item_summaries, .. } => {
                         if !descend {
-                            let item_summary = &item_summaries[entry.index];
+                            let item_summary = &item_summaries[entry.index()];
                             entry.index += 1;
                             entry.position.add_summary(item_summary, self.cx);
                             self.position.add_summary(item_summary, self.cx);
                         }
 
                         loop {
-                            if let Some(next_item_summary) = item_summaries.get(entry.index) {
+                            if let Some(next_item_summary) = item_summaries.get(entry.index()) {
                                 if filter_node(next_item_summary) {
                                     return;
                                 } else {
@@ -376,7 +383,7 @@ where
     }
 }
 
-impl<'a, T, D> Cursor<'a, T, D>
+impl<'a, 'b, T, D> Cursor<'a, 'b, T, D>
 where
     T: Item,
     D: Dimension<'a, T::Summary>,
@@ -465,9 +472,9 @@ where
                         entry.position = self.position.clone();
                     }
 
-                    for (child_tree, child_summary) in child_trees[entry.index..]
+                    for (child_tree, child_summary) in child_trees[entry.index()..]
                         .iter()
-                        .zip(&child_summaries[entry.index..])
+                        .zip(&child_summaries[entry.index()..])
                     {
                         let mut child_end = self.position.clone();
                         child_end.add_summary(child_summary, self.cx);
@@ -498,9 +505,9 @@ where
                 } => {
                     aggregate.begin_leaf();
 
-                    for (item, item_summary) in items[entry.index..]
+                    for (item, item_summary) in items[entry.index()..]
                         .iter()
-                        .zip(&item_summaries[entry.index..])
+                        .zip(&item_summaries[entry.index()..])
                     {
                         let mut child_end = self.position.clone();
                         child_end.add_summary(item_summary, self.cx);
@@ -572,14 +579,14 @@ impl<'a, T: Item> Iterator for Iter<'a, T> {
                         if !descend {
                             entry.index += 1;
                         }
-                        child_trees.get(entry.index)
+                        child_trees.get(entry.index())
                     }
                     Node::Leaf { items, .. } => {
                         if !descend {
                             entry.index += 1;
                         }
 
-                        if let Some(next_item) = items.get(entry.index) {
+                        if let Some(next_item) = items.get(entry.index()) {
                             return Some(next_item);
                         } else {
                             None
@@ -605,7 +612,7 @@ impl<'a, T: Item> Iterator for Iter<'a, T> {
     }
 }
 
-impl<'a, T: Item, D> Iterator for Cursor<'a, T, D>
+impl<'a, 'b, T: Item, D> Iterator for Cursor<'a, 'b, T, D>
 where
     D: Dimension<'a, T::Summary>,
 {
@@ -625,12 +632,12 @@ where
     }
 }
 
-pub struct FilterCursor<'a, F, T: Item, D> {
-    cursor: Cursor<'a, T, D>,
+pub struct FilterCursor<'a, 'b, F, T: Item, D> {
+    cursor: Cursor<'a, 'b, T, D>,
     filter_node: F,
 }
 
-impl<'a, F, T: Item, D> FilterCursor<'a, F, T, D>
+impl<'a, 'b, F, T: Item, D> FilterCursor<'a, 'b, F, T, D>
 where
     F: FnMut(&T::Summary) -> bool,
     T: Item,
@@ -638,7 +645,7 @@ where
 {
     pub fn new(
         tree: &'a SumTree<T>,
-        cx: &'a <T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'b>,
         filter_node: F,
     ) -> Self {
         let cursor = tree.cursor::<D>(cx);
@@ -673,7 +680,7 @@ where
     }
 }
 
-impl<'a, F, T: Item, U> Iterator for FilterCursor<'a, F, T, U>
+impl<'a, 'b, F, T: Item, U> Iterator for FilterCursor<'a, 'b, F, T, U>
 where
     F: FnMut(&T::Summary) -> bool,
     U: Dimension<'a, T::Summary>,
@@ -696,18 +703,18 @@ where
 
 trait SeekAggregate<'a, T: Item> {
     fn begin_leaf(&mut self);
-    fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context);
+    fn end_leaf(&mut self, cx: <T::Summary as Summary>::Context<'_>);
     fn push_item(
         &mut self,
         item: &'a T,
         summary: &'a T::Summary,
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'_>,
     );
     fn push_tree(
         &mut self,
         tree: &'a SumTree<T>,
         summary: &'a T::Summary,
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'_>,
     );
 }
 
@@ -722,14 +729,20 @@ struct SummarySeekAggregate<D>(D);
 
 impl<T: Item> SeekAggregate<'_, T> for () {
     fn begin_leaf(&mut self) {}
-    fn end_leaf(&mut self, _: &<T::Summary as Summary>::Context) {}
-    fn push_item(&mut self, _: &T, _: &T::Summary, _: &<T::Summary as Summary>::Context) {}
-    fn push_tree(&mut self, _: &SumTree<T>, _: &T::Summary, _: &<T::Summary as Summary>::Context) {}
+    fn end_leaf(&mut self, _: <T::Summary as Summary>::Context<'_>) {}
+    fn push_item(&mut self, _: &T, _: &T::Summary, _: <T::Summary as Summary>::Context<'_>) {}
+    fn push_tree(
+        &mut self,
+        _: &SumTree<T>,
+        _: &T::Summary,
+        _: <T::Summary as Summary>::Context<'_>,
+    ) {
+    }
 }
 
 impl<T: Item> SeekAggregate<'_, T> for SliceSeekAggregate<T> {
     fn begin_leaf(&mut self) {}
-    fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context) {
+    fn end_leaf(&mut self, cx: <T::Summary as Summary>::Context<'_>) {
         self.tree.append(
             SumTree(Arc::new(Node::Leaf {
                 summary: mem::replace(&mut self.leaf_summary, <T::Summary as Summary>::zero(cx)),
@@ -739,7 +752,12 @@ impl<T: Item> SeekAggregate<'_, T> for SliceSeekAggregate<T> {
             cx,
         );
     }
-    fn push_item(&mut self, item: &T, summary: &T::Summary, cx: &<T::Summary as Summary>::Context) {
+    fn push_item(
+        &mut self,
+        item: &T,
+        summary: &T::Summary,
+        cx: <T::Summary as Summary>::Context<'_>,
+    ) {
         self.leaf_items.push(item.clone());
         self.leaf_item_summaries.push(summary.clone());
         Summary::add_summary(&mut self.leaf_summary, summary, cx);
@@ -748,7 +766,7 @@ impl<T: Item> SeekAggregate<'_, T> for SliceSeekAggregate<T> {
         &mut self,
         tree: &SumTree<T>,
         _: &T::Summary,
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'_>,
     ) {
         self.tree.append(tree.clone(), cx);
     }
@@ -759,15 +777,20 @@ where
     D: Dimension<'a, T::Summary>,
 {
     fn begin_leaf(&mut self) {}
-    fn end_leaf(&mut self, _: &<T::Summary as Summary>::Context) {}
-    fn push_item(&mut self, _: &T, summary: &'a T::Summary, cx: &<T::Summary as Summary>::Context) {
+    fn end_leaf(&mut self, _: <T::Summary as Summary>::Context<'_>) {}
+    fn push_item(
+        &mut self,
+        _: &T,
+        summary: &'a T::Summary,
+        cx: <T::Summary as Summary>::Context<'_>,
+    ) {
         self.0.add_summary(summary, cx);
     }
     fn push_tree(
         &mut self,
         _: &SumTree<T>,
         summary: &'a T::Summary,
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'_>,
     ) {
         self.0.add_summary(summary, cx);
     }
@@ -782,7 +805,7 @@ impl<D> End<D> {
 }
 
 impl<'a, S: Summary, D: Dimension<'a, S>> SeekTarget<'a, S, D> for End<D> {
-    fn cmp(&self, _: &D, _: &S::Context) -> Ordering {
+    fn cmp(&self, _: &D, _: S::Context<'_>) -> Ordering {
         Ordering::Greater
     }
 }

crates/sum_tree/src/sum_tree.rs 🔗

@@ -20,7 +20,7 @@ pub const TREE_BASE: usize = 6;
 pub trait Item: Clone {
     type Summary: Summary;
 
-    fn summary(&self, cx: &<Self::Summary as Summary>::Context) -> Self::Summary;
+    fn summary(&self, cx: <Self::Summary as Summary>::Context<'_>) -> Self::Summary;
 }
 
 /// An [`Item`] whose summary has a specific key that can be used to identify it
@@ -35,23 +35,40 @@ pub trait KeyedItem: Item {
 /// Each Summary type can have multiple [`Dimension`]s that it measures,
 /// which can be used to navigate the tree
 pub trait Summary: Clone {
-    type Context;
+    type Context<'a>: Copy;
+    fn zero<'a>(cx: Self::Context<'a>) -> Self;
+    fn add_summary<'a>(&mut self, summary: &Self, cx: Self::Context<'a>);
+}
 
-    fn zero(cx: &Self::Context) -> Self;
-    fn add_summary(&mut self, summary: &Self, cx: &Self::Context);
+pub trait ContextLessSummary: Clone {
+    fn zero() -> Self;
+    fn add_summary(&mut self, summary: &Self);
 }
 
+impl<T: ContextLessSummary> Summary for T {
+    type Context<'a> = ();
+
+    fn zero<'a>((): ()) -> Self {
+        T::zero()
+    }
+
+    fn add_summary<'a>(&mut self, summary: &Self, (): ()) {
+        T::add_summary(self, summary)
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct NoSummary;
+
 /// Catch-all implementation for when you need something that implements [`Summary`] without a specific type.
-/// We implement it on a &'static, as that avoids blanket impl collisions with `impl<T: Summary> Dimension for T`
+/// We implement it on a `NoSummary` instead of re-using `()`, as that avoids blanket impl collisions with `impl<T: Summary> Dimension for T`
 /// (as we also need unit type to be a fill-in dimension)
-impl Summary for &'static () {
-    type Context = ();
-
-    fn zero(_: &()) -> Self {
-        &()
+impl ContextLessSummary for NoSummary {
+    fn zero() -> Self {
+        NoSummary
     }
 
-    fn add_summary(&mut self, _: &Self, _: &()) {}
+    fn add_summary(&mut self, _: &Self) {}
 }
 
 /// Each [`Summary`] type can have more than one [`Dimension`] type that it measures.
@@ -62,11 +79,11 @@ impl Summary for &'static () {
 /// 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 {
-    fn zero(cx: &S::Context) -> Self;
+    fn zero(cx: S::Context<'_>) -> Self;
 
-    fn add_summary(&mut self, summary: &'a S, cx: &S::Context);
+    fn add_summary(&mut self, summary: &'a S, cx: S::Context<'_>);
 
-    fn from_summary(summary: &'a S, cx: &S::Context) -> Self {
+    fn from_summary(summary: &'a S, cx: S::Context<'_>) -> Self {
         let mut dimension = Self::zero(cx);
         dimension.add_summary(summary, cx);
         dimension
@@ -74,29 +91,29 @@ pub trait Dimension<'a, S: Summary>: Clone {
 }
 
 impl<'a, T: Summary> Dimension<'a, T> for T {
-    fn zero(cx: &T::Context) -> Self {
+    fn zero(cx: T::Context<'_>) -> Self {
         Summary::zero(cx)
     }
 
-    fn add_summary(&mut self, summary: &'a T, cx: &T::Context) {
+    fn add_summary(&mut self, summary: &'a T, cx: T::Context<'_>) {
         Summary::add_summary(self, summary, cx);
     }
 }
 
 pub trait SeekTarget<'a, S: Summary, D: Dimension<'a, S>> {
-    fn cmp(&self, cursor_location: &D, cx: &S::Context) -> Ordering;
+    fn cmp(&self, cursor_location: &D, cx: S::Context<'_>) -> Ordering;
 }
 
 impl<'a, S: Summary, D: Dimension<'a, S> + Ord> SeekTarget<'a, S, D> for D {
-    fn cmp(&self, cursor_location: &Self, _: &S::Context) -> Ordering {
+    fn cmp(&self, cursor_location: &Self, _: S::Context<'_>) -> Ordering {
         Ord::cmp(self, cursor_location)
     }
 }
 
 impl<'a, T: Summary> Dimension<'a, T> for () {
-    fn zero(_: &T::Context) -> Self {}
+    fn zero(_: T::Context<'_>) -> Self {}
 
-    fn add_summary(&mut self, _: &'a T, _: &T::Context) {}
+    fn add_summary(&mut self, _: &'a T, _: T::Context<'_>) {}
 }
 
 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
@@ -105,11 +122,11 @@ pub struct Dimensions<D1, D2, D3 = ()>(pub D1, pub D2, pub D3);
 impl<'a, T: Summary, D1: Dimension<'a, T>, D2: Dimension<'a, T>, D3: Dimension<'a, T>>
     Dimension<'a, T> for Dimensions<D1, D2, D3>
 {
-    fn zero(cx: &T::Context) -> Self {
+    fn zero(cx: T::Context<'_>) -> Self {
         Dimensions(D1::zero(cx), D2::zero(cx), D3::zero(cx))
     }
 
-    fn add_summary(&mut self, summary: &'a T, cx: &T::Context) {
+    fn add_summary(&mut self, summary: &'a T, cx: T::Context<'_>) {
         self.0.add_summary(summary, cx);
         self.1.add_summary(summary, cx);
         self.2.add_summary(summary, cx);
@@ -123,7 +140,7 @@ where
     D2: Dimension<'a, S>,
     D3: Dimension<'a, S>,
 {
-    fn cmp(&self, cursor_location: &Dimensions<D1, D2, D3>, cx: &S::Context) -> Ordering {
+    fn cmp(&self, cursor_location: &Dimensions<D1, D2, D3>, cx: S::Context<'_>) -> Ordering {
         self.cmp(&cursor_location.0, cx)
     }
 }
@@ -187,7 +204,7 @@ where
 }
 
 impl<T: Item> SumTree<T> {
-    pub fn new(cx: &<T::Summary as Summary>::Context) -> Self {
+    pub fn new(cx: <T::Summary as Summary>::Context<'_>) -> Self {
         SumTree(Arc::new(Node::Leaf {
             summary: <T::Summary as Summary>::zero(cx),
             items: ArrayVec::new(),
@@ -204,7 +221,7 @@ impl<T: Item> SumTree<T> {
         }))
     }
 
-    pub fn from_item(item: T, cx: &<T::Summary as Summary>::Context) -> Self {
+    pub fn from_item(item: T, cx: <T::Summary as Summary>::Context<'_>) -> Self {
         let mut tree = Self::new(cx);
         tree.push(item, cx);
         tree
@@ -212,7 +229,7 @@ impl<T: Item> SumTree<T> {
 
     pub fn from_iter<I: IntoIterator<Item = T>>(
         iter: I,
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'_>,
     ) -> Self {
         let mut nodes = Vec::new();
 
@@ -276,13 +293,13 @@ impl<T: Item> SumTree<T> {
         }
     }
 
-    pub fn from_par_iter<I, Iter>(iter: I, cx: &<T::Summary as Summary>::Context) -> Self
+    pub fn from_par_iter<I, Iter>(iter: I, cx: <T::Summary as Summary>::Context<'_>) -> Self
     where
         I: IntoParallelIterator<Iter = Iter>,
         Iter: IndexedParallelIterator<Item = T>,
         T: Send + Sync,
         T::Summary: Send + Sync,
-        <T::Summary as Summary>::Context: Sync,
+        for<'a> <T::Summary as Summary>::Context<'a>: Sync,
     {
         let mut nodes = iter
             .into_par_iter()
@@ -339,7 +356,7 @@ impl<T: Item> SumTree<T> {
     }
 
     #[allow(unused)]
-    pub fn items(&self, cx: &<T::Summary as Summary>::Context) -> Vec<T> {
+    pub fn items<'a>(&'a self, cx: <T::Summary as Summary>::Context<'a>) -> Vec<T> {
         let mut items = Vec::new();
         let mut cursor = self.cursor::<()>(cx);
         cursor.next();
@@ -354,7 +371,10 @@ impl<T: Item> SumTree<T> {
         Iter::new(self)
     }
 
-    pub fn cursor<'a, S>(&'a self, cx: &'a <T::Summary as Summary>::Context) -> Cursor<'a, T, S>
+    pub fn cursor<'a, 'b, S>(
+        &'a self,
+        cx: <T::Summary as Summary>::Context<'b>,
+    ) -> Cursor<'a, 'b, T, S>
     where
         S: Dimension<'a, T::Summary>,
     {
@@ -363,11 +383,11 @@ impl<T: Item> SumTree<T> {
 
     /// 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>(
+    pub fn filter<'a, 'b, F, U>(
         &'a self,
-        cx: &'a <T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'b>,
         filter_node: F,
-    ) -> FilterCursor<'a, F, T, U>
+    ) -> FilterCursor<'a, 'b, F, T, U>
     where
         F: FnMut(&T::Summary) -> bool,
         U: Dimension<'a, T::Summary>,
@@ -384,14 +404,18 @@ impl<T: Item> SumTree<T> {
         self.rightmost_leaf().0.items().last()
     }
 
-    pub fn update_last(&mut self, f: impl FnOnce(&mut T), cx: &<T::Summary as Summary>::Context) {
+    pub fn update_last(
+        &mut self,
+        f: impl FnOnce(&mut T),
+        cx: <T::Summary as Summary>::Context<'_>,
+    ) {
         self.update_last_recursive(f, cx);
     }
 
     fn update_last_recursive(
         &mut self,
         f: impl FnOnce(&mut T),
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'_>,
     ) -> Option<T::Summary> {
         match Arc::make_mut(&mut self.0) {
             Node::Internal {
@@ -426,7 +450,7 @@ impl<T: Item> SumTree<T> {
 
     pub fn extent<'a, D: Dimension<'a, T::Summary>>(
         &'a self,
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'_>,
     ) -> D {
         let mut extent = D::zero(cx);
         match self.0.as_ref() {
@@ -451,25 +475,25 @@ impl<T: Item> SumTree<T> {
         }
     }
 
-    pub fn extend<I>(&mut self, iter: I, cx: &<T::Summary as Summary>::Context)
+    pub fn extend<I>(&mut self, iter: I, cx: <T::Summary as Summary>::Context<'_>)
     where
         I: IntoIterator<Item = T>,
     {
         self.append(Self::from_iter(iter, cx), cx);
     }
 
-    pub fn par_extend<I, Iter>(&mut self, iter: I, cx: &<T::Summary as Summary>::Context)
+    pub fn par_extend<I, Iter>(&mut self, iter: I, cx: <T::Summary as Summary>::Context<'_>)
     where
         I: IntoParallelIterator<Iter = Iter>,
         Iter: IndexedParallelIterator<Item = T>,
         T: Send + Sync,
         T::Summary: Send + Sync,
-        <T::Summary as Summary>::Context: Sync,
+        for<'a> <T::Summary as Summary>::Context<'a>: Sync,
     {
         self.append(Self::from_par_iter(iter, cx), cx);
     }
 
-    pub fn push(&mut self, item: T, cx: &<T::Summary as Summary>::Context) {
+    pub fn push(&mut self, item: T, cx: <T::Summary as Summary>::Context<'_>) {
         let summary = item.summary(cx);
         self.append(
             SumTree(Arc::new(Node::Leaf {
@@ -481,7 +505,7 @@ impl<T: Item> SumTree<T> {
         );
     }
 
-    pub fn append(&mut self, other: Self, cx: &<T::Summary as Summary>::Context) {
+    pub fn append(&mut self, other: Self, cx: <T::Summary as Summary>::Context<'_>) {
         if self.is_empty() {
             *self = other;
         } else if !other.0.is_leaf() || !other.0.items().is_empty() {
@@ -498,7 +522,7 @@ impl<T: Item> SumTree<T> {
     fn push_tree_recursive(
         &mut self,
         other: SumTree<T>,
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'_>,
     ) -> Option<SumTree<T>> {
         match Arc::make_mut(&mut self.0) {
             Node::Internal {
@@ -618,7 +642,7 @@ impl<T: Item> SumTree<T> {
     fn from_child_trees(
         left: SumTree<T>,
         right: SumTree<T>,
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'_>,
     ) -> Self {
         let height = left.0.height() + 1;
         let mut child_summaries = ArrayVec::new();
@@ -663,13 +687,13 @@ impl<T: Item + PartialEq> PartialEq for SumTree<T> {
 impl<T: Item + Eq> Eq for SumTree<T> {}
 
 impl<T: KeyedItem> SumTree<T> {
-    pub fn insert_or_replace(
-        &mut self,
+    pub fn insert_or_replace<'a, 'b>(
+        &'a mut self,
         item: T,
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'b>,
     ) -> Option<T> {
         let mut replaced = None;
-        *self = {
+        {
             let mut cursor = self.cursor::<T::Key>(cx);
             let mut new_tree = cursor.slice(&item.key(), Bias::Left);
             if let Some(cursor_item) = cursor.item()
@@ -680,12 +704,13 @@ impl<T: KeyedItem> SumTree<T> {
             }
             new_tree.push(item, cx);
             new_tree.append(cursor.suffix(), cx);
-            new_tree
+            drop(cursor);
+            *self = new_tree
         };
         replaced
     }
 
-    pub fn remove(&mut self, key: &T::Key, cx: &<T::Summary as Summary>::Context) -> Option<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>(cx);
@@ -705,7 +730,7 @@ impl<T: KeyedItem> SumTree<T> {
     pub fn edit(
         &mut self,
         mut edits: Vec<Edit<T>>,
-        cx: &<T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'_>,
     ) -> Vec<T> {
         if edits.is_empty() {
             return Vec::new();
@@ -760,7 +785,7 @@ impl<T: KeyedItem> SumTree<T> {
     pub fn get<'a>(
         &'a self,
         key: &T::Key,
-        cx: &'a <T::Summary as Summary>::Context,
+        cx: <T::Summary as Summary>::Context<'a>,
     ) -> Option<&'a T> {
         let mut cursor = self.cursor::<T::Key>(cx);
         if cursor.seek(key, Bias::Left) {
@@ -774,10 +799,10 @@ impl<T: KeyedItem> SumTree<T> {
 impl<T, S> Default for SumTree<T>
 where
     T: Item<Summary = S>,
-    S: Summary<Context = ()>,
+    S: for<'a> Summary<Context<'a> = ()>,
 {
     fn default() -> Self {
-        Self::new(&())
+        Self::new(())
     }
 }
 
@@ -894,7 +919,7 @@ impl<T: KeyedItem> Edit<T> {
     }
 }
 
-fn sum<'a, T, I>(iter: I, cx: &T::Context) -> T
+fn sum<'a, T, I>(iter: I, cx: T::Context<'_>) -> T
 where
     T: 'a + Summary,
     I: Iterator<Item = &'a T>,
@@ -920,16 +945,13 @@ mod tests {
     #[test]
     fn test_extend_and_push_tree() {
         let mut tree1 = SumTree::default();
-        tree1.extend(0..20, &());
+        tree1.extend(0..20, ());
 
         let mut tree2 = SumTree::default();
-        tree2.extend(50..100, &());
+        tree2.extend(50..100, ());
 
-        tree1.append(tree2, &());
-        assert_eq!(
-            tree1.items(&()),
-            (0..20).chain(50..100).collect::<Vec<u8>>()
-        );
+        tree1.append(tree2, ());
+        assert_eq!(tree1.items(()), (0..20).chain(50..100).collect::<Vec<u8>>());
     }
 
     #[test]
@@ -953,53 +975,53 @@ mod tests {
             let mut tree = SumTree::<u8>::default();
             let count = rng.random_range(0..10);
             if rng.random() {
-                tree.extend(rng.sample_iter(StandardUniform).take(count), &());
+                tree.extend(rng.sample_iter(StandardUniform).take(count), ());
             } else {
                 let items = rng
                     .sample_iter(StandardUniform)
                     .take(count)
                     .collect::<Vec<_>>();
-                tree.par_extend(items, &());
+                tree.par_extend(items, ());
             }
 
             for _ in 0..num_operations {
-                let splice_end = rng.random_range(0..tree.extent::<Count>(&()).0 + 1);
+                let splice_end = rng.random_range(0..tree.extent::<Count>(()).0 + 1);
                 let splice_start = rng.random_range(0..splice_end + 1);
                 let count = rng.random_range(0..10);
-                let tree_end = tree.extent::<Count>(&());
+                let tree_end = tree.extent::<Count>(());
                 let new_items = rng
                     .sample_iter(StandardUniform)
                     .take(count)
                     .collect::<Vec<u8>>();
 
-                let mut reference_items = tree.items(&());
+                let mut reference_items = tree.items(());
                 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.random() {
-                        new_tree.extend(new_items, &());
+                        new_tree.extend(new_items, ());
                     } else {
-                        new_tree.par_extend(new_items, &());
+                        new_tree.par_extend(new_items, ());
                     }
                     cursor.seek(&Count(splice_end), Bias::Right);
-                    new_tree.append(cursor.slice(&tree_end, Bias::Right), &());
+                    new_tree.append(cursor.slice(&tree_end, Bias::Right), ());
                     new_tree
                 };
 
-                assert_eq!(tree.items(&()), reference_items);
+                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(&()));
+                log::info!("tree items: {:?}", tree.items(()));
 
                 let mut filter_cursor =
-                    tree.filter::<_, Count>(&(), |summary| summary.contains_even);
+                    tree.filter::<_, Count>((), |summary| summary.contains_even);
                 let expected_filtered_items = tree
-                    .items(&())
+                    .items(())
                     .into_iter()
                     .enumerate()
                     .filter(|(_, item)| (item & 1) == 0)
@@ -1038,7 +1060,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.random_range(0..=reference_items.len());
                 cursor.seek(&Count(start_pos), Bias::Right);
                 let mut pos = rng.random_range(start_pos..=reference_items.len());
@@ -1084,7 +1106,7 @@ mod tests {
             }
 
             for _ in 0..10 {
-                let end = rng.random_range(0..tree.extent::<Count>(&()).0 + 1);
+                let end = rng.random_range(0..tree.extent::<Count>(()).0 + 1);
                 let start = rng.random_range(0..end + 1);
                 let start_bias = if rng.random() {
                     Bias::Left
@@ -1097,7 +1119,7 @@ mod tests {
                     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);
 
@@ -1113,9 +1135,9 @@ mod tests {
     fn test_cursor() {
         // Empty tree
         let tree = SumTree::<u8>::default();
-        let mut cursor = tree.cursor::<IntegersSummary>(&());
+        let mut cursor = tree.cursor::<IntegersSummary>(());
         assert_eq!(
-            cursor.slice(&Count(0), Bias::Right).items(&()),
+            cursor.slice(&Count(0), Bias::Right).items(()),
             Vec::<u8>::new()
         );
         assert_eq!(cursor.item(), None);
@@ -1135,10 +1157,10 @@ mod tests {
 
         // Single-element tree
         let mut tree = SumTree::<u8>::default();
-        tree.extend(vec![1], &());
-        let mut cursor = tree.cursor::<IntegersSummary>(&());
+        tree.extend(vec![1], ());
+        let mut cursor = tree.cursor::<IntegersSummary>(());
         assert_eq!(
-            cursor.slice(&Count(0), Bias::Right).items(&()),
+            cursor.slice(&Count(0), Bias::Right).items(()),
             Vec::<u8>::new()
         );
         assert_eq!(cursor.item(), Some(&1));
@@ -1158,8 +1180,8 @@ mod tests {
         assert_eq!(cursor.next_item(), None);
         assert_eq!(cursor.start().sum, 0);
 
-        let mut cursor = tree.cursor::<IntegersSummary>(&());
-        assert_eq!(cursor.slice(&Count(1), Bias::Right).items(&()), [1]);
+        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));
         assert_eq!(cursor.next_item(), None);
@@ -1168,8 +1190,8 @@ mod tests {
         cursor.seek(&Count(0), Bias::Right);
         assert_eq!(
             cursor
-                .slice(&tree.extent::<Count>(&()), Bias::Right)
-                .items(&()),
+                .slice(&tree.extent::<Count>(()), Bias::Right)
+                .items(()),
             [1]
         );
         assert_eq!(cursor.item(), None);
@@ -1179,10 +1201,10 @@ mod tests {
 
         // Multiple-element tree
         let mut tree = SumTree::default();
-        tree.extend(vec![1, 2, 3, 4, 5, 6], &());
-        let mut cursor = tree.cursor::<IntegersSummary>(&());
+        tree.extend(vec![1, 2, 3, 4, 5, 6], ());
+        let mut cursor = tree.cursor::<IntegersSummary>(());
 
-        assert_eq!(cursor.slice(&Count(2), Bias::Right).items(&()), [1, 2]);
+        assert_eq!(cursor.slice(&Count(2), Bias::Right).items(()), [1, 2]);
         assert_eq!(cursor.item(), Some(&3));
         assert_eq!(cursor.prev_item(), Some(&2));
         assert_eq!(cursor.next_item(), Some(&4));
@@ -1261,12 +1283,12 @@ 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)
-                .items(&()),
-            tree.items(&())
+                .slice(&tree.extent::<Count>(()), Bias::Right)
+                .items(()),
+            tree.items(())
         );
         assert_eq!(cursor.item(), None);
         assert_eq!(cursor.prev_item(), Some(&6));
@@ -1276,8 +1298,8 @@ mod tests {
         cursor.seek(&Count(3), Bias::Right);
         assert_eq!(
             cursor
-                .slice(&tree.extent::<Count>(&()), Bias::Right)
-                .items(&()),
+                .slice(&tree.extent::<Count>(()), Bias::Right)
+                .items(()),
             [4, 5, 6]
         );
         assert_eq!(cursor.item(), None);
@@ -1293,36 +1315,36 @@ mod tests {
 
         // Slicing without resetting starts from where the cursor is parked at.
         cursor.seek(&Count(1), Bias::Right);
-        assert_eq!(cursor.slice(&Count(3), Bias::Right).items(&()), vec![2, 3]);
-        assert_eq!(cursor.slice(&Count(6), Bias::Left).items(&()), vec![4, 5]);
-        assert_eq!(cursor.slice(&Count(6), Bias::Right).items(&()), vec![6]);
+        assert_eq!(cursor.slice(&Count(3), Bias::Right).items(()), vec![2, 3]);
+        assert_eq!(cursor.slice(&Count(6), Bias::Left).items(()), vec![4, 5]);
+        assert_eq!(cursor.slice(&Count(6), Bias::Right).items(()), vec![6]);
     }
 
     #[test]
     fn test_edit() {
         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]);
+        let removed = tree.edit(vec![Edit::Insert(1), Edit::Insert(2), Edit::Insert(0)], ());
+        assert_eq!(tree.items(()), vec![0, 1, 2]);
         assert_eq!(removed, Vec::<u8>::new());
-        assert_eq!(tree.get(&0, &()), Some(&0));
-        assert_eq!(tree.get(&1, &()), Some(&1));
-        assert_eq!(tree.get(&2, &()), Some(&2));
-        assert_eq!(tree.get(&4, &()), None);
+        assert_eq!(tree.get(&0, ()), Some(&0));
+        assert_eq!(tree.get(&1, ()), Some(&1));
+        assert_eq!(tree.get(&2, ()), Some(&2));
+        assert_eq!(tree.get(&4, ()), None);
 
-        let removed = tree.edit(vec![Edit::Insert(2), Edit::Insert(4), Edit::Remove(0)], &());
-        assert_eq!(tree.items(&()), vec![1, 2, 4]);
+        let removed = tree.edit(vec![Edit::Insert(2), Edit::Insert(4), Edit::Remove(0)], ());
+        assert_eq!(tree.items(()), vec![1, 2, 4]);
         assert_eq!(removed, vec![0, 2]);
-        assert_eq!(tree.get(&0, &()), None);
-        assert_eq!(tree.get(&1, &()), Some(&1));
-        assert_eq!(tree.get(&2, &()), Some(&2));
-        assert_eq!(tree.get(&4, &()), Some(&4));
+        assert_eq!(tree.get(&0, ()), None);
+        assert_eq!(tree.get(&1, ()), Some(&1));
+        assert_eq!(tree.get(&2, ()), Some(&2));
+        assert_eq!(tree.get(&4, ()), Some(&4));
     }
 
     #[test]
     fn test_from_iter() {
         assert_eq!(
-            SumTree::from_iter(0..100, &()).items(&()),
+            SumTree::from_iter(0..100, ()).items(()),
             (0..100).collect::<Vec<_>>()
         );
 
@@ -1333,7 +1355,7 @@ mod tests {
             ix = (ix + 1) % 2;
             if ix == 1 { Some(1) } else { None }
         });
-        assert_eq!(SumTree::from_iter(iterator, &()).items(&()), vec![1]);
+        assert_eq!(SumTree::from_iter(iterator, ()).items(()), vec![1]);
     }
 
     #[derive(Clone, Default, Debug)]
@@ -1353,7 +1375,7 @@ mod tests {
     impl Item for u8 {
         type Summary = IntegersSummary;
 
-        fn summary(&self, _cx: &()) -> Self::Summary {
+        fn summary(&self, _cx: ()) -> Self::Summary {
             IntegersSummary {
                 count: 1,
                 sum: *self as usize,
@@ -1371,14 +1393,12 @@ mod tests {
         }
     }
 
-    impl Summary for IntegersSummary {
-        type Context = ();
-
-        fn zero(_cx: &()) -> Self {
+    impl ContextLessSummary for IntegersSummary {
+        fn zero() -> Self {
             Default::default()
         }
 
-        fn add_summary(&mut self, other: &Self, _: &()) {
+        fn add_summary(&mut self, other: &Self) {
             self.count += other.count;
             self.sum += other.sum;
             self.contains_even |= other.contains_even;
@@ -1387,37 +1407,37 @@ mod tests {
     }
 
     impl Dimension<'_, IntegersSummary> for u8 {
-        fn zero(_cx: &()) -> Self {
+        fn zero(_cx: ()) -> Self {
             Default::default()
         }
 
-        fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
+        fn add_summary(&mut self, summary: &IntegersSummary, _: ()) {
             *self = summary.max;
         }
     }
 
     impl Dimension<'_, IntegersSummary> for Count {
-        fn zero(_cx: &()) -> Self {
+        fn zero(_cx: ()) -> Self {
             Default::default()
         }
 
-        fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
+        fn add_summary(&mut self, summary: &IntegersSummary, _: ()) {
             self.0 += summary.count;
         }
     }
 
     impl SeekTarget<'_, IntegersSummary, IntegersSummary> for Count {
-        fn cmp(&self, cursor_location: &IntegersSummary, _: &()) -> Ordering {
+        fn cmp(&self, cursor_location: &IntegersSummary, _: ()) -> Ordering {
             self.0.cmp(&cursor_location.count)
         }
     }
 
     impl Dimension<'_, IntegersSummary> for Sum {
-        fn zero(_cx: &()) -> Self {
+        fn zero(_cx: ()) -> Self {
             Default::default()
         }
 
-        fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
+        fn add_summary(&mut self, summary: &IntegersSummary, _: ()) {
             self.0 += summary.sum;
         }
     }

crates/sum_tree/src/tree_map.rs 🔗

@@ -1,6 +1,6 @@
 use std::{cmp::Ordering, fmt::Debug};
 
-use crate::{Bias, Dimension, Edit, Item, KeyedItem, SeekTarget, SumTree, Summary};
+use crate::{Bias, ContextLessSummary, Dimension, Edit, Item, KeyedItem, SeekTarget, SumTree};
 
 /// A cheaply-cloneable ordered map based on a [SumTree](crate::SumTree).
 #[derive(Clone, PartialEq, Eq)]
@@ -44,7 +44,7 @@ impl<K: Clone + Ord, V: Clone> TreeMap<K, V> {
             entries
                 .into_iter()
                 .map(|(key, value)| MapEntry { key, value }),
-            &(),
+            (),
         );
         Self(tree)
     }
@@ -54,7 +54,7 @@ impl<K: Clone + Ord, V: Clone> TreeMap<K, V> {
     }
 
     pub fn get(&self, key: &K) -> Option<&V> {
-        let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>(&());
+        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() {
@@ -68,7 +68,7 @@ impl<K: Clone + Ord, V: Clone> TreeMap<K, V> {
     }
 
     pub fn insert(&mut self, key: K, value: V) {
-        self.0.insert_or_replace(MapEntry { key, value }, &());
+        self.0.insert_or_replace(MapEntry { key, value }, ());
     }
 
     pub fn extend(&mut self, iter: impl IntoIterator<Item = (K, V)>) {
@@ -76,7 +76,7 @@ impl<K: Clone + Ord, V: Clone> TreeMap<K, V> {
             .into_iter()
             .map(|(key, value)| Edit::Insert(MapEntry { key, value }))
             .collect();
-        self.0.edit(edits, &());
+        self.0.edit(edits, ());
     }
 
     pub fn clear(&mut self) {
@@ -85,14 +85,14 @@ impl<K: Clone + Ord, V: Clone> 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 {
+        if key.cmp(&cursor.end(), ()) == Ordering::Equal {
             removed = Some(cursor.item().unwrap().value.clone());
             cursor.next();
         }
-        new_tree.append(cursor.suffix(), &());
+        new_tree.append(cursor.suffix(), ());
         drop(cursor);
         self.0 = new_tree;
         removed
@@ -101,17 +101,17 @@ impl<K: Clone + Ord, V: Clone> 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(), &());
+        new_tree.append(cursor.suffix(), ());
         drop(cursor);
         self.0 = new_tree;
     }
 
     /// 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();
@@ -119,7 +119,7 @@ impl<K: Clone + Ord, V: Clone> TreeMap<K, V> {
     }
 
     pub fn iter_from<'a>(&'a self, from: &K) -> impl Iterator<Item = (&'a K, &'a V)> + 'a {
-        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);
 
@@ -130,17 +130,17 @@ impl<K: Clone + Ord, V: Clone> 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;
-        if key.cmp(&cursor.end(), &()) == Ordering::Equal {
+        if key.cmp(&cursor.end(), ()) == Ordering::Equal {
             let mut updated = cursor.item().unwrap().clone();
             result = Some(f(&mut updated.value));
-            new_tree.push(updated, &());
+            new_tree.push(updated, ());
             cursor.next();
         }
-        new_tree.append(cursor.suffix(), &());
+        new_tree.append(cursor.suffix(), ());
         drop(cursor);
         self.0 = new_tree;
         result
@@ -149,11 +149,11 @@ impl<K: Clone + Ord, V: Clone> 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) {
-                new_map.push(item.clone(), &());
+                new_map.push(item.clone(), ());
             }
             cursor.next();
         }
@@ -189,7 +189,7 @@ impl<K: Clone + Ord, V: Clone> TreeMap<K, V> {
             })
             .collect();
 
-        self.0.edit(edits, &());
+        self.0.edit(edits, ());
     }
 }
 
@@ -209,7 +209,7 @@ struct MapSeekTargetAdaptor<'a, T>(&'a T);
 impl<'a, K: Clone + Ord, T: MapSeekTarget<K>> SeekTarget<'a, MapKey<K>, MapKeyRef<'a, K>>
     for MapSeekTargetAdaptor<'_, T>
 {
-    fn cmp(&self, cursor_location: &MapKeyRef<K>, _: &()) -> Ordering {
+    fn cmp(&self, cursor_location: &MapKeyRef<K>, _: ()) -> Ordering {
         if let Some(key) = &cursor_location.0 {
             MapSeekTarget::cmp_cursor(self.0, key)
         } else {
@@ -245,7 +245,7 @@ where
 {
     type Summary = MapKey<K>;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         self.key()
     }
 }
@@ -262,17 +262,15 @@ where
     }
 }
 
-impl<K> Summary for MapKey<K>
+impl<K> ContextLessSummary for MapKey<K>
 where
     K: Clone,
 {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &()) {
+    fn add_summary(&mut self, summary: &Self) {
         *self = summary.clone()
     }
 }
@@ -281,11 +279,11 @@ impl<'a, K> Dimension<'a, MapKey<K>> for MapKeyRef<'a, K>
 where
     K: Clone + Ord,
 {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a MapKey<K>, _: &()) {
+    fn add_summary(&mut self, summary: &'a MapKey<K>, _: ()) {
         self.0 = summary.0.as_ref();
     }
 }
@@ -294,7 +292,7 @@ impl<'a, K> SeekTarget<'a, MapKey<K>, MapKeyRef<'a, K>> for MapKeyRef<'_, K>
 where
     K: Clone + Ord,
 {
-    fn cmp(&self, cursor_location: &MapKeyRef<K>, _: &()) -> Ordering {
+    fn cmp(&self, cursor_location: &MapKeyRef<K>, _: ()) -> Ordering {
         Ord::cmp(&self.0, &cursor_location.0)
     }
 }

crates/text/src/locator.rs 🔗

@@ -67,7 +67,7 @@ impl Default for Locator {
 impl sum_tree::Item for Locator {
     type Summary = Locator;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         self.clone()
     }
 }
@@ -80,14 +80,12 @@ impl sum_tree::KeyedItem for Locator {
     }
 }
 
-impl sum_tree::Summary for Locator {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for Locator {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &()) {
+    fn add_summary(&mut self, summary: &Self) {
         self.assign(summary);
     }
 }

crates/text/src/operation_queue.rs 🔗

@@ -1,5 +1,5 @@
 use std::{fmt::Debug, ops::Add};
-use sum_tree::{Dimension, Edit, Item, KeyedItem, SumTree, Summary};
+use sum_tree::{ContextLessSummary, Dimension, Edit, Item, KeyedItem, SumTree};
 
 pub trait Operation: Clone + Debug {
     fn lamport_timestamp(&self) -> clock::Lamport;
@@ -52,7 +52,7 @@ impl<T: Operation> OperationQueue<T> {
             ops.into_iter()
                 .map(|op| Edit::Insert(OperationItem(op)))
                 .collect(),
-            &(),
+            (),
         );
     }
 
@@ -67,14 +67,12 @@ impl<T: Operation> OperationQueue<T> {
     }
 }
 
-impl Summary for OperationSummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl ContextLessSummary for OperationSummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, other: &Self, _: &()) {
+    fn add_summary(&mut self, other: &Self) {
         assert!(self.key < other.key);
         self.key = other.key;
         self.len += other.len;
@@ -94,11 +92,11 @@ impl Add<&Self> for OperationSummary {
 }
 
 impl Dimension<'_, OperationSummary> for OperationKey {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &OperationSummary, _: &()) {
+    fn add_summary(&mut self, summary: &OperationSummary, _: ()) {
         assert!(*self <= summary.key);
         *self = summary.key;
     }
@@ -107,7 +105,7 @@ impl Dimension<'_, OperationSummary> for OperationKey {
 impl<T: Operation> Item for OperationItem<T> {
     type Summary = OperationSummary;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         OperationSummary {
             key: OperationKey::new(self.0.lamport_timestamp()),
             len: 1,

crates/text/src/text.rs 🔗

@@ -482,7 +482,7 @@ impl History {
 struct Edits<'a, D: TextDimension, F: FnMut(&FragmentSummary) -> bool> {
     visible_cursor: rope::Cursor<'a>,
     deleted_cursor: rope::Cursor<'a>,
-    fragments_cursor: Option<FilterCursor<'a, F, Fragment, FragmentTextSummary>>,
+    fragments_cursor: Option<FilterCursor<'a, 'static, F, Fragment, FragmentTextSummary>>,
     undos: &'a UndoMap,
     since: &'a clock::Global,
     old_end: D,
@@ -747,7 +747,7 @@ impl Buffer {
                 deletions: Default::default(),
                 max_undos: Default::default(),
             };
-            insertions.push(InsertionFragment::new(&fragment), &());
+            insertions.push(InsertionFragment::new(&fragment), ());
             fragments.push(fragment, &None);
         }
 
@@ -992,7 +992,7 @@ impl Buffer {
         drop(old_fragments);
 
         self.snapshot.fragments = new_fragments;
-        self.snapshot.insertions.edit(new_insertions, &());
+        self.snapshot.insertions.edit(new_insertions, ());
         self.snapshot.visible_text = visible_text;
         self.snapshot.deleted_text = deleted_text;
         self.subscriptions.publish_mut(&edits_patch);
@@ -1240,7 +1240,7 @@ impl Buffer {
         self.snapshot.fragments = new_fragments;
         self.snapshot.visible_text = visible_text;
         self.snapshot.deleted_text = deleted_text;
-        self.snapshot.insertions.edit(new_insertions, &());
+        self.snapshot.insertions.edit(new_insertions, ());
         self.snapshot.insertion_slices.extend(insertion_slices);
         self.subscriptions.publish_mut(&edits_patch)
     }
@@ -1269,7 +1269,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
@@ -1597,7 +1597,7 @@ impl Buffer {
             });
 
         // convert to the desired text dimension.
-        let mut position = D::zero(&());
+        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));
@@ -1782,7 +1782,7 @@ impl Buffer {
                         timestamp: fragment.timestamp,
                         split_offset: fragment.insertion_offset,
                     },
-                    &(),
+                    (),
                 )
                 .unwrap();
             assert_eq!(
@@ -1793,7 +1793,7 @@ impl Buffer {
         }
 
         let mut cursor = self.snapshot.fragments.cursor::<Option<&Locator>>(&None);
-        for insertion_fragment in self.snapshot.insertions.cursor::<()>(&()) {
+        for insertion_fragment in self.snapshot.insertions.cursor::<()>(()) {
             cursor.seek(&Some(&insertion_fragment.fragment_id), Bias::Left);
             let fragment = cursor.item().unwrap();
             assert_eq!(insertion_fragment.fragment_id, fragment.id);
@@ -2237,16 +2237,16 @@ impl BufferSnapshot {
         A: 'a + IntoIterator<Item = (&'a Anchor, T)>,
     {
         let anchors = anchors.into_iter();
-        let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>(&());
+        let mut insertion_cursor = self.insertions.cursor::<InsertionFragmentKey>(());
         let mut fragment_cursor = self
             .fragments
             .cursor::<Dimensions<Option<&Locator>, usize>>(&None);
         let mut text_cursor = self.visible_text.cursor(0);
-        let mut position = D::zero(&());
+        let mut position = D::zero(());
 
         anchors.map(move |(anchor, payload)| {
             if *anchor == Anchor::MIN {
-                return (D::zero(&()), payload);
+                return (D::zero(()), payload);
             } else if *anchor == Anchor::MAX {
                 return (D::from_text_summary(&self.visible_text.summary()), payload);
             }
@@ -2301,7 +2301,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);
@@ -2358,7 +2358,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);
@@ -2519,8 +2519,8 @@ impl BufferSnapshot {
             fragments_cursor,
             undos: &self.undo_map,
             since,
-            old_end: D::zero(&()),
-            new_end: D::zero(&()),
+            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,
         }
@@ -2851,13 +2851,13 @@ impl sum_tree::Item for Fragment {
 }
 
 impl sum_tree::Summary for FragmentSummary {
-    type Context = Option<clock::Global>;
+    type Context<'a> = &'a Option<clock::Global>;
 
-    fn zero(_cx: &Self::Context) -> Self {
+    fn zero(_cx: Self::Context<'_>) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, other: &Self, _: &Self::Context) {
+    fn add_summary(&mut self, other: &Self, _: Self::Context<'_>) {
         self.max_id.assign(&other.max_id);
         self.text.visible += &other.text.visible;
         self.text.deleted += &other.text.deleted;
@@ -2884,7 +2884,7 @@ impl Default for FragmentSummary {
 impl sum_tree::Item for InsertionFragment {
     type Summary = InsertionFragmentKey;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         InsertionFragmentKey {
             timestamp: self.timestamp,
             split_offset: self.split_offset,
@@ -2896,7 +2896,7 @@ impl sum_tree::KeyedItem for InsertionFragment {
     type Key = InsertionFragmentKey;
 
     fn key(&self) -> Self::Key {
-        sum_tree::Item::summary(self, &())
+        sum_tree::Item::summary(self, ())
     }
 }
 
@@ -2914,14 +2914,12 @@ impl InsertionFragment {
     }
 }
 
-impl sum_tree::Summary for InsertionFragmentKey {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for InsertionFragmentKey {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &()) {
+    fn add_summary(&mut self, summary: &Self) {
         *self = *summary;
     }
 }

crates/text/src/undo_map.rs 🔗

@@ -11,7 +11,7 @@ struct UndoMapEntry {
 impl sum_tree::Item for UndoMapEntry {
     type Summary = UndoMapKey;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         self.key
     }
 }
@@ -30,14 +30,12 @@ struct UndoMapKey {
     undo_id: clock::Lamport,
 }
 
-impl sum_tree::Summary for UndoMapKey {
-    type Context = ();
-
-    fn zero(_cx: &Self::Context) -> Self {
+impl sum_tree::ContextLessSummary for UndoMapKey {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &Self::Context) {
+    fn add_summary(&mut self, summary: &Self) {
         *self = cmp::max(*self, *summary);
     }
 }
@@ -60,14 +58,14 @@ impl UndoMap {
                 })
             })
             .collect::<Vec<_>>();
-        self.0.edit(edits, &());
+        self.0.edit(edits, ());
     }
 
     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,
@@ -91,7 +89,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 🔗

@@ -391,12 +391,12 @@ struct LocalRepositoryEntry {
 }
 
 impl sum_tree::Item for LocalRepositoryEntry {
-    type Summary = PathSummary<&'static ()>;
+    type Summary = PathSummary<sum_tree::NoSummary>;
 
-    fn summary(&self, _: &<Self::Summary as Summary>::Context) -> Self::Summary {
+    fn summary(&self, _: <Self::Summary as Summary>::Context<'_>) -> Self::Summary {
         PathSummary {
             max_path: self.work_directory.path_key().0,
-            item_summary: &(),
+            item_summary: sum_tree::NoSummary,
         }
     }
 }
@@ -2429,7 +2429,7 @@ impl Snapshot {
     }
 
     pub fn contains_entry(&self, entry_id: ProjectEntryId) -> bool {
-        self.entries_by_id.get(&entry_id, &()).is_some()
+        self.entries_by_id.get(&entry_id, ()).is_some()
     }
 
     fn insert_entry(
@@ -2445,30 +2445,30 @@ impl Snapshot {
                 is_ignored: entry.is_ignored,
                 scan_id: 0,
             },
-            &(),
+            (),
         );
         if let Some(old_entry) = old_entry {
-            self.entries_by_path.remove(&PathKey(old_entry.path), &());
+            self.entries_by_path.remove(&PathKey(old_entry.path), ());
         }
-        self.entries_by_path.insert_or_replace(entry.clone(), &());
+        self.entries_by_path.insert_or_replace(entry.clone(), ());
         Ok(entry)
     }
 
     fn delete_entry(&mut self, entry_id: ProjectEntryId) -> Option<Arc<Path>> {
-        let removed_entry = self.entries_by_id.remove(&entry_id, &())?;
+        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() {
                 if entry.path.starts_with(&removed_entry.path) {
-                    self.entries_by_id.remove(&entry.id, &());
+                    self.entries_by_id.remove(&entry.id, ());
                     cursor.next();
                 } else {
                     break;
                 }
             }
-            new_entries_by_path.append(cursor.suffix(), &());
+            new_entries_by_path.append(cursor.suffix(), ());
             new_entries_by_path
         };
 
@@ -2511,10 +2511,10 @@ impl Snapshot {
 
         for entry in update.updated_entries {
             let entry = Entry::from((&self.root_char_bag, always_included_paths, entry));
-            if let Some(PathEntry { path, .. }) = self.entries_by_id.get(&entry.id, &()) {
+            if let Some(PathEntry { path, .. }) = self.entries_by_id.get(&entry.id, ()) {
                 entries_by_path_edits.push(Edit::Remove(PathKey(path.clone())));
             }
-            if let Some(old_entry) = self.entries_by_path.get(&PathKey(entry.path.clone()), &())
+            if let Some(old_entry) = self.entries_by_path.get(&PathKey(entry.path.clone()), ())
                 && old_entry.id != entry.id
             {
                 entries_by_id_edits.push(Edit::Remove(old_entry.id));
@@ -2528,8 +2528,8 @@ impl Snapshot {
             entries_by_path_edits.push(Edit::Insert(entry));
         }
 
-        self.entries_by_path.edit(entries_by_path_edits, &());
-        self.entries_by_id.edit(entries_by_id_edits, &());
+        self.entries_by_path.edit(entries_by_path_edits, ());
+        self.entries_by_id.edit(entries_by_id_edits, ());
 
         self.scan_id = update.scan_id as usize;
         if update.is_last_update {
@@ -2570,7 +2570,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,
@@ -2614,7 +2614,7 @@ 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)
     }
@@ -2633,7 +2633,7 @@ impl Snapshot {
         parent_path: &'a Path,
         options: ChildEntriesOptions,
     ) -> 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 {
             snapshot: self,
@@ -2683,7 +2683,7 @@ impl Snapshot {
     }
 
     pub fn entry_for_id(&self, id: ProjectEntryId) -> Option<&Entry> {
-        let entry = self.entries_by_id.get(&id, &())?;
+        let entry = self.entries_by_id.get(&id, ())?;
         self.entry_for_path(&entry.path)
     }
 
@@ -2757,18 +2757,17 @@ impl LocalSnapshot {
         }
 
         if entry.kind == EntryKind::PendingDir
-            && let Some(existing_entry) =
-                self.entries_by_path.get(&PathKey(entry.path.clone()), &())
+            && let Some(existing_entry) = self.entries_by_path.get(&PathKey(entry.path.clone()), ())
         {
             entry.kind = existing_entry.kind;
         }
 
         let scan_id = self.scan_id;
-        let removed = self.entries_by_path.insert_or_replace(entry.clone(), &());
+        let removed = self.entries_by_path.insert_or_replace(entry.clone(), ());
         if let Some(removed) = removed
             && removed.id != entry.id
         {
-            self.entries_by_id.remove(&removed.id, &());
+            self.entries_by_id.remove(&removed.id, ());
         }
         self.entries_by_id.insert_or_replace(
             PathEntry {
@@ -2777,7 +2776,7 @@ impl LocalSnapshot {
                 is_ignored: entry.is_ignored,
                 scan_id,
             },
-            &(),
+            (),
         );
 
         entry
@@ -2838,7 +2837,7 @@ impl LocalSnapshot {
     #[cfg(test)]
     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))
     }
 
@@ -2848,11 +2847,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()
@@ -2862,7 +2861,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) || entry.is_always_included {
@@ -2890,7 +2889,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);
@@ -2918,7 +2917,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));
             }
@@ -3012,7 +3011,7 @@ impl BackgroundScannerState {
         let mut parent_entry = if let Some(parent_entry) = self
             .snapshot
             .entries_by_path
-            .get(&PathKey(parent_path.clone()), &())
+            .get(&PathKey(parent_path.clone()), ())
         {
             parent_entry.clone()
         } else {
@@ -3053,8 +3052,8 @@ impl BackgroundScannerState {
 
         self.snapshot
             .entries_by_path
-            .edit(entries_by_path_edits, &());
-        self.snapshot.entries_by_id.edit(entries_by_id_edits, &());
+            .edit(entries_by_path_edits, ());
+        self.snapshot.entries_by_id.edit(entries_by_id_edits, ());
 
         if let Err(ix) = self.changed_paths.binary_search(parent_path) {
             self.changed_paths.insert(ix, parent_path.clone());
@@ -3072,15 +3071,15 @@ impl BackgroundScannerState {
             let mut cursor = self
                 .snapshot
                 .entries_by_path
-                .cursor::<TraversalProgress>(&());
+                .cursor::<TraversalProgress>(());
             new_entries = cursor.slice(&TraversalTarget::path(path), Bias::Left);
             removed_entries = cursor.slice(&TraversalTarget::successor(path), Bias::Left);
-            new_entries.append(cursor.suffix(), &());
+            new_entries.append(cursor.suffix(), ());
         }
         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();
@@ -3113,10 +3112,9 @@ impl BackgroundScannerState {
             }
         }
 
-        self.snapshot.entries_by_id.edit(
-            removed_ids.iter().map(|&id| Edit::Remove(id)).collect(),
-            &(),
-        );
+        self.snapshot
+            .entries_by_id
+            .edit(removed_ids.iter().map(|&id| Edit::Remove(id)).collect(), ());
         self.snapshot
             .git_repositories
             .retain(|id, _| removed_ids.binary_search(id).is_err());
@@ -3560,23 +3558,23 @@ pub struct PathSummary<S> {
 }
 
 impl<S: Summary> Summary for PathSummary<S> {
-    type Context = S::Context;
+    type Context<'a> = S::Context<'a>;
 
-    fn zero(cx: &Self::Context) -> Self {
+    fn zero(cx: Self::Context<'_>) -> Self {
         Self {
             max_path: Path::new("").into(),
             item_summary: S::zero(cx),
         }
     }
 
-    fn add_summary(&mut self, rhs: &Self, cx: &Self::Context) {
+    fn add_summary(&mut self, rhs: &Self, cx: Self::Context<'_>) {
         self.max_path = rhs.max_path.clone();
         self.item_summary.add_summary(&rhs.item_summary, cx);
     }
 }
 
 impl<'a, S: Summary> sum_tree::Dimension<'a, PathSummary<S>> for PathProgress<'a> {
-    fn zero(_: &<PathSummary<S> as Summary>::Context) -> Self {
+    fn zero(_: <PathSummary<S> as Summary>::Context<'_>) -> Self {
         Self {
             max_path: Path::new(""),
         }
@@ -3585,18 +3583,18 @@ impl<'a, S: Summary> sum_tree::Dimension<'a, PathSummary<S>> for PathProgress<'a
     fn add_summary(
         &mut self,
         summary: &'a PathSummary<S>,
-        _: &<PathSummary<S> as Summary>::Context,
+        _: <PathSummary<S> as Summary>::Context<'_>,
     ) {
         self.max_path = summary.max_path.as_ref()
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, PathSummary<GitSummary>> for GitSummary {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a PathSummary<GitSummary>, _: &()) {
+    fn add_summary(&mut self, summary: &'a PathSummary<GitSummary>, _: ()) {
         *self += summary.item_summary
     }
 }
@@ -3608,28 +3606,28 @@ impl<'a>
     fn cmp(
         &self,
         cursor_location: &Dimensions<TraversalProgress<'a>, GitSummary>,
-        _: &(),
+        _: (),
     ) -> Ordering {
         self.cmp_path(cursor_location.0.max_path)
     }
 }
 
 impl<'a, S: Summary> sum_tree::Dimension<'a, PathSummary<S>> for PathKey {
-    fn zero(_: &S::Context) -> Self {
+    fn zero(_: S::Context<'_>) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a PathSummary<S>, _: &S::Context) {
+    fn add_summary(&mut self, summary: &'a PathSummary<S>, _: S::Context<'_>) {
         self.0 = summary.max_path.clone();
     }
 }
 
 impl<'a, S: Summary> sum_tree::Dimension<'a, PathSummary<S>> for TraversalProgress<'a> {
-    fn zero(_cx: &S::Context) -> Self {
+    fn zero(_cx: S::Context<'_>) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a PathSummary<S>, _: &S::Context) {
+    fn add_summary(&mut self, summary: &'a PathSummary<S>, _: S::Context<'_>) {
         self.max_path = summary.max_path.as_ref();
     }
 }
@@ -3697,7 +3695,7 @@ impl EntryKind {
 impl sum_tree::Item for Entry {
     type Summary = EntrySummary;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         let non_ignored_count = if (self.is_ignored || self.is_external) && !self.is_always_included
         {
             0
@@ -3753,14 +3751,12 @@ impl Default for EntrySummary {
     }
 }
 
-impl sum_tree::Summary for EntrySummary {
-    type Context = ();
-
-    fn zero(_cx: &()) -> Self {
+impl sum_tree::ContextLessSummary for EntrySummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, rhs: &Self, _: &()) {
+    fn add_summary(&mut self, rhs: &Self) {
         self.max_path = rhs.max_path.clone();
         self.count += rhs.count;
         self.non_ignored_count += rhs.non_ignored_count;
@@ -3780,7 +3776,7 @@ struct PathEntry {
 impl sum_tree::Item for PathEntry {
     type Summary = PathEntrySummary;
 
-    fn summary(&self, _cx: &()) -> Self::Summary {
+    fn summary(&self, _cx: ()) -> Self::Summary {
         PathEntrySummary { max_id: self.id }
     }
 }
@@ -3798,24 +3794,22 @@ struct PathEntrySummary {
     max_id: ProjectEntryId,
 }
 
-impl sum_tree::Summary for PathEntrySummary {
-    type Context = ();
-
-    fn zero(_cx: &Self::Context) -> Self {
+impl sum_tree::ContextLessSummary for PathEntrySummary {
+    fn zero() -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &Self, _: &Self::Context) {
+    fn add_summary(&mut self, summary: &Self) {
         self.max_id = summary.max_id;
     }
 }
 
 impl<'a> sum_tree::Dimension<'a, PathEntrySummary> for ProjectEntryId {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a PathEntrySummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a PathEntrySummary, _: ()) {
         *self = summary.max_id;
     }
 }
@@ -3830,11 +3824,11 @@ impl Default for PathKey {
 }
 
 impl<'a> sum_tree::Dimension<'a, EntrySummary> for PathKey {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a EntrySummary, _: ()) {
         self.0 = summary.max_path.clone();
     }
 }
@@ -4889,7 +4883,7 @@ impl BackgroundScanner {
             }
 
             if entry.is_ignored != was_ignored {
-                let mut path_entry = snapshot.entries_by_id.get(&entry.id, &()).unwrap().clone();
+                let mut path_entry = snapshot.entries_by_id.get(&entry.id, ()).unwrap().clone();
                 path_entry.scan_id = snapshot.scan_id;
                 path_entry.is_ignored = entry.is_ignored;
                 entries_by_id_edits.push(Edit::Insert(path_entry));
@@ -4909,8 +4903,8 @@ impl BackgroundScanner {
         state
             .snapshot
             .entries_by_path
-            .edit(entries_by_path_edits, &());
-        state.snapshot.entries_by_id.edit(entries_by_id_edits, &());
+            .edit(entries_by_path_edits, ());
+        state.snapshot.entries_by_id.edit(entries_by_id_edits, ());
     }
 
     fn update_git_repositories(&self, dot_git_paths: Vec<PathBuf>) -> Vec<Arc<Path>> {
@@ -5094,8 +5088,8 @@ fn build_diff(
     // 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();
@@ -5384,11 +5378,11 @@ impl TraversalProgress<'_> {
 }
 
 impl<'a> sum_tree::Dimension<'a, EntrySummary> for TraversalProgress<'a> {
-    fn zero(_cx: &()) -> Self {
+    fn zero(_cx: ()) -> Self {
         Default::default()
     }
 
-    fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
+    fn add_summary(&mut self, summary: &'a EntrySummary, _: ()) {
         self.max_path = summary.max_path.as_ref();
         self.count += summary.count;
         self.non_ignored_count += summary.non_ignored_count;
@@ -5412,7 +5406,7 @@ impl Default for TraversalProgress<'_> {
 #[derive(Debug)]
 pub struct Traversal<'a> {
     snapshot: &'a Snapshot,
-    cursor: sum_tree::Cursor<'a, Entry, TraversalProgress<'a>>,
+    cursor: sum_tree::Cursor<'a, 'static, Entry, TraversalProgress<'a>>,
     include_ignored: bool,
     include_files: bool,
     include_dirs: bool,
@@ -5426,7 +5420,7 @@ impl<'a> Traversal<'a> {
         include_ignored: bool,
         start_path: &Path,
     ) -> Self {
-        let mut cursor = snapshot.entries_by_path.cursor(&());
+        let mut cursor = snapshot.entries_by_path.cursor(());
         cursor.seek(&TraversalTarget::path(start_path), Bias::Left);
         let mut traversal = Self {
             snapshot,
@@ -5536,13 +5530,13 @@ impl PathTarget<'_> {
 }
 
 impl<'a, S: Summary> SeekTarget<'a, PathSummary<S>, PathProgress<'a>> for PathTarget<'_> {
-    fn cmp(&self, cursor_location: &PathProgress<'a>, _: &S::Context) -> Ordering {
+    fn cmp(&self, cursor_location: &PathProgress<'a>, _: S::Context<'_>) -> Ordering {
         self.cmp_path(cursor_location.max_path)
     }
 }
 
 impl<'a, S: Summary> SeekTarget<'a, PathSummary<S>, TraversalProgress<'a>> for PathTarget<'_> {
-    fn cmp(&self, cursor_location: &TraversalProgress<'a>, _: &S::Context) -> Ordering {
+    fn cmp(&self, cursor_location: &TraversalProgress<'a>, _: S::Context<'_>) -> Ordering {
         self.cmp_path(cursor_location.max_path)
     }
 }
@@ -5584,13 +5578,15 @@ impl<'a> TraversalTarget<'a> {
 }
 
 impl<'a> SeekTarget<'a, EntrySummary, TraversalProgress<'a>> for TraversalTarget<'_> {
-    fn cmp(&self, cursor_location: &TraversalProgress<'a>, _: &()) -> Ordering {
+    fn cmp(&self, cursor_location: &TraversalProgress<'a>, _: ()) -> Ordering {
         self.cmp_progress(cursor_location)
     }
 }
 
-impl<'a> SeekTarget<'a, PathSummary<&'static ()>, TraversalProgress<'a>> for TraversalTarget<'_> {
-    fn cmp(&self, cursor_location: &TraversalProgress<'a>, _: &()) -> Ordering {
+impl<'a> SeekTarget<'a, PathSummary<sum_tree::NoSummary>, TraversalProgress<'a>>
+    for TraversalTarget<'_>
+{
+    fn cmp(&self, cursor_location: &TraversalProgress<'a>, _: ()) -> Ordering {
         self.cmp_progress(cursor_location)
     }
 }