Maintain cursor stack's position correctly when ascending the tree (#2795)

Antonio Scandurra created

This fixes a bug that could cause the cursor to incorrectly report its
start when using `slice` or `seek_forward`, and then calling `prev`. We
didn't notice this because we were not testing those three methods
together.

I suppose this could explain some of the panics we've observed because
we do use `slice`/`seek_forward` followed by `prev` calls in production.

Change summary

crates/sum_tree/src/cursor.rs   | 1 +
crates/sum_tree/src/sum_tree.rs | 8 +++++---
2 files changed, 6 insertions(+), 3 deletions(-)

Detailed changes

crates/sum_tree/src/cursor.rs 🔗

@@ -438,6 +438,7 @@ where
                 } => {
                     if ascending {
                         entry.index += 1;
+                        entry.position = self.position.clone();
                     }
 
                     for (child_tree, child_summary) in child_trees[entry.index..]

crates/sum_tree/src/sum_tree.rs 🔗

@@ -738,7 +738,7 @@ mod tests {
             for _ in 0..num_operations {
                 let splice_end = rng.gen_range(0..tree.extent::<Count>(&()).0 + 1);
                 let splice_start = rng.gen_range(0..splice_end + 1);
-                let count = rng.gen_range(0..3);
+                let count = rng.gen_range(0..10);
                 let tree_end = tree.extent::<Count>(&());
                 let new_items = rng
                     .sample_iter(distributions::Standard)
@@ -805,10 +805,12 @@ mod tests {
                 }
                 assert_eq!(filter_cursor.item(), None);
 
-                let mut pos = rng.gen_range(0..tree.extent::<Count>(&()).0 + 1);
                 let mut before_start = false;
                 let mut cursor = tree.cursor::<Count>();
-                cursor.seek(&Count(pos), Bias::Right, &());
+                let start_pos = rng.gen_range(0..=reference_items.len());
+                cursor.seek(&Count(start_pos), Bias::Right, &());
+                let mut pos = rng.gen_range(start_pos..=reference_items.len());
+                cursor.seek_forward(&Count(pos), Bias::Right, &());
 
                 for i in 0..10 {
                     assert_eq!(cursor.start().0, pos);