From e2bcb2828692ecfafd2891bf528bd799337e298c Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 27 Feb 2024 22:19:11 +0200 Subject: [PATCH] Use proper buffer versions when [de]serializing hint proto requests (#8502) During inlay hint<->proto conversions, uses proper buffer versions and never carries them across the .await points, to fix the ``` thread 'main' panicked at 'invalid anchor Anchor { timestamp: Lamport {0: 8558}, offset: 54, bias: Right, buffer_id: Some(BufferId(8)) }. buffer id: 8, version: Global {0: 8546, 1: 8378}' /Users/administrator/actions-runner-2/_work/zed/zed/crates/text/src/text.rs:1919 ::create ::new Zed::init_panic_hook::{closure#0} std::panicking::rust_panic_with_hook std::panicking::begin_panic_handler::{{closure}} std::sys_common::backtrace::__rust_end_short_backtrace _rust_begin_unwind core::panicking::panic_fmt ::summary_for_anchor:: ::to_offset ::splice_inlays ::splice_inlay_hints editor::inlay_hint_cache::fetch_and_update_hints::{closure#0}::{closure#0} >::spawn_local::Checked>>>>, core::result::Result<(), anyhow::Error>, ::spawn::inner>::{closure#0}, ()>>::run ::run Zed::main std::sys_common::backtrace::__rust_begin_short_backtrace:: std::rt::lang_start::<()>::{closure#0} std::rt::lang_start_internal _main ``` class of panics. Release Notes: - Fixed occasional panics during collaborative editing with inlay hints on both sides Co-authored-by: Conrad --- crates/project/src/project.rs | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index a3475cc23afc917f8302407cd9965f07bfb36962..1ee04eb62875c137ed88863dad11900d21592897 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -5756,7 +5756,6 @@ impl Project { let range_start = range.start; let range_end = range.end; let buffer_id = buffer.remote_id().into(); - let buffer_version = buffer.version().clone(); let lsp_request = InlayHints { range }; if self.is_local() { @@ -5782,23 +5781,22 @@ impl Project { buffer_id, start: Some(serialize_anchor(&range_start)), end: Some(serialize_anchor(&range_end)), - version: serialize_version(&buffer_version), + version: serialize_version(&buffer_handle.read(cx).version()), }; cx.spawn(move |project, cx| async move { let response = client .request(request) .await .context("inlay hints proto request")?; - let hints_request_result = LspCommand::response_from_proto( + LspCommand::response_from_proto( lsp_request, response, project.upgrade().ok_or_else(|| anyhow!("No project"))?, buffer_handle.clone(), - cx, + cx.clone(), ) - .await; - - hints_request_result.context("inlay hints proto response conversion") + .await + .context("inlay hints proto response conversion") }) } else { Task::ready(Err(anyhow!("project does not have a remote id"))) @@ -8074,20 +8072,12 @@ impl Project { .and_then(|buffer| buffer.upgrade()) .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id)) })??; - let buffer_version = deserialize_version(&envelope.payload.version); - buffer .update(&mut cx, |buffer, _| { - buffer.wait_for_version(buffer_version.clone()) + buffer.wait_for_version(deserialize_version(&envelope.payload.version)) })? .await - .with_context(|| { - format!( - "waiting for version {:?} for buffer {}", - buffer_version, - buffer.entity_id() - ) - })?; + .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?; let start = envelope .payload @@ -8101,13 +8091,19 @@ impl Project { .context("missing range end")?; let buffer_hints = this .update(&mut cx, |project, cx| { - project.inlay_hints(buffer, start..end, cx) + project.inlay_hints(buffer.clone(), start..end, cx) })? .await .context("inlay hints fetch")?; Ok(this.update(&mut cx, |project, cx| { - InlayHints::response_to_proto(buffer_hints, project, sender_id, &buffer_version, cx) + InlayHints::response_to_proto( + buffer_hints, + project, + sender_id, + &buffer.read(cx).version(), + cx, + ) })?) } @@ -8183,10 +8179,14 @@ impl Project { cx.clone(), ) .await?; - let buffer_version = buffer_handle.update(&mut cx, |buffer, _| buffer.version())?; let response = this .update(&mut cx, |this, cx| { - this.request_lsp(buffer_handle, LanguageServerToQuery::Primary, request, cx) + this.request_lsp( + buffer_handle.clone(), + LanguageServerToQuery::Primary, + request, + cx, + ) })? .await?; this.update(&mut cx, |this, cx| { @@ -8194,7 +8194,7 @@ impl Project { response, this, sender_id, - &buffer_version, + &buffer_handle.read(cx).version(), cx, )) })?