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

@ -2,7 +2,7 @@ pub mod participant;
pub mod room;
use crate::call_settings::CallSettings;
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result, anyhow};
use audio::Audio;
use client::{ChannelId, Client, TypedEnvelope, User, UserStore, ZED_ALWAYS_ACTIVE, proto};
use collections::HashSet;
@ -187,7 +187,7 @@ impl ActiveCall {
let invite = if let Some(room) = room {
cx.spawn(async move |_, cx| {
let room = room.await.map_err(|err| anyhow!("{:?}", err))?;
let room = room.await.map_err(|err| anyhow!("{err:?}"))?;
let initial_project_id = if let Some(initial_project) = initial_project {
Some(
@ -236,7 +236,7 @@ impl ActiveCall {
.shared();
self.pending_room_creation = Some(room.clone());
cx.background_spawn(async move {
room.await.map_err(|err| anyhow!("{:?}", err))?;
room.await.map_err(|err| anyhow!("{err:?}"))?;
anyhow::Ok(())
})
};
@ -326,7 +326,7 @@ impl ActiveCall {
.0
.borrow_mut()
.take()
.ok_or_else(|| anyhow!("no incoming call"))?;
.context("no incoming call")?;
telemetry::event!("Incoming Call Declined", room_id = call.room_id);
self.client.send(proto::DeclineCall {
room_id: call.room_id,
@ -399,12 +399,9 @@ impl ActiveCall {
project: Entity<Project>,
cx: &mut Context<Self>,
) -> Result<()> {
if let Some((room, _)) = self.room.as_ref() {
self.report_call_event("Project Unshared", cx);
room.update(cx, |room, cx| room.unshare_project(project, cx))
} else {
Err(anyhow!("no active call"))
}
let (room, _) = self.room.as_ref().context("no active call")?;
self.report_call_event("Project Unshared", cx);
room.update(cx, |room, cx| room.unshare_project(project, cx))
}
pub fn location(&self) -> Option<&WeakEntity<Project>> {

View file

@ -1,4 +1,4 @@
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result};
use client::{ParticipantIndex, User, proto};
use collections::HashMap;
use gpui::WeakEntity;
@ -18,17 +18,17 @@ pub enum ParticipantLocation {
impl ParticipantLocation {
pub fn from_proto(location: Option<proto::ParticipantLocation>) -> Result<Self> {
match location.and_then(|l| l.variant) {
Some(proto::participant_location::Variant::SharedProject(project)) => {
match location
.and_then(|l| l.variant)
.context("participant location was not provided")?
{
proto::participant_location::Variant::SharedProject(project) => {
Ok(Self::SharedProject {
project_id: project.id,
})
}
Some(proto::participant_location::Variant::UnsharedProject(_)) => {
Ok(Self::UnsharedProject)
}
Some(proto::participant_location::Variant::External(_)) => Ok(Self::External),
None => Err(anyhow!("participant location was not provided")),
proto::participant_location::Variant::UnsharedProject(_) => Ok(Self::UnsharedProject),
proto::participant_location::Variant::External(_) => Ok(Self::External),
}
}
}

View file

@ -2,7 +2,7 @@ use crate::{
call_settings::CallSettings,
participant::{LocalParticipant, ParticipantLocation, RemoteParticipant},
};
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result, anyhow};
use audio::{Audio, Sound};
use client::{
ChannelId, Client, ParticipantIndex, TypedEnvelope, User, UserStore,
@ -165,7 +165,7 @@ impl Room {
) -> Task<Result<Entity<Self>>> {
cx.spawn(async move |cx| {
let response = client.request(proto::CreateRoom {}).await?;
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
let room_proto = response.room.context("invalid room")?;
let room = cx.new(|cx| {
let mut room = Self::new(
room_proto.id,
@ -270,7 +270,7 @@ impl Room {
user_store: Entity<UserStore>,
mut cx: AsyncApp,
) -> Result<Entity<Self>> {
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
let room_proto = response.room.context("invalid room")?;
let room = cx.new(|cx| {
Self::new(
room_proto.id,
@ -360,7 +360,7 @@ impl Room {
log::info!("detected client disconnection");
this.upgrade()
.ok_or_else(|| anyhow!("room was dropped"))?
.context("room was dropped")?
.update(cx, |this, cx| {
this.status = RoomStatus::Rejoining;
cx.notify();
@ -428,9 +428,7 @@ impl Room {
log::info!("reconnection failed, leaving room");
this.update(cx, |this, cx| this.leave(cx))?.await?;
}
Err(anyhow!(
"can't reconnect to room: client failed to re-establish connection"
))
anyhow::bail!("can't reconnect to room: client failed to re-establish connection");
}
fn rejoin(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
@ -494,7 +492,7 @@ impl Room {
let response = response.await?;
let message_id = response.message_id;
let response = response.payload;
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
let room_proto = response.room.context("invalid room")?;
this.update(cx, |this, cx| {
this.status = RoomStatus::Online;
this.apply_room_update(room_proto, cx)?;
@ -645,10 +643,7 @@ impl Room {
envelope: TypedEnvelope<proto::RoomUpdated>,
mut cx: AsyncApp,
) -> Result<()> {
let room = envelope
.payload
.room
.ok_or_else(|| anyhow!("invalid room"))?;
let room = envelope.payload.room.context("invalid room")?;
this.update(&mut cx, |this, cx| this.apply_room_update(room, cx))?
}
@ -937,12 +932,15 @@ impl Room {
} => {
let user_id = participant.identity().0.parse()?;
let track_id = track.sid();
let participant = self.remote_participants.get_mut(&user_id).ok_or_else(|| {
anyhow!(
"{:?} subscribed to track by unknown participant {user_id}",
self.client.user_id()
)
})?;
let participant =
self.remote_participants
.get_mut(&user_id)
.with_context(|| {
format!(
"{:?} subscribed to track by unknown participant {user_id}",
self.client.user_id()
)
})?;
if self.live_kit.as_ref().map_or(true, |kit| kit.deafened) {
if publication.is_audio() {
publication.set_enabled(false, cx);
@ -972,12 +970,15 @@ impl Room {
track, participant, ..
} => {
let user_id = participant.identity().0.parse()?;
let participant = self.remote_participants.get_mut(&user_id).ok_or_else(|| {
anyhow!(
"{:?}, unsubscribed from track by unknown participant {user_id}",
self.client.user_id()
)
})?;
let participant =
self.remote_participants
.get_mut(&user_id)
.with_context(|| {
format!(
"{:?}, unsubscribed from track by unknown participant {user_id}",
self.client.user_id()
)
})?;
match track {
livekit_client::RemoteTrack::Audio(track) => {
participant.audio_tracks.remove(&track.sid());
@ -1324,7 +1325,7 @@ impl Room {
let live_kit = this
.live_kit
.as_mut()
.ok_or_else(|| anyhow!("live-kit was not initialized"))?;
.context("live-kit was not initialized")?;
let canceled = if let LocalTrack::Pending {
publish_id: cur_publish_id,
@ -1389,7 +1390,7 @@ impl Room {
cx.spawn(async move |this, cx| {
let sources = sources.await??;
let source = sources.first().ok_or_else(|| anyhow!("no display found"))?;
let source = sources.first().context("no display found")?;
let publication = participant.publish_screenshare_track(&**source, cx).await;
@ -1397,7 +1398,7 @@ impl Room {
let live_kit = this
.live_kit
.as_mut()
.ok_or_else(|| anyhow!("live-kit was not initialized"))?;
.context("live-kit was not initialized")?;
let canceled = if let LocalTrack::Pending {
publish_id: cur_publish_id,
@ -1485,16 +1486,14 @@ impl Room {
}
pub fn unshare_screen(&mut self, cx: &mut Context<Self>) -> Result<()> {
if self.status.is_offline() {
return Err(anyhow!("room is offline"));
}
anyhow::ensure!(!self.status.is_offline(), "room is offline");
let live_kit = self
.live_kit
.as_mut()
.ok_or_else(|| anyhow!("live-kit was not initialized"))?;
.context("live-kit was not initialized")?;
match mem::take(&mut live_kit.screen_track) {
LocalTrack::None => Err(anyhow!("screen was not shared")),
LocalTrack::None => anyhow::bail!("screen was not shared"),
LocalTrack::Pending { .. } => {
cx.notify();
Ok(())