panics (#7793)

Conrad Irwin and Max created

Release Notes:

- Fix a panic in rename
([#7509](https://github.com/zed-industries/zed/issues/7509)).

---------

Co-authored-by: Max <max@zed.dev>

Change summary

crates/editor/src/editor.rs             | 12 +++++++-----
crates/multi_buffer/src/multi_buffer.rs | 17 ++++++++++-------
2 files changed, 17 insertions(+), 12 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -7660,8 +7660,9 @@ impl Editor {
         let snapshot = cursor_buffer.read(cx).snapshot();
         let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
         let prepare_rename = project.update(cx, |project, cx| {
-            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
+            project.prepare_rename(cursor_buffer.clone(), cursor_buffer_offset, cx)
         });
+        drop(snapshot);
 
         Some(cx.spawn(|this, mut cx| async move {
             let rename_range = if let Some(range) = prepare_rename.await? {
@@ -7681,11 +7682,12 @@ impl Editor {
                 })?
             };
             if let Some(rename_range) = rename_range {
-                let rename_buffer_range = rename_range.to_offset(&snapshot);
-                let cursor_offset_in_rename_range =
-                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
-
                 this.update(&mut cx, |this, cx| {
+                    let snapshot = cursor_buffer.read(cx).snapshot();
+                    let rename_buffer_range = rename_range.to_offset(&snapshot);
+                    let cursor_offset_in_rename_range =
+                        cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
+
                     this.take_rename(false, cx);
                     let buffer = this.buffer.read(cx).read(cx);
                     let cursor_offset = selection.head().to_offset(&buffer);

crates/multi_buffer/src/multi_buffer.rs 🔗

@@ -50,7 +50,6 @@ pub struct ExcerptId(usize);
 pub struct MultiBuffer {
     snapshot: RefCell<MultiBufferSnapshot>,
     buffers: RefCell<HashMap<BufferId, BufferState>>,
-    next_excerpt_id: usize,
     subscriptions: Topic,
     singleton: bool,
     replica_id: ReplicaId,
@@ -232,7 +231,6 @@ impl MultiBuffer {
         Self {
             snapshot: Default::default(),
             buffers: Default::default(),
-            next_excerpt_id: 1,
             subscriptions: Default::default(),
             singleton: false,
             capability,
@@ -272,7 +270,6 @@ impl MultiBuffer {
         Self {
             snapshot: RefCell::new(self.snapshot.borrow().clone()),
             buffers: RefCell::new(buffers),
-            next_excerpt_id: 1,
             subscriptions: Default::default(),
             singleton: self.singleton,
             capability: self.capability,
@@ -993,7 +990,12 @@ impl MultiBuffer {
         O: text::ToOffset,
     {
         let mut ids = Vec::new();
-        let mut next_excerpt_id = self.next_excerpt_id;
+        let mut next_excerpt_id =
+            if let Some(last_entry) = self.snapshot.borrow().excerpt_ids.last() {
+                last_entry.id.0 + 1
+            } else {
+                1
+            };
         self.insert_excerpts_with_ids_after(
             prev_excerpt_id,
             buffer,
@@ -1079,9 +1081,6 @@ impl MultiBuffer {
                         ..buffer_snapshot.anchor_after(&primary.end)
                 }),
             };
-            if id.0 >= self.next_excerpt_id {
-                self.next_excerpt_id = id.0 + 1;
-            }
             excerpts.push((id, range.clone()));
             let excerpt = Excerpt::new(
                 id,
@@ -1093,6 +1092,10 @@ impl MultiBuffer {
             );
             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 }, &());
         }