Don't allow strong view handles to be read/updated with an AsyncAppContext

This avoids an invitation to hold strong view handles across async await
points, which is a common source of leaks.

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra 2023-04-26 13:36:13 +02:00
parent 689e878bd8
commit 6317e885c7
14 changed files with 129 additions and 163 deletions

View file

@ -2715,14 +2715,15 @@ impl Editor {
let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
project.apply_code_action(buffer, action, true, cx)
});
let editor = editor.downgrade();
Some(cx.spawn(|workspace, cx| async move {
let project_transaction = apply_code_actions.await?;
Self::open_project_transaction(editor, workspace, project_transaction, title, cx).await
Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
}))
}
async fn open_project_transaction(
this: ViewHandle<Editor>,
this: &WeakViewHandle<Editor>,
workspace: WeakViewHandle<Workspace>,
transaction: ProjectTransaction,
title: String,
@ -5943,10 +5944,11 @@ impl Editor {
project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
});
let editor = editor.downgrade();
Some(cx.spawn(|workspace, mut cx| async move {
let project_transaction = rename.await?;
Self::open_project_transaction(
editor.clone(),
&editor,
workspace,
project_transaction,
format!("Rename: {}{}", old_name, new_name),
@ -6761,7 +6763,8 @@ impl Editor {
let editor = editor
.await?
.downcast::<Editor>()
.ok_or_else(|| anyhow!("opened item was not an editor"))?;
.ok_or_else(|| anyhow!("opened item was not an editor"))?
.downgrade();
editor.update(&mut cx, |editor, cx| {
let buffer = editor
.buffer()
@ -6783,6 +6786,7 @@ impl Editor {
anyhow::Ok(())
})??;
anyhow::Ok(())
})
.detach_and_log_err(cx);

View file

@ -67,6 +67,7 @@ impl FollowableItem for Editor {
.collect::<Vec<_>>()
});
let pane = pane.downgrade();
Some(cx.spawn(|mut cx| async move {
let mut buffers = futures::future::try_join_all(buffers).await?;
let editor = pane.read_with(&cx, |pane, cx| {
@ -127,7 +128,7 @@ impl FollowableItem for Editor {
};
update_editor_from_message(
editor.clone(),
editor.downgrade(),
project,
proto::update_view::Editor {
selections: state.selections,
@ -286,9 +287,6 @@ impl FollowableItem for Editor {
let update_view::Variant::Editor(message) = message;
let project = project.clone();
cx.spawn(|this, mut cx| async move {
let this = this
.upgrade(&cx)
.ok_or_else(|| anyhow!("editor was dropped"))?;
update_editor_from_message(this, project, message, &mut cx).await
})
}
@ -304,7 +302,7 @@ impl FollowableItem for Editor {
}
async fn update_editor_from_message(
this: ViewHandle<Editor>,
this: WeakViewHandle<Editor>,
project: ModelHandle<Project>,
message: proto::update_view::Editor,
cx: &mut AsyncAppContext,