assistant panel: Fix panic when opening panel with zed.dev provider (#15538)

There was/is some race condition that gets triggered only with the
zed.dev provider when opening the provider that would cause a
double-borrow on workspace.

This PR fixes the issue by cloning the workspace weakly. Turns out we
can go very far with just the weak reference.

We're still a bit unsure why exactly the race condition happened, since
it's hard to reproduce, but we're working on configuration
view/management in #15490 anyway.

Release Notes:

- N/A

Co-authored-by: Bennet <bennet@zed.dev>
This commit is contained in:
Thorsten Ball 2024-07-31 16:57:24 +02:00 committed by GitHub
parent 64bfec533e
commit 874fedd717
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 14 additions and 24 deletions

View file

@ -545,7 +545,7 @@ impl AssistantPanel {
let mut editor = ContextEditor::for_context(
context,
self.fs.clone(),
workspace.clone(),
self.workspace.clone(),
self.project.clone(),
lsp_adapter_delegate,
assistant_panel,
@ -789,12 +789,9 @@ impl AssistantPanel {
let context = task.await?;
this.update(&mut cx, |this, cx| {
let Some(workspace) = this.workspace.upgrade() else {
return Ok(());
};
let lsp_adapter_delegate = workspace.update(cx, |workspace, cx| {
make_lsp_adapter_delegate(workspace.project(), cx).log_err()
});
let workspace = this.workspace.clone();
let project = this.project.clone();
let lsp_adapter_delegate = make_lsp_adapter_delegate(&project, cx).log_err();
let fs = this.fs.clone();
let project = this.project.clone();
@ -804,7 +801,7 @@ impl AssistantPanel {
let mut editor = ContextEditor::for_context(
context,
fs,
workspace.clone(),
workspace,
project,
lsp_adapter_delegate,
weak_assistant_panel,
@ -826,17 +823,14 @@ impl AssistantPanel {
None
} else {
let context = self.context_store.update(cx, |store, cx| store.create(cx));
let workspace = self.workspace.upgrade()?;
let lsp_adapter_delegate = workspace.update(cx, |workspace, cx| {
make_lsp_adapter_delegate(workspace.project(), cx).log_err()
});
let lsp_adapter_delegate = make_lsp_adapter_delegate(&self.project, cx).log_err();
let assistant_panel = cx.view().downgrade();
let editor = cx.new_view(|cx| {
let mut editor = ContextEditor::for_context(
context,
self.fs.clone(),
workspace.clone(),
self.workspace.clone(),
self.project.clone(),
lsp_adapter_delegate,
assistant_panel,
@ -1004,9 +998,6 @@ impl AssistantPanel {
let context = context.await?;
let assistant_panel = this.clone();
this.update(&mut cx, |this, cx| {
let workspace = workspace
.upgrade()
.ok_or_else(|| anyhow!("workspace dropped"))?;
let editor = cx.new_view(|cx| {
ContextEditor::for_context(
context,
@ -1060,9 +1051,6 @@ impl AssistantPanel {
let context = context.await?;
let assistant_panel = this.clone();
this.update(&mut cx, |this, cx| {
let workspace = workspace
.upgrade()
.ok_or_else(|| anyhow!("workspace dropped"))?;
let editor = cx.new_view(|cx| {
ContextEditor::for_context(
context,
@ -1276,7 +1264,7 @@ impl ContextEditor {
fn for_context(
context: Model<Context>,
fs: Arc<dyn Fs>,
workspace: View<Workspace>,
workspace: WeakView<Workspace>,
project: Model<Project>,
lsp_adapter_delegate: Option<Arc<dyn LspAdapterDelegate>>,
assistant_panel: WeakView<AssistantPanel>,
@ -1284,7 +1272,7 @@ impl ContextEditor {
) -> Self {
let completion_provider = SlashCommandCompletionProvider::new(
Some(cx.view().downgrade()),
Some(workspace.downgrade()),
Some(workspace.clone()),
);
let editor = cx.new_view(|cx| {
@ -1318,7 +1306,7 @@ impl ContextEditor {
scroll_position: None,
remote_id: None,
fs,
workspace: workspace.downgrade(),
workspace,
project,
pending_slash_command_creases: HashMap::default(),
pending_slash_command_blocks: HashMap::default(),

View file

@ -84,8 +84,10 @@ impl CloudLanguageModelProvider {
while let Some(status) = status_rx.next().await {
if let Some(this) = state_ref.upgrade() {
_ = this.update(&mut cx, |this, cx| {
this.status = status;
cx.notify();
if this.status != status {
this.status = status;
cx.notify();
}
});
} else {
break;