Move "async move" a few characters to the left in cx.spawn() (#26758)

This is the core change:
https://github.com/zed-industries/zed/pull/26758/files#diff-044302c0d57147af17e68a0009fee3e8dcdfb4f32c27a915e70cfa80e987f765R1052

TODO:
- [x] Use AsyncFn instead of Fn() -> Future in GPUI spawn methods
- [x] Implement it in the whole app
- [x] Implement it in the debugger 
- [x] Glance at the RPC crate, and see if those box future methods can
be switched over. Answer: It can't directly, as you can't make an
AsyncFn* into a trait object. There's ways around that, but they're all
more complex than just keeping the code as is.
- [ ] Fix platform specific code

Release Notes:

- N/A
This commit is contained in:
Mikayla Maki 2025-03-18 19:09:02 -07:00 committed by GitHub
parent 7f2e3fb5bd
commit 1aefa5178b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
256 changed files with 3110 additions and 3200 deletions

View file

@ -77,12 +77,12 @@ impl State {
.anthropic
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.delete_credentials(&api_url, &cx)
.await
.ok();
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = None;
this.api_key_from_env = false;
cx.notify();
@ -96,13 +96,13 @@ impl State {
.anthropic
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.write_credentials(&api_url, "Bearer", api_key.as_bytes(), &cx)
.await
.ok();
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = Some(api_key);
cx.notify();
})
@ -124,7 +124,7 @@ impl State {
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
let (api_key, from_env) = if let Ok(api_key) = std::env::var(ANTHROPIC_API_KEY_VAR) {
(api_key, true)
} else {
@ -138,7 +138,7 @@ impl State {
)
};
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = Some(api_key);
this.api_key_from_env = from_env;
cx.notify();
@ -760,15 +760,15 @@ impl ConfigurationView {
let load_credentials_task = Some(cx.spawn({
let state = state.clone();
|this, mut cx| async move {
async move |this, cx| {
if let Some(task) = state
.update(&mut cx, |state, cx| state.authenticate(cx))
.update(cx, |state, cx| state.authenticate(cx))
.log_err()
{
// We don't log an error, because "not signed in" is also an error.
let _ = task.await;
}
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.load_credentials_task = None;
cx.notify();
})
@ -794,9 +794,9 @@ impl ConfigurationView {
}
let state = self.state.clone();
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
state
.update(&mut cx, |state, cx| state.set_api_key(api_key, cx))?
.update(cx, |state, cx| state.set_api_key(api_key, cx))?
.await
})
.detach_and_log_err(cx);
@ -809,10 +809,8 @@ impl ConfigurationView {
.update(cx, |editor, cx| editor.set_text("", window, cx));
let state = self.state.clone();
cx.spawn_in(window, |_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.reset_api_key(cx))?
.await
cx.spawn_in(window, async move |_, cx| {
state.update(cx, |state, cx| state.reset_api_key(cx))?.await
})
.detach_and_log_err(cx);

View file

@ -90,12 +90,12 @@ pub struct State {
impl State {
fn reset_credentials(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
let credentials_provider = <dyn CredentialsProvider>::global(cx);
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.delete_credentials(AMAZON_AWS_URL, &cx)
.await
.log_err();
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.credentials = None;
this.credentials_from_env = false;
cx.notify();
@ -109,7 +109,7 @@ impl State {
cx: &mut Context<Self>,
) -> Task<Result<()>> {
let credentials_provider = <dyn CredentialsProvider>::global(cx);
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.write_credentials(
AMAZON_AWS_URL,
@ -118,7 +118,7 @@ impl State {
&cx,
)
.await?;
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.credentials = Some(credentials);
cx.notify();
})
@ -135,7 +135,7 @@ impl State {
}
let credentials_provider = <dyn CredentialsProvider>::global(cx);
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
let (credentials, from_env) =
if let Ok(credentials) = std::env::var(ZED_AWS_CREDENTIALS_VAR) {
(credentials, true)
@ -154,7 +154,7 @@ impl State {
let credentials: BedrockCredentials =
serde_json::from_str(&credentials).context("failed to parse credentials")?;
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.credentials = Some(credentials);
this.credentials_from_env = from_env;
cx.notify();
@ -789,15 +789,15 @@ impl ConfigurationView {
let load_credentials_task = Some(cx.spawn({
let state = state.clone();
|this, mut cx| async move {
async move |this, cx| {
if let Some(task) = state
.update(&mut cx, |state, cx| state.authenticate(cx))
.update(cx, |state, cx| state.authenticate(cx))
.log_err()
{
// We don't log an error, because "not signed in" is also an error.
let _ = task.await;
}
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.load_credentials_task = None;
cx.notify();
})
@ -855,9 +855,9 @@ impl ConfigurationView {
.to_string();
let state = self.state.clone();
cx.spawn(|_, mut cx| async move {
cx.spawn(async move |_, cx| {
state
.update(&mut cx, |state, cx| {
.update(cx, |state, cx| {
let credentials: BedrockCredentials = BedrockCredentials {
access_key_id: access_key_id.clone(),
secret_access_key: secret_access_key.clone(),
@ -880,9 +880,9 @@ impl ConfigurationView {
.update(cx, |editor, cx| editor.set_text("", window, cx));
let state = self.state.clone();
cx.spawn(|_, mut cx| async move {
cx.spawn(async move |_, cx| {
state
.update(&mut cx, |state, cx| state.reset_credentials(cx))?
.update(cx, |state, cx| state.reset_credentials(cx))?
.await
})
.detach_and_log_err(cx);

View file

@ -132,7 +132,7 @@ impl State {
|this, _listener, _event, cx| {
let client = this.client.clone();
let llm_api_token = this.llm_api_token.clone();
cx.spawn(|_this, _cx| async move {
cx.spawn(async move |_this, _cx| {
llm_api_token.refresh(&client).await?;
anyhow::Ok(())
})
@ -148,9 +148,9 @@ impl State {
fn authenticate(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
let client = self.client.clone();
cx.spawn(move |this, mut cx| async move {
cx.spawn(async move |this, cx| {
client.authenticate_and_connect(true, &cx).await?;
this.update(&mut cx, |_, cx| cx.notify())
this.update(cx, |_, cx| cx.notify())
})
}
@ -163,11 +163,11 @@ impl State {
fn accept_terms_of_service(&mut self, cx: &mut Context<Self>) {
let user_store = self.user_store.clone();
self.accept_terms = Some(cx.spawn(move |this, mut cx| async move {
self.accept_terms = Some(cx.spawn(async move |this, cx| {
let _ = user_store
.update(&mut cx, |store, cx| store.accept_terms_of_service(cx))?
.update(cx, |store, cx| store.accept_terms_of_service(cx))?
.await;
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.accept_terms = None;
cx.notify()
})
@ -183,10 +183,10 @@ impl CloudLanguageModelProvider {
let state = cx.new(|cx| State::new(client.clone(), user_store.clone(), status, cx));
let state_ref = state.downgrade();
let maintain_client_status = cx.spawn(|mut cx| async move {
let maintain_client_status = cx.spawn(async move |cx| {
while let Some(status) = status_rx.next().await {
if let Some(this) = state_ref.upgrade() {
_ = this.update(&mut cx, |this, cx| {
_ = this.update(cx, |this, cx| {
if this.status != status {
this.status = status;
cx.notify();

View file

@ -229,8 +229,8 @@ impl LanguageModel for CopilotChatLanguageModel {
let is_streaming = copilot_request.stream;
let request_limiter = self.request_limiter.clone();
let future = cx.spawn(|cx| async move {
let response = CopilotChat::stream_completion(copilot_request, cx);
let future = cx.spawn(async move |cx| {
let response = CopilotChat::stream_completion(copilot_request, cx.clone());
request_limiter.stream(async move {
let response = response.await?;
let stream = response
@ -264,6 +264,7 @@ impl LanguageModel for CopilotChatLanguageModel {
}
})
.boxed();
Ok(stream)
}).await
});

View file

@ -63,12 +63,12 @@ impl State {
.deepseek
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.delete_credentials(&api_url, &cx)
.await
.log_err();
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = None;
this.api_key_from_env = false;
cx.notify();
@ -82,11 +82,11 @@ impl State {
.deepseek
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.write_credentials(&api_url, "Bearer", api_key.as_bytes(), &cx)
.await?;
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = Some(api_key);
cx.notify();
})
@ -103,7 +103,7 @@ impl State {
.deepseek
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
let (api_key, from_env) = if let Ok(api_key) = std::env::var(DEEPSEEK_API_KEY_VAR) {
(api_key, true)
} else {
@ -117,7 +117,7 @@ impl State {
)
};
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = Some(api_key);
this.api_key_from_env = from_env;
cx.notify();
@ -517,15 +517,15 @@ impl ConfigurationView {
let load_credentials_task = Some(cx.spawn({
let state = state.clone();
|this, mut cx| async move {
async move |this, cx| {
if let Some(task) = state
.update(&mut cx, |state, cx| state.authenticate(cx))
.update(cx, |state, cx| state.authenticate(cx))
.log_err()
{
let _ = task.await;
}
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.load_credentials_task = None;
cx.notify();
})
@ -547,9 +547,9 @@ impl ConfigurationView {
}
let state = self.state.clone();
cx.spawn(|_, mut cx| async move {
cx.spawn(async move |_, cx| {
state
.update(&mut cx, |state, cx| state.set_api_key(api_key, cx))?
.update(cx, |state, cx| state.set_api_key(api_key, cx))?
.await
})
.detach_and_log_err(cx);
@ -562,12 +562,8 @@ impl ConfigurationView {
.update(cx, |editor, cx| editor.set_text("", window, cx));
let state = self.state.clone();
cx.spawn(|_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.reset_api_key(cx))?
.await
})
.detach_and_log_err(cx);
cx.spawn(async move |_, cx| state.update(cx, |state, cx| state.reset_api_key(cx))?.await)
.detach_and_log_err(cx);
cx.notify();
}

View file

@ -66,12 +66,12 @@ impl State {
.google
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.delete_credentials(&api_url, &cx)
.await
.log_err();
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = None;
this.api_key_from_env = false;
cx.notify();
@ -85,11 +85,11 @@ impl State {
.google
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.write_credentials(&api_url, "Bearer", api_key.as_bytes(), &cx)
.await?;
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = Some(api_key);
cx.notify();
})
@ -107,7 +107,7 @@ impl State {
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
let (api_key, from_env) = if let Ok(api_key) = std::env::var(GOOGLE_AI_API_KEY_VAR) {
(api_key, true)
} else {
@ -121,7 +121,7 @@ impl State {
)
};
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = Some(api_key);
this.api_key_from_env = from_env;
cx.notify();
@ -418,15 +418,15 @@ impl ConfigurationView {
let load_credentials_task = Some(cx.spawn_in(window, {
let state = state.clone();
|this, mut cx| async move {
async move |this, cx| {
if let Some(task) = state
.update(&mut cx, |state, cx| state.authenticate(cx))
.update(cx, |state, cx| state.authenticate(cx))
.log_err()
{
// We don't log an error, because "not signed in" is also an error.
let _ = task.await;
}
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.load_credentials_task = None;
cx.notify();
})
@ -452,9 +452,9 @@ impl ConfigurationView {
}
let state = self.state.clone();
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
state
.update(&mut cx, |state, cx| state.set_api_key(api_key, cx))?
.update(cx, |state, cx| state.set_api_key(api_key, cx))?
.await
})
.detach_and_log_err(cx);
@ -467,10 +467,8 @@ impl ConfigurationView {
.update(cx, |editor, cx| editor.set_text("", window, cx));
let state = self.state.clone();
cx.spawn_in(window, |_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.reset_api_key(cx))?
.await
cx.spawn_in(window, async move |_, cx| {
state.update(cx, |state, cx| state.reset_api_key(cx))?.await
})
.detach_and_log_err(cx);

View file

@ -67,7 +67,7 @@ impl State {
let api_url = settings.api_url.clone();
// As a proxy for the server being "authenticated", we'll check if its up by fetching the models
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
let models = get_models(http_client.as_ref(), &api_url, None).await?;
let mut models: Vec<lmstudio::Model> = models
@ -78,7 +78,7 @@ impl State {
models.sort_by(|a, b| a.name.cmp(&b.name));
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.available_models = models;
cx.notify();
})
@ -96,7 +96,7 @@ impl State {
}
let fetch_models_task = self.fetch_models(cx);
cx.spawn(|_this, _cx| async move { Ok(fetch_models_task.await?) })
cx.spawn(async move |_this, _cx| Ok(fetch_models_task.await?))
}
}
@ -198,7 +198,7 @@ impl LanguageModelProvider for LmStudioLanguageModelProvider {
let http_client = self.http_client.clone();
let api_url = settings.api_url.clone();
let id = model.id().0.to_string();
cx.spawn(|_| async move { preload_model(http_client, &api_url, &id).await })
cx.spawn(async move |_| preload_model(http_client, &api_url, &id).await)
.detach_and_log_err(cx);
}
@ -382,14 +382,14 @@ impl ConfigurationView {
pub fn new(state: gpui::Entity<State>, cx: &mut Context<Self>) -> Self {
let loading_models_task = Some(cx.spawn({
let state = state.clone();
|this, mut cx| async move {
async move |this, cx| {
if let Some(task) = state
.update(&mut cx, |state, cx| state.authenticate(cx))
.update(cx, |state, cx| state.authenticate(cx))
.log_err()
{
task.await.log_err();
}
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.loading_models_task = None;
cx.notify();
})

View file

@ -68,12 +68,12 @@ impl State {
.mistral
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.delete_credentials(&api_url, &cx)
.await
.log_err();
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = None;
this.api_key_from_env = false;
cx.notify();
@ -87,11 +87,11 @@ impl State {
.mistral
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.write_credentials(&api_url, "Bearer", api_key.as_bytes(), &cx)
.await?;
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = Some(api_key);
cx.notify();
})
@ -108,7 +108,7 @@ impl State {
.mistral
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
let (api_key, from_env) = if let Ok(api_key) = std::env::var(MISTRAL_API_KEY_VAR) {
(api_key, true)
} else {
@ -121,7 +121,7 @@ impl State {
false,
)
};
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = Some(api_key);
this.api_key_from_env = from_env;
cx.notify();
@ -482,16 +482,16 @@ impl ConfigurationView {
let load_credentials_task = Some(cx.spawn_in(window, {
let state = state.clone();
|this, mut cx| async move {
async move |this, cx| {
if let Some(task) = state
.update(&mut cx, |state, cx| state.authenticate(cx))
.update(cx, |state, cx| state.authenticate(cx))
.log_err()
{
// We don't log an error, because "not signed in" is also an error.
let _ = task.await;
}
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.load_credentials_task = None;
cx.notify();
})
@ -513,9 +513,9 @@ impl ConfigurationView {
}
let state = self.state.clone();
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
state
.update(&mut cx, |state, cx| state.set_api_key(api_key, cx))?
.update(cx, |state, cx| state.set_api_key(api_key, cx))?
.await
})
.detach_and_log_err(cx);
@ -528,10 +528,8 @@ impl ConfigurationView {
.update(cx, |editor, cx| editor.set_text("", window, cx));
let state = self.state.clone();
cx.spawn_in(window, |_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.reset_api_key(cx))?
.await
cx.spawn_in(window, async move |_, cx| {
state.update(cx, |state, cx| state.reset_api_key(cx))?.await
})
.detach_and_log_err(cx);

View file

@ -69,7 +69,7 @@ impl State {
let api_url = settings.api_url.clone();
// As a proxy for the server being "authenticated", we'll check if its up by fetching the models
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
let models = get_models(http_client.as_ref(), &api_url, None).await?;
let mut models: Vec<ollama::Model> = models
@ -83,7 +83,7 @@ impl State {
models.sort_by(|a, b| a.name.cmp(&b.name));
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.available_models = models;
cx.notify();
})
@ -101,7 +101,7 @@ impl State {
}
let fetch_models_task = self.fetch_models(cx);
cx.spawn(|_this, _cx| async move { Ok(fetch_models_task.await?) })
cx.spawn(async move |_this, _cx| Ok(fetch_models_task.await?))
}
}
@ -204,7 +204,7 @@ impl LanguageModelProvider for OllamaLanguageModelProvider {
let http_client = self.http_client.clone();
let api_url = settings.api_url.clone();
let id = model.id().0.to_string();
cx.spawn(|_| async move { preload_model(http_client, &api_url, &id).await })
cx.spawn(async move |_| preload_model(http_client, &api_url, &id).await)
.detach_and_log_err(cx);
}
@ -421,14 +421,14 @@ impl ConfigurationView {
pub fn new(state: gpui::Entity<State>, window: &mut Window, cx: &mut Context<Self>) -> Self {
let loading_models_task = Some(cx.spawn_in(window, {
let state = state.clone();
|this, mut cx| async move {
async move |this, cx| {
if let Some(task) = state
.update(&mut cx, |state, cx| state.authenticate(cx))
.update(cx, |state, cx| state.authenticate(cx))
.log_err()
{
task.await.log_err();
}
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.loading_models_task = None;
cx.notify();
})

View file

@ -69,12 +69,12 @@ impl State {
.openai
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.delete_credentials(&api_url, &cx)
.await
.log_err();
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = None;
this.api_key_from_env = false;
cx.notify();
@ -88,12 +88,12 @@ impl State {
.openai
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
credentials_provider
.write_credentials(&api_url, "Bearer", api_key.as_bytes(), &cx)
.await
.log_err();
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = Some(api_key);
cx.notify();
})
@ -110,7 +110,7 @@ impl State {
.openai
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
cx.spawn(async move |this, cx| {
let (api_key, from_env) = if let Ok(api_key) = std::env::var(OPENAI_API_KEY_VAR) {
(api_key, true)
} else {
@ -123,7 +123,7 @@ impl State {
false,
)
};
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.api_key = Some(api_key);
this.api_key_from_env = from_env;
cx.notify();
@ -452,16 +452,16 @@ impl ConfigurationView {
let load_credentials_task = Some(cx.spawn_in(window, {
let state = state.clone();
|this, mut cx| async move {
async move |this, cx| {
if let Some(task) = state
.update(&mut cx, |state, cx| state.authenticate(cx))
.update(cx, |state, cx| state.authenticate(cx))
.log_err()
{
// We don't log an error, because "not signed in" is also an error.
let _ = task.await;
}
this.update(&mut cx, |this, cx| {
this.update(cx, |this, cx| {
this.load_credentials_task = None;
cx.notify();
})
@ -483,9 +483,9 @@ impl ConfigurationView {
}
let state = self.state.clone();
cx.spawn_in(window, |_, mut cx| async move {
cx.spawn_in(window, async move |_, cx| {
state
.update(&mut cx, |state, cx| state.set_api_key(api_key, cx))?
.update(cx, |state, cx| state.set_api_key(api_key, cx))?
.await
})
.detach_and_log_err(cx);
@ -498,10 +498,8 @@ impl ConfigurationView {
.update(cx, |editor, cx| editor.set_text("", window, cx));
let state = self.state.clone();
cx.spawn_in(window, |_, mut cx| async move {
state
.update(&mut cx, |state, cx| state.reset_api_key(cx))?
.await
cx.spawn_in(window, async move |_, cx| {
state.update(cx, |state, cx| state.reset_api_key(cx))?.await
})
.detach_and_log_err(cx);