Use anyhow more idiomatically (#31052)

https://github.com/zed-industries/zed/issues/30972 brought up another
case where our context is not enough to track the actual source of the
issue: we get a general top-level error without inner error.

The reason for this was `.ok_or_else(|| anyhow!("failed to read HEAD
SHA"))?; ` on the top level.

The PR finally reworks the way we use anyhow to reduce such issues (or
at least make it simpler to bubble them up later in a fix).
On top of that, uses a few more anyhow methods for better readability.

* `.ok_or_else(|| anyhow!("..."))`, `map_err` and other similar error
conversion/option reporting cases are replaced with `context` and
`with_context` calls
* in addition to that, various `anyhow!("failed to do ...")` are
stripped with `.context("Doing ...")` messages instead to remove the
parasitic `failed to` text
* `anyhow::ensure!` is used instead of `if ... { return Err(...); }`
calls
* `anyhow::bail!` is used instead of `return Err(anyhow!(...));`

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2025-05-21 02:06:07 +03:00 committed by GitHub
parent 1e51a7ac44
commit 16366cf9f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
294 changed files with 2037 additions and 2610 deletions

View file

@ -1,5 +1,5 @@
use crate::{Channel, ChannelStore};
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result};
use client::{
ChannelId, Client, Subscription, TypedEnvelope, UserId, proto,
user::{User, UserStore},
@ -170,15 +170,16 @@ impl ChannelChat {
message: MessageParams,
cx: &mut Context<Self>,
) -> Result<Task<Result<u64>>> {
if message.text.trim().is_empty() {
Err(anyhow!("message body can't be empty"))?;
}
anyhow::ensure!(
!message.text.trim().is_empty(),
"message body can't be empty"
);
let current_user = self
.user_store
.read(cx)
.current_user()
.ok_or_else(|| anyhow!("current_user is not present"))?;
.context("current_user is not present")?;
let channel_id = self.channel_id;
let pending_id = ChannelMessageId::Pending(post_inc(&mut self.next_pending_message_id));
@ -215,7 +216,7 @@ impl ChannelChat {
});
let response = request.await?;
drop(outgoing_message_guard);
let response = response.message.ok_or_else(|| anyhow!("invalid message"))?;
let response = response.message.context("invalid message")?;
let id = response.id;
let message = ChannelMessage::from_proto(response, &user_store, cx).await?;
this.update(cx, |this, cx| {
@ -470,7 +471,7 @@ impl ChannelChat {
});
let response = request.await?;
let message = ChannelMessage::from_proto(
response.message.ok_or_else(|| anyhow!("invalid message"))?,
response.message.context("invalid message")?,
&user_store,
cx,
)
@ -531,10 +532,7 @@ impl ChannelChat {
mut cx: AsyncApp,
) -> Result<()> {
let user_store = this.update(&mut cx, |this, _| this.user_store.clone())?;
let message = message
.payload
.message
.ok_or_else(|| anyhow!("empty message"))?;
let message = message.payload.message.context("empty message")?;
let message_id = message.id;
let message = ChannelMessage::from_proto(message, &user_store, &mut cx).await?;
@ -566,10 +564,7 @@ impl ChannelChat {
mut cx: AsyncApp,
) -> Result<()> {
let user_store = this.update(&mut cx, |this, _| this.user_store.clone())?;
let message = message
.payload
.message
.ok_or_else(|| anyhow!("empty message"))?;
let message = message.payload.message.context("empty message")?;
let message = ChannelMessage::from_proto(message, &user_store, &mut cx).await?;
@ -753,10 +748,7 @@ impl ChannelMessage {
.collect(),
timestamp: OffsetDateTime::from_unix_timestamp(message.timestamp as i64)?,
sender,
nonce: message
.nonce
.ok_or_else(|| anyhow!("nonce is required"))?
.into(),
nonce: message.nonce.context("nonce is required")?.into(),
reply_to_message_id: message.reply_to_message_id,
edited_at,
})

View file

@ -1,7 +1,7 @@
mod channel_index;
use crate::{ChannelMessage, channel_buffer::ChannelBuffer, channel_chat::ChannelChat};
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result, anyhow};
use channel_index::ChannelIndex;
use client::{ChannelId, Client, ClientSettings, Subscription, User, UserId, UserStore};
use collections::{HashMap, HashSet, hash_map};
@ -332,9 +332,7 @@ impl ChannelStore {
cx.spawn(async move |this, cx| {
if let Some(request) = request {
let response = request.await?;
let this = this
.upgrade()
.ok_or_else(|| anyhow!("channel store dropped"))?;
let this = this.upgrade().context("channel store dropped")?;
let user_store = this.update(cx, |this, _| this.user_store.clone())?;
ChannelMessage::from_proto_vec(response.messages, &user_store, cx).await
} else {
@ -482,7 +480,7 @@ impl ChannelStore {
.spawn(async move |this, cx| {
let channel = this.update(cx, |this, _| {
this.channel_for_id(channel_id).cloned().ok_or_else(|| {
Arc::new(anyhow!("no channel for id: {}", channel_id))
Arc::new(anyhow!("no channel for id: {channel_id}"))
})
})??;
@ -514,7 +512,7 @@ impl ChannelStore {
}
}
};
cx.background_spawn(async move { task.await.map_err(|error| anyhow!("{}", error)) })
cx.background_spawn(async move { task.await.map_err(|error| anyhow!("{error}")) })
}
pub fn is_channel_admin(&self, channel_id: ChannelId) -> bool {
@ -578,9 +576,7 @@ impl ChannelStore {
})
.await?;
let channel = response
.channel
.ok_or_else(|| anyhow!("missing channel in response"))?;
let channel = response.channel.context("missing channel in response")?;
let channel_id = ChannelId(channel.id);
this.update(cx, |this, cx| {
@ -752,7 +748,7 @@ impl ChannelStore {
})
.await?
.channel
.ok_or_else(|| anyhow!("missing channel in response"))?;
.context("missing channel in response")?;
this.update(cx, |this, cx| {
let task = this.update_channels(
proto::UpdateChannels {