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,6 +1,5 @@
use std::{path::Path, sync::Arc, time::Duration};
use anyhow::anyhow;
use gpui::{
Animation, AnimationExt, App, Application, Asset, AssetLogger, AssetSource, Bounds, Context,
Hsla, ImageAssetLoader, ImageCacheError, ImgResourceLoader, LOADING_DELAY, Length, Pixels,
@ -57,7 +56,7 @@ impl Asset for LoadImageWithParameters {
timer.await;
if parameters.fail {
log::error!("Intentionally failed to load image");
Err(anyhow!("Failed to load image").into())
Err(anyhow::anyhow!("Failed to load image").into())
} else {
data.await
}

View file

@ -1,5 +1,5 @@
use crate::SharedString;
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result};
use collections::HashMap;
pub use no_action::{NoAction, is_no_action};
use serde_json::json;
@ -235,7 +235,7 @@ impl ActionRegistry {
let name = self
.names_by_type_id
.get(type_id)
.ok_or_else(|| anyhow!("no action type registered for {:?}", type_id))?
.with_context(|| format!("no action type registered for {type_id:?}"))?
.clone();
Ok(self.build_action(&name, None)?)

View file

@ -10,7 +10,7 @@ use std::{
time::Duration,
};
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result, anyhow};
use derive_more::{Deref, DerefMut};
use futures::{
Future, FutureExt,
@ -1021,9 +1021,9 @@ impl App {
let mut window = cx
.windows
.get_mut(id)
.ok_or_else(|| anyhow!("window not found"))?
.context("window not found")?
.take()
.ok_or_else(|| anyhow!("window not found"))?;
.context("window not found")?;
let root_view = window.root.clone().unwrap();
@ -1042,7 +1042,7 @@ impl App {
} else {
cx.windows
.get_mut(id)
.ok_or_else(|| anyhow!("window not found"))?
.context("window not found")?
.replace(window);
}
@ -1119,7 +1119,7 @@ impl App {
self.globals_by_type
.get(&TypeId::of::<G>())
.map(|any_state| any_state.downcast_ref::<G>().unwrap())
.ok_or_else(|| anyhow!("no state of type {} exists", type_name::<G>()))
.with_context(|| format!("no state of type {} exists", type_name::<G>()))
.unwrap()
}
@ -1138,7 +1138,7 @@ impl App {
self.globals_by_type
.get_mut(&global_type)
.and_then(|any_state| any_state.downcast_mut::<G>())
.ok_or_else(|| anyhow!("no state of type {} exists", type_name::<G>()))
.with_context(|| format!("no state of type {} exists", type_name::<G>()))
.unwrap()
}
@ -1201,7 +1201,7 @@ impl App {
GlobalLease::new(
self.globals_by_type
.remove(&TypeId::of::<G>())
.ok_or_else(|| anyhow!("no global registered of type {}", type_name::<G>()))
.with_context(|| format!("no global registered of type {}", type_name::<G>()))
.unwrap(),
)
}
@ -1765,7 +1765,7 @@ impl AppContext for App {
let window = self
.windows
.get(window.id)
.ok_or_else(|| anyhow!("window not found"))?
.context("window not found")?
.as_ref()
.expect("attempted to read a window that is already on the stack");
@ -1915,9 +1915,12 @@ impl HttpClient for NullHttpClient {
_req: http_client::Request<http_client::AsyncBody>,
) -> futures::future::BoxFuture<
'static,
Result<http_client::Response<http_client::AsyncBody>, anyhow::Error>,
anyhow::Result<http_client::Response<http_client::AsyncBody>>,
> {
async move { Err(anyhow!("No HttpClient available")) }.boxed()
async move {
anyhow::bail!("No HttpClient available");
}
.boxed()
}
fn proxy(&self) -> Option<&Url> {

View file

@ -3,7 +3,7 @@ use crate::{
Entity, EventEmitter, Focusable, ForegroundExecutor, Global, PromptLevel, Render, Reservation,
Result, Subscription, Task, VisualContext, Window, WindowHandle,
};
use anyhow::{Context as _, anyhow};
use anyhow::Context as _;
use derive_more::{Deref, DerefMut};
use futures::channel::oneshot;
use std::{future::Future, rc::Weak};
@ -27,19 +27,13 @@ impl AppContext for AsyncApp {
&mut self,
build_entity: impl FnOnce(&mut Context<T>) -> T,
) -> Self::Result<Entity<T>> {
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let mut app = app.borrow_mut();
Ok(app.new(build_entity))
}
fn reserve_entity<T: 'static>(&mut self) -> Result<Reservation<T>> {
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let mut app = app.borrow_mut();
Ok(app.reserve_entity())
}
@ -49,10 +43,7 @@ impl AppContext for AsyncApp {
reservation: Reservation<T>,
build_entity: impl FnOnce(&mut Context<T>) -> T,
) -> Result<Entity<T>> {
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let mut app = app.borrow_mut();
Ok(app.insert_entity(reservation, build_entity))
}
@ -62,10 +53,7 @@ impl AppContext for AsyncApp {
handle: &Entity<T>,
update: impl FnOnce(&mut T, &mut Context<T>) -> R,
) -> Self::Result<R> {
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let mut app = app.borrow_mut();
Ok(app.update_entity(handle, update))
}
@ -125,10 +113,7 @@ impl AppContext for AsyncApp {
impl AsyncApp {
/// Schedules all windows in the application to be redrawn.
pub fn refresh(&self) -> Result<()> {
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let mut lock = app.borrow_mut();
lock.refresh_windows();
Ok(())
@ -146,10 +131,7 @@ impl AsyncApp {
/// Invoke the given function in the context of the app, then flush any effects produced during its invocation.
pub fn update<R>(&self, f: impl FnOnce(&mut App) -> R) -> Result<R> {
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let mut lock = app.borrow_mut();
Ok(lock.update(f))
}
@ -165,10 +147,7 @@ impl AsyncApp {
T: 'static + EventEmitter<Event>,
Event: 'static,
{
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let mut lock = app.borrow_mut();
let subscription = lock.subscribe(entity, on_event);
Ok(subscription)
@ -183,10 +162,7 @@ impl AsyncApp {
where
V: 'static + Render,
{
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let mut lock = app.borrow_mut();
lock.open_window(options, build_root_view)
}
@ -206,10 +182,7 @@ impl AsyncApp {
/// Determine whether global state of the specified type has been assigned.
/// Returns an error if the `App` has been dropped.
pub fn has_global<G: Global>(&self) -> Result<bool> {
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let app = app.borrow_mut();
Ok(app.has_global::<G>())
}
@ -219,10 +192,7 @@ impl AsyncApp {
/// Panics if no global state of the specified type has been assigned.
/// Returns an error if the `App` has been dropped.
pub fn read_global<G: Global, R>(&self, read: impl FnOnce(&G, &App) -> R) -> Result<R> {
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let app = app.borrow_mut();
Ok(read(app.global(), &app))
}
@ -245,10 +215,7 @@ impl AsyncApp {
&self,
update: impl FnOnce(&mut G, &mut App) -> R,
) -> Result<R> {
let app = self
.app
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let app = self.app.upgrade().context("app was released")?;
let mut app = app.borrow_mut();
Ok(app.update(|cx| cx.update_global(update)))
}

View file

@ -1,5 +1,5 @@
use crate::{App, AppContext, VisualContext, Window, seal::Sealed};
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result};
use collections::FxHashSet;
use derive_more::{Deref, DerefMut};
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
@ -692,7 +692,7 @@ impl<T: 'static> WeakEntity<T> {
{
crate::Flatten::flatten(
self.upgrade()
.ok_or_else(|| anyhow!("entity released"))
.context("entity released")
.map(|this| cx.update_entity(&this, update)),
)
}
@ -710,7 +710,7 @@ impl<T: 'static> WeakEntity<T> {
Result<C::Result<R>>: crate::Flatten<R>,
{
let window = cx.window_handle();
let this = self.upgrade().ok_or_else(|| anyhow!("entity released"))?;
let this = self.upgrade().context("entity released")?;
crate::Flatten::flatten(window.update(cx, |_, window, cx| {
this.update(cx, |entity, cx| update(entity, window, cx))
@ -727,7 +727,7 @@ impl<T: 'static> WeakEntity<T> {
{
crate::Flatten::flatten(
self.upgrade()
.ok_or_else(|| anyhow!("entity release"))
.context("entity released")
.map(|this| cx.read_entity(&this, read)),
)
}

View file

@ -1,4 +1,4 @@
use anyhow::{Context, bail};
use anyhow::{Context as _, bail};
use serde::de::{self, Deserialize, Deserializer, Visitor};
use std::{
fmt::{self, Display, Formatter},

View file

@ -5,7 +5,7 @@ use crate::{
SMOOTH_SVG_SCALE_FACTOR, SharedString, SharedUri, StyleRefinement, Styled, SvgSize, Task,
Window, px, swap_rgba_pa_to_bgra,
};
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result};
use futures::{AsyncReadExt, Future};
use image::{
@ -595,7 +595,7 @@ impl Asset for ImageAssetLoader {
let mut response = client
.get(uri.as_ref(), ().into(), true)
.await
.map_err(|e| anyhow!(e))?;
.with_context(|| format!("loading image asset from {uri:?}"))?;
let mut body = Vec::new();
response.body_mut().read_to_end(&mut body).await?;
if !response.status().is_success() {

View file

@ -4,7 +4,7 @@ use crate::{
Pixels, Point, SharedString, Size, TextOverflow, TextRun, TextStyle, TooltipId, WhiteSpace,
Window, WrappedLine, WrappedLineLayout, register_tooltip_mouse_handlers, set_tooltip_on_window,
};
use anyhow::anyhow;
use anyhow::Context as _;
use smallvec::SmallVec;
use std::{
cell::{Cell, RefCell},
@ -401,7 +401,7 @@ impl TextLayout {
let mut element_state = self.0.borrow_mut();
let element_state = element_state
.as_mut()
.ok_or_else(|| anyhow!("measurement has not been performed on {}", text))
.with_context(|| format!("measurement has not been performed on {text}"))
.unwrap();
element_state.bounds = Some(bounds);
}
@ -410,11 +410,11 @@ impl TextLayout {
let element_state = self.0.borrow();
let element_state = element_state
.as_ref()
.ok_or_else(|| anyhow!("measurement has not been performed on {}", text))
.with_context(|| format!("measurement has not been performed on {text}"))
.unwrap();
let bounds = element_state
.bounds
.ok_or_else(|| anyhow!("prepaint has not been performed on {:?}", text))
.with_context(|| format!("prepaint has not been performed on {text}"))
.unwrap();
let line_height = element_state.line_height;

View file

@ -1,5 +1,5 @@
use crate::SharedString;
use anyhow::{Result, anyhow};
use anyhow::{Context as _, Result};
use std::fmt;
/// A datastructure for resolving whether an action should be dispatched
@ -243,7 +243,7 @@ impl KeyBindingContextPredicate {
let source = skip_whitespace(source);
let (predicate, rest) = Self::parse_expr(source, 0)?;
if let Some(next) = rest.chars().next() {
Err(anyhow!("unexpected character '{next:?}'"))
anyhow::bail!("unexpected character '{next:?}'");
} else {
Ok(predicate)
}
@ -329,20 +329,14 @@ impl KeyBindingContextPredicate {
}
fn parse_primary(mut source: &str) -> anyhow::Result<(Self, &str)> {
let next = source
.chars()
.next()
.ok_or_else(|| anyhow!("unexpected end"))?;
let next = source.chars().next().context("unexpected end")?;
match next {
'(' => {
source = skip_whitespace(&source[1..]);
let (predicate, rest) = Self::parse_expr(source, 0)?;
if let Some(stripped) = rest.strip_prefix(')') {
source = skip_whitespace(stripped);
Ok((predicate, source))
} else {
Err(anyhow!("expected a ')'"))
}
let stripped = rest.strip_prefix(')').context("expected a ')'")?;
source = skip_whitespace(stripped);
Ok((predicate, source))
}
'!' => {
let source = skip_whitespace(&source[1..]);
@ -368,7 +362,7 @@ impl KeyBindingContextPredicate {
source,
))
}
_ => Err(anyhow!("unexpected character '{next:?}'")),
_ => anyhow::bail!("unexpected character '{next:?}'"),
}
}
@ -388,7 +382,7 @@ impl KeyBindingContextPredicate {
if let (Self::Identifier(left), Self::Identifier(right)) = (self, other) {
Ok(Self::Equal(left, right))
} else {
Err(anyhow!("operands of == must be identifiers"))
anyhow::bail!("operands of == must be identifiers");
}
}
@ -396,7 +390,7 @@ impl KeyBindingContextPredicate {
if let (Self::Identifier(left), Self::Identifier(right)) = (self, other) {
Ok(Self::NotEqual(left, right))
} else {
Err(anyhow!("operands of != must be identifiers"))
anyhow::bail!("operands of != must be identifiers");
}
}
}

View file

@ -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)]

View file

@ -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 {

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,

View file

@ -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);

View file

@ -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> {

View file

@ -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)
}

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());

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(),
));
);
}
}

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")]

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;

View file

@ -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."),
}
}
}

View file

@ -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;

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) {

View file

@ -1,5 +1,4 @@
use crate::{AssetSource, DevicePixels, IsZero, Result, SharedString, Size};
use anyhow::anyhow;
use resvg::tiny_skia::Pixmap;
use std::{
hash::Hash,
@ -56,9 +55,7 @@ impl SvgRenderer {
}
pub(crate) fn render(&self, params: &RenderSvgParams) -> Result<Option<Vec<u8>>> {
if params.size.is_zero() {
return Err(anyhow!("can't render at a zero size"));
}
anyhow::ensure!(!params.size.is_zero(), "can't render at a zero size");
// Load the tree.
let Some(bytes) = self.asset_source.load(&params.path)? else {

View file

@ -16,7 +16,7 @@ use crate::{
Bounds, DevicePixels, Hsla, Pixels, PlatformTextSystem, Point, Result, SharedString, Size,
StrikethroughStyle, UnderlineStyle, px,
};
use anyhow::anyhow;
use anyhow::{Context as _, anyhow};
use collections::FxHashMap;
use core::fmt;
use derive_more::Deref;
@ -100,7 +100,7 @@ impl TextSystem {
fn clone_font_id_result(font_id: &Result<FontId>) -> Result<FontId> {
match font_id {
Ok(font_id) => Ok(*font_id),
Err(err) => Err(anyhow!("{}", err)),
Err(err) => Err(anyhow!("{err}")),
}
}
@ -174,7 +174,7 @@ impl TextSystem {
let glyph_id = self
.platform_text_system
.glyph_for_char(font_id, character)
.ok_or_else(|| anyhow!("glyph not found for character '{}'", character))?;
.with_context(|| format!("glyph not found for character '{character}'"))?;
let bounds = self
.platform_text_system
.typographic_bounds(font_id, glyph_id)?;
@ -188,7 +188,7 @@ impl TextSystem {
let glyph_id = self
.platform_text_system
.glyph_for_char(font_id, ch)
.ok_or_else(|| anyhow!("glyph not found for character '{}'", ch))?;
.with_context(|| format!("glyph not found for character '{ch}'"))?;
let result = self.platform_text_system.advance(font_id, glyph_id)?
/ self.units_per_em(font_id) as f32;

View file

@ -3922,7 +3922,7 @@ impl<V: 'static + Render> WindowHandle<V> {
.and_then(|window| window.root.clone())
.map(|root_view| root_view.downcast::<V>())
})
.ok_or_else(|| anyhow!("window not found"))?
.context("window not found")?
.map_err(|_| anyhow!("the type of the window's root view has changed"))?;
Ok(x.read(cx))
@ -4103,7 +4103,7 @@ impl TryInto<SharedString> for ElementId {
if let ElementId::Name(name) = self {
Ok(name)
} else {
Err(anyhow!("element id is not string"))
anyhow::bail!("element id is not string")
}
}
}