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

@ -58,7 +58,7 @@ struct RemoteBufferStore {
project_id: u64,
loading_remote_buffers_by_id: HashMap<BufferId, Entity<Buffer>>,
remote_buffer_listeners:
HashMap<BufferId, Vec<oneshot::Sender<Result<Entity<Buffer>, anyhow::Error>>>>,
HashMap<BufferId, Vec<oneshot::Sender<anyhow::Result<Entity<Buffer>>>>>,
worktree_store: Entity<WorktreeStore>,
}
@ -152,11 +152,7 @@ impl RemoteBufferStore {
capability: Capability,
cx: &mut Context<BufferStore>,
) -> Result<Option<Entity<Buffer>>> {
match envelope
.payload
.variant
.ok_or_else(|| anyhow!("missing variant"))?
{
match envelope.payload.variant.context("missing variant")? {
proto::create_buffer_for_peer::Variant::State(mut state) => {
let buffer_id = BufferId::new(state.id)?;
@ -168,8 +164,8 @@ impl RemoteBufferStore {
.worktree_store
.read(cx)
.worktree_for_id(worktree_id, cx)
.ok_or_else(|| {
anyhow!("no worktree found for id {}", file.worktree_id)
.with_context(|| {
format!("no worktree found for id {}", file.worktree_id)
})?;
buffer_file = Some(Arc::new(File::from_proto(file, worktree.clone(), cx)?)
as Arc<dyn language::File>);
@ -197,8 +193,8 @@ impl RemoteBufferStore {
.loading_remote_buffers_by_id
.get(&buffer_id)
.cloned()
.ok_or_else(|| {
anyhow!(
.with_context(|| {
format!(
"received chunk for buffer {} without initial state",
chunk.buffer_id
)
@ -341,10 +337,7 @@ impl RemoteBufferStore {
});
cx.spawn(async move |this, cx| {
let response = request
.await?
.transaction
.ok_or_else(|| anyhow!("missing transaction"))?;
let response = request.await?.transaction.context("missing transaction")?;
this.update(cx, |this, cx| {
this.deserialize_project_transaction(response, push_to_history, cx)
})?
@ -913,8 +906,8 @@ impl BufferStore {
if is_remote {
return Ok(());
} else {
debug_panic!("buffer {} was already registered", remote_id);
Err(anyhow!("buffer {} was already registered", remote_id))?;
debug_panic!("buffer {remote_id} was already registered");
anyhow::bail!("buffer {remote_id} was already registered");
}
}
entry.insert(open_buffer);
@ -963,7 +956,7 @@ impl BufferStore {
pub fn get_existing(&self, buffer_id: BufferId) -> Result<Entity<Buffer>> {
self.get(buffer_id)
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))
.with_context(|| format!("unknown buffer id {buffer_id}"))
}
pub fn get_possibly_incomplete(&self, buffer_id: BufferId) -> Option<Entity<Buffer>> {
@ -1279,9 +1272,9 @@ impl BufferStore {
capability: Capability,
cx: &mut Context<Self>,
) -> Result<()> {
let Some(remote) = self.as_remote_mut() else {
return Err(anyhow!("buffer store is not a remote"));
};
let remote = self
.as_remote_mut()
.context("buffer store is not a remote")?;
if let Some(buffer) =
remote.handle_create_buffer_for_peer(envelope, replica_id, capability, cx)?
@ -1303,12 +1296,12 @@ impl BufferStore {
this.update(&mut cx, |this, cx| {
let payload = envelope.payload.clone();
if let Some(buffer) = this.get_possibly_incomplete(buffer_id) {
let file = payload.file.ok_or_else(|| anyhow!("invalid file"))?;
let file = payload.file.context("invalid file")?;
let worktree = this
.worktree_store
.read(cx)
.worktree_for_id(WorktreeId::from_proto(file.worktree_id), cx)
.ok_or_else(|| anyhow!("no such worktree"))?;
.context("no such worktree")?;
let file = File::from_proto(file, worktree, cx)?;
let old_file = buffer.update(cx, |buffer, cx| {
let old_file = buffer.file().cloned();
@ -1445,7 +1438,7 @@ impl BufferStore {
let mtime = envelope.payload.mtime.clone().map(|time| time.into());
let line_ending = deserialize_line_ending(
proto::LineEnding::from_i32(envelope.payload.line_ending)
.ok_or_else(|| anyhow!("missing line ending"))?,
.context("missing line ending")?,
);
this.update(&mut cx, |this, cx| {
if let Some(buffer) = this.get_possibly_incomplete(buffer_id) {
@ -1495,7 +1488,7 @@ impl BufferStore {
let buffer_id = BufferId::new(*buffer_id)?;
buffers.insert(this.get_existing(buffer_id)?);
}
Ok::<_, anyhow::Error>(this.reload_buffers(buffers, false, cx))
anyhow::Ok(this.reload_buffers(buffers, false, cx))
})??;
let project_transaction = reload.await?;