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
<backtrace::capture::Backtrace>::create
<backtrace::capture::Backtrace>::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
<text::BufferSnapshot>::summary_for_anchor::<usize>
<multi_buffer::Anchor as multi_buffer::ToOffset>::to_offset
<editor::display_map::DisplayMap>::splice_inlays
<editor::Editor>::splice_inlay_hints
editor::inlay_hint_cache::fetch_and_update_hints::{closure#0}::{closure#0}
<async_task::raw::RawTask<<async_task::runnable::Builder<_>>::spawn_local::Checked<core::pin::Pin<alloc::boxed::Box<dyn core::future::future::Future<Output = core::result::Result<(), anyhow::Error>>>>>, core::result::Result<(), anyhow::Error>, <gpui::executor::ForegroundExecutor>::spawn::inner<core::result::Result<(), anyhow::Error>>::{closure#0}, ()>>::run
<gpui::platform::mac::platform::MacPlatform as gpui::platform::Platform>::run
Zed::main
std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>
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 <conrad@zed.dev>
This commit is contained in:
Kirill Bulatov 2024-02-27 22:19:11 +02:00 committed by GitHub
parent 89caf06dbe
commit e2bcb28286
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -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,
))
})?