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-20 23:06:07 +00:00
committed by GitHub
parent 1e51a7ac44
commit 16366cf9f2
294 changed files with 2037 additions and 2610 deletions
@@ -30,7 +30,7 @@ impl BladeContext {
..Default::default()
})
}
.map_err(|e| anyhow::anyhow!("{:?}", e))?,
.map_err(|e| anyhow::anyhow!("{e:?}"))?,
);
Ok(Self { gpu })
}
@@ -49,8 +49,7 @@ fn parse_pci_id(id: &str) -> anyhow::Result<u32> {
"Expected a 4 digit PCI ID in hexadecimal format"
);
return u32::from_str_radix(id, 16)
.map_err(|_| anyhow::anyhow!("Failed to parse PCI ID as hex"));
return u32::from_str_radix(id, 16).context("parsing PCI ID as hex");
}
#[cfg(test)]
@@ -95,9 +95,7 @@ impl LinuxClient for HeadlessClient {
_handle: AnyWindowHandle,
_params: WindowParams,
) -> anyhow::Result<Box<dyn PlatformWindow>> {
Err(anyhow::anyhow!(
"neither DISPLAY nor WAYLAND_DISPLAY is set. You can run in headless mode"
))
anyhow::bail!("neither DISPLAY nor WAYLAND_DISPLAY is set. You can run in headless mode");
}
fn compositor_name(&self) -> &'static str {
+1 -1
View File
@@ -490,7 +490,7 @@ impl<P: LinuxClient + 'static> Platform for P {
let attributes = item.attributes().await?;
let username = attributes
.get("username")
.ok_or_else(|| anyhow!("Cannot find username in stored credentials"))?;
.context("Cannot find username in stored credentials")?;
let secret = item.secret().await?;
// we lose the zeroizing capabilities at this boundary,
@@ -3,7 +3,7 @@ use crate::{
GlyphId, LineLayout, Pixels, PlatformTextSystem, Point, RenderGlyphParams, SUBPIXEL_VARIANTS,
ShapedGlyph, ShapedRun, SharedString, Size, point, size,
};
use anyhow::{Context as _, Ok, Result, anyhow};
use anyhow::{Context as _, Ok, Result};
use collections::HashMap;
use cosmic_text::{
Attrs, AttrsList, CacheKey, Family, Font as CosmicTextFont, FontFeatures as CosmicFontFeatures,
@@ -232,7 +232,7 @@ impl CosmicTextSystemState {
let font = self
.font_system
.get_font(font_id)
.ok_or_else(|| anyhow!("Could not load font"))?;
.context("Could not load font")?;
// HACK: To let the storybook run and render Windows caption icons. We should actually do better font fallback.
let allowed_bad_font_names = [
@@ -309,7 +309,7 @@ impl CosmicTextSystemState {
glyph_bounds: Bounds<DevicePixels>,
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
if glyph_bounds.size.width.0 == 0 || glyph_bounds.size.height.0 == 0 {
Err(anyhow!("glyph bounds are empty"))
anyhow::bail!("glyph bounds are empty");
} else {
let bitmap_size = glyph_bounds.size;
let font = &self.loaded_fonts[params.font_id.0].font;
@@ -469,7 +469,7 @@ impl TryFrom<&FontFeatures> for CosmicFontFeatures {
.0
.as_bytes()
.try_into()
.map_err(|_| anyhow!("Incorrect feature flag format"))?;
.context("Incorrect feature flag format")?;
let tag = cosmic_text::FeatureTag::new(&name_bytes);
@@ -3,6 +3,7 @@ use std::{
hash::{Hash, Hasher},
};
use anyhow::Context as _;
use uuid::Uuid;
use wayland_backend::client::ObjectId;
@@ -28,11 +29,11 @@ impl PlatformDisplay for WaylandDisplay {
}
fn uuid(&self) -> anyhow::Result<Uuid> {
if let Some(name) = &self.name {
Ok(Uuid::new_v5(&Uuid::NAMESPACE_DNS, name.as_bytes()))
} else {
Err(anyhow::anyhow!("Wayland display does not have a name"))
}
let name = self
.name
.as_ref()
.context("Wayland display does not have a name")?;
Ok(Uuid::new_v5(&Uuid::NAMESPACE_DNS, name.as_bytes()))
}
fn bounds(&self) -> Bounds<Pixels> {
@@ -1,4 +1,4 @@
use anyhow::Result;
use anyhow::Context as _;
use uuid::Uuid;
use x11rb::{connection::Connection as _, xcb_ffi::XCBConnection};
@@ -17,12 +17,11 @@ impl X11Display {
scale_factor: f32,
x_screen_index: usize,
) -> anyhow::Result<Self> {
let Some(screen) = xcb.setup().roots.get(x_screen_index) else {
return Err(anyhow::anyhow!(
"No screen found with index {}",
x_screen_index
));
};
let screen = xcb
.setup()
.roots
.get(x_screen_index)
.with_context(|| format!("No screen found with index {x_screen_index}"))?;
Ok(Self {
x_screen_index,
bounds: Bounds {
@@ -42,7 +41,7 @@ impl PlatformDisplay for X11Display {
DisplayId(self.x_screen_index as u32)
}
fn uuid(&self) -> Result<Uuid> {
fn uuid(&self) -> anyhow::Result<Uuid> {
Ok(self.uuid)
}
+2 -2
View File
@@ -2,7 +2,7 @@ use crate::{
AtlasKey, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, DevicePixels, PlatformAtlas,
Point, Size, platform::AtlasTextureList,
};
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result};
use collections::FxHashMap;
use derive_more::{Deref, DerefMut};
use etagere::BucketedAtlasAllocator;
@@ -77,7 +77,7 @@ impl PlatformAtlas for MetalAtlas {
};
let tile = lock
.allocate(size, key.texture_kind())
.ok_or_else(|| anyhow!("failed to allocate"))?;
.context("failed to allocate")?;
let texture = lock.texture(tile.texture_id);
texture.upload(tile.bounds, &bytes);
lock.tiles_by_key.insert(key.clone(), tile.clone());
+11 -11
View File
@@ -4,7 +4,7 @@ use crate::{
MonochromeSprite, PaintSurface, Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch,
Quad, ScaledPixels, Scene, Shadow, Size, Surface, Underline, point, size,
};
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result};
use block::ConcreteBlock;
use cocoa::{
base::{NO, YES},
@@ -376,14 +376,14 @@ impl MetalRenderer {
let command_buffer = command_queue.new_command_buffer();
let mut instance_offset = 0;
let Some(path_tiles) = self.rasterize_paths(
scene.paths(),
instance_buffer,
&mut instance_offset,
command_buffer,
) else {
return Err(anyhow!("failed to rasterize {} paths", scene.paths().len()));
};
let path_tiles = self
.rasterize_paths(
scene.paths(),
instance_buffer,
&mut instance_offset,
command_buffer,
)
.with_context(|| format!("rasterizing {} paths", scene.paths().len()))?;
let render_pass_descriptor = metal::RenderPassDescriptor::new();
let color_attachment = render_pass_descriptor
@@ -471,7 +471,7 @@ impl MetalRenderer {
if !ok {
command_encoder.end_encoding();
return Err(anyhow!(
anyhow::bail!(
"scene too large: {} paths, {} shadows, {} quads, {} underlines, {} mono, {} poly, {} surfaces",
scene.paths.len(),
scene.shadows.len(),
@@ -480,7 +480,7 @@ impl MetalRenderer {
scene.monochrome_sprites.len(),
scene.polychrome_sprites.len(),
scene.surfaces.len(),
));
);
}
}
+22 -40
View File
@@ -638,7 +638,7 @@ impl Platform for MacPlatform {
Ok(())
} else {
let msg: id = msg_send![error, localizedDescription];
Err(anyhow!("Failed to register: {:?}", msg))
Err(anyhow!("Failed to register: {msg:?}"))
};
if let Some(done_tx) = done_tx.take() {
@@ -832,11 +832,8 @@ impl Platform for MacPlatform {
fn app_path(&self) -> Result<PathBuf> {
unsafe {
let bundle: id = NSBundle::mainBundle();
if bundle.is_null() {
Err(anyhow!("app is not running inside a bundle"))
} else {
Ok(path_from_objc(msg_send![bundle, bundlePath]))
}
anyhow::ensure!(!bundle.is_null(), "app is not running inside a bundle");
Ok(path_from_objc(msg_send![bundle, bundlePath]))
}
}
@@ -877,17 +874,11 @@ impl Platform for MacPlatform {
fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
unsafe {
let bundle: id = NSBundle::mainBundle();
if bundle.is_null() {
Err(anyhow!("app is not running inside a bundle"))
} else {
let name = ns_string(name);
let url: id = msg_send![bundle, URLForAuxiliaryExecutable: name];
if url.is_null() {
Err(anyhow!("resource not found"))
} else {
ns_url_to_path(url)
}
}
anyhow::ensure!(!bundle.is_null(), "app is not running inside a bundle");
let name = ns_string(name);
let url: id = msg_send![bundle, URLForAuxiliaryExecutable: name];
anyhow::ensure!(!url.is_null(), "resource not found");
ns_url_to_path(url)
}
}
@@ -1101,10 +1092,7 @@ impl Platform for MacPlatform {
verb = "creating";
status = SecItemAdd(attrs.as_concrete_TypeRef(), ptr::null_mut());
}
if status != errSecSuccess {
return Err(anyhow!("{} password failed: {}", verb, status));
}
anyhow::ensure!(status == errSecSuccess, "{verb} password failed: {status}");
}
Ok(())
})
@@ -1131,24 +1119,24 @@ impl Platform for MacPlatform {
match status {
security::errSecSuccess => {}
security::errSecItemNotFound | security::errSecUserCanceled => return Ok(None),
_ => return Err(anyhow!("reading password failed: {}", status)),
_ => anyhow::bail!("reading password failed: {status}"),
}
let result = CFType::wrap_under_create_rule(result)
.downcast::<CFDictionary>()
.ok_or_else(|| anyhow!("keychain item was not a dictionary"))?;
.context("keychain item was not a dictionary")?;
let username = result
.find(kSecAttrAccount as *const _)
.ok_or_else(|| anyhow!("account was missing from keychain item"))?;
.context("account was missing from keychain item")?;
let username = CFType::wrap_under_get_rule(*username)
.downcast::<CFString>()
.ok_or_else(|| anyhow!("account was not a string"))?;
.context("account was not a string")?;
let password = result
.find(kSecValueData as *const _)
.ok_or_else(|| anyhow!("password was missing from keychain item"))?;
.context("password was missing from keychain item")?;
let password = CFType::wrap_under_get_rule(*password)
.downcast::<CFData>()
.ok_or_else(|| anyhow!("password was not a string"))?;
.context("password was not a string")?;
Ok(Some((username.to_string(), password.bytes().to_vec())))
}
@@ -1168,10 +1156,7 @@ impl Platform for MacPlatform {
query_attrs.set(kSecAttrServer as *const _, url.as_CFTypeRef());
let status = SecItemDelete(query_attrs.as_concrete_TypeRef());
if status != errSecSuccess {
return Err(anyhow!("delete password failed: {}", status));
}
anyhow::ensure!(status == errSecSuccess, "delete password failed: {status}");
}
Ok(())
})
@@ -1455,15 +1440,12 @@ unsafe fn ns_string(string: &str) -> id {
unsafe fn ns_url_to_path(url: id) -> Result<PathBuf> {
let path: *mut c_char = msg_send![url, fileSystemRepresentation];
if path.is_null() {
Err(anyhow!("url is not a file path: {}", unsafe {
CStr::from_ptr(url.absoluteString().UTF8String()).to_string_lossy()
}))
} else {
Ok(PathBuf::from(OsStr::from_bytes(unsafe {
CStr::from_ptr(path).to_bytes()
})))
}
anyhow::ensure!(!path.is_null(), "url is not a file path: {}", unsafe {
CStr::from_ptr(url.absoluteString().UTF8String()).to_string_lossy()
});
Ok(PathBuf::from(OsStr::from_bytes(unsafe {
CStr::from_ptr(path).to_bytes()
})))
}
#[link(name = "Carbon", kind = "framework")]
+2 -2
View File
@@ -194,7 +194,7 @@ impl MacTextSystemState {
core_graphics::data_provider::CGDataProvider::from_slice(embedded_font)
};
let font = core_graphics::font::CGFont::from_data_provider(data_provider)
.map_err(|_| anyhow!("Could not load an embedded font."))?;
.map_err(|()| anyhow!("Could not load an embedded font."))?;
let font = font_kit::loaders::core_text::Font::from_core_graphics_font(font);
Ok(Handle::from_native(&font))
}
@@ -348,7 +348,7 @@ impl MacTextSystemState {
glyph_bounds: Bounds<DevicePixels>,
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
if glyph_bounds.size.width.0 == 0 || glyph_bounds.size.height.0 == 0 {
Err(anyhow!("glyph bounds are empty"))
anyhow::bail!("glyph bounds are empty");
} else {
// Add an extra pixel when the subpixel variant isn't zero to make room for anti-aliasing.
let mut bitmap_size = glyph_bounds.size;
@@ -54,9 +54,7 @@ impl DockMenuItem {
},
action,
}),
_ => Err(anyhow::anyhow!(
"Only `MenuItem::Action` is supported for dock menu on Windows."
)),
_ => anyhow::bail!("Only `MenuItem::Action` is supported for dock menu on Windows."),
}
}
}
@@ -1,7 +1,7 @@
use std::{borrow::Cow, sync::Arc};
use ::util::ResultExt;
use anyhow::{Result, anyhow};
use anyhow::Result;
use collections::HashMap;
use itertools::Itertools;
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
@@ -729,7 +729,7 @@ impl DirectWriteState {
glyph_bounds: Bounds<DevicePixels>,
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
if glyph_bounds.size.width.0 == 0 || glyph_bounds.size.height.0 == 0 {
return Err(anyhow!("glyph bounds are empty"));
anyhow::bail!("glyph bounds are empty");
}
let font_info = &self.fonts[params.font_id.0];
@@ -1301,7 +1301,7 @@ fn get_postscript_name(font_face: &IDWriteFontFace3, locale: &str) -> Result<Str
)?
};
if !exists.as_bool() || info.is_none() {
return Err(anyhow!("No postscript name found for font face"));
anyhow::bail!("No postscript name found for font face");
}
get_name(info.unwrap(), locale)
@@ -1393,9 +1393,7 @@ fn get_name(string: IDWriteLocalizedStrings, locale: &str) -> Result<String> {
&mut exists as _,
)?
};
if !exists.as_bool() {
return Err(anyhow!("No localised string for {}", locale));
}
anyhow::ensure!(exists.as_bool(), "No localised string for {locale}");
}
let name_length = unsafe { string.GetStringLength(locale_name_index) }? as usize;
+1 -1
View File
@@ -576,7 +576,7 @@ impl Platform for WindowsPlatform {
// todo(windows)
fn path_for_auxiliary_executable(&self, _name: &str) -> Result<PathBuf> {
Err(anyhow!("not yet implemented"))
anyhow::bail!("not yet implemented");
}
fn set_cursor_style(&self, style: CursorStyle) {