18325e1ecSAlex Crichton use super::boxed::try_new_uninit_box; 28325e1ecSAlex Crichton use super::context::ContextError; 38325e1ecSAlex Crichton use super::ptr::{MutPtr, OwnedPtr, SharedPtr}; 48325e1ecSAlex Crichton use super::vtable::Vtable; 58325e1ecSAlex Crichton use crate::error::{OutOfMemory, Result}; 68325e1ecSAlex Crichton use core::{ 78325e1ecSAlex Crichton any::TypeId, 88325e1ecSAlex Crichton fmt::{self, Debug}, 98325e1ecSAlex Crichton iter::FusedIterator, 108325e1ecSAlex Crichton mem, 118325e1ecSAlex Crichton ptr::NonNull, 128325e1ecSAlex Crichton }; 138325e1ecSAlex Crichton #[cfg(feature = "backtrace")] 148325e1ecSAlex Crichton use std::backtrace::{Backtrace, BacktraceStatus}; 158325e1ecSAlex Crichton use std_alloc::boxed::Box; 168325e1ecSAlex Crichton 178325e1ecSAlex Crichton /// Internal extension trait for errors. 188325e1ecSAlex Crichton /// 198325e1ecSAlex Crichton /// # Safety 208325e1ecSAlex Crichton /// 218325e1ecSAlex Crichton /// Safety relies on `ext_is` being implemented correctly. Implementations must 228325e1ecSAlex Crichton /// not lie about whether they are or are not an instance of the given type id's 238325e1ecSAlex Crichton /// associated type (or a newtype wrapper around that type). Violations will 248325e1ecSAlex Crichton /// lead to unsafety. 258325e1ecSAlex Crichton pub(crate) unsafe trait ErrorExt: Send + Sync + 'static { 268325e1ecSAlex Crichton /// Get this error as a shared reference to a `dyn core::error::Error` trait 278325e1ecSAlex Crichton /// object. ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static)288325e1ecSAlex Crichton fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static); 298325e1ecSAlex Crichton 308325e1ecSAlex Crichton /// Get this error as a boxed `dyn core::error::Error` trait object. ext_into_boxed_dyn_core_error( self, ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory>318325e1ecSAlex Crichton fn ext_into_boxed_dyn_core_error( 328325e1ecSAlex Crichton self, 338325e1ecSAlex Crichton ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory>; 348325e1ecSAlex Crichton 358325e1ecSAlex Crichton /// Get a shared borrow of the next error in the chain. ext_source(&self) -> Option<&Error>365afb6030SNick Fitzgerald fn ext_source(&self) -> Option<&Error>; 378325e1ecSAlex Crichton 388325e1ecSAlex Crichton /// Get an exclusive borrow of the next error in the chain. ext_source_mut(&mut self) -> Option<&mut Error>395afb6030SNick Fitzgerald fn ext_source_mut(&mut self) -> Option<&mut Error>; 408325e1ecSAlex Crichton 418325e1ecSAlex Crichton /// Is this error an instance of `T`, where `type_id == TypeId::of::<T>()` 428325e1ecSAlex Crichton /// or a newtype wrapper around that type? 438325e1ecSAlex Crichton /// 448325e1ecSAlex Crichton /// # Safety 458325e1ecSAlex Crichton /// 468325e1ecSAlex Crichton /// Implementations must return `true` only when they are actually a `T`, a 478325e1ecSAlex Crichton /// `#[repr(transparent)]` newtype wrapper around a `T`, or a `#[repr(C)]` 488325e1ecSAlex Crichton /// struct with a `T` as their first field. Safety relies on this invariant. ext_is(&self, type_id: TypeId) -> bool498325e1ecSAlex Crichton fn ext_is(&self, type_id: TypeId) -> bool; 508325e1ecSAlex Crichton 518325e1ecSAlex Crichton /// Move the inner `T` error into the storage referenced by `dest`. 528325e1ecSAlex Crichton /// 538325e1ecSAlex Crichton /// # Safety 548325e1ecSAlex Crichton /// 558325e1ecSAlex Crichton /// Callers must ensure that `dest` is valid for writing a `T` to. 568325e1ecSAlex Crichton /// 578325e1ecSAlex Crichton /// Implementations must ensure that the memory block pointed to by `dest` 588325e1ecSAlex Crichton /// contains a valid, initialized `T` upon successful return. ext_move(self, dest: NonNull<u8>)598325e1ecSAlex Crichton unsafe fn ext_move(self, dest: NonNull<u8>); 608325e1ecSAlex Crichton 618325e1ecSAlex Crichton /// Take the backtrace from this error, if any. 628325e1ecSAlex Crichton #[cfg(feature = "backtrace")] take_backtrace(&mut self) -> Option<Backtrace>638325e1ecSAlex Crichton fn take_backtrace(&mut self) -> Option<Backtrace>; 644fd25c07SAlex Crichton 654fd25c07SAlex Crichton /// Conversion into an `anyhow::Error`. 664fd25c07SAlex Crichton #[cfg(feature = "anyhow")] ext_into_anyhow(self) -> anyhow::Error674fd25c07SAlex Crichton fn ext_into_anyhow(self) -> anyhow::Error; 688325e1ecSAlex Crichton } 698325e1ecSAlex Crichton 708325e1ecSAlex Crichton /// Morally a `dyn ErrorExt` trait object that holds its own vtable. 718325e1ecSAlex Crichton /// 728325e1ecSAlex Crichton /// Must only ever be used via some kind of indirection (pointer, reference, 738325e1ecSAlex Crichton /// `Box`, etc...) that is punning a `ConcreteError<?>` and never directly as an 748325e1ecSAlex Crichton /// on-stack value, for example. 758325e1ecSAlex Crichton /// 768325e1ecSAlex Crichton /// See the docs for `Vtable` for details about why we make our own trait 778325e1ecSAlex Crichton /// objects. 788325e1ecSAlex Crichton /// 798325e1ecSAlex Crichton /// XXX: Must have a compatible layout with `ConcreteError<E>`. See the 808325e1ecSAlex Crichton /// assertions in `BoxedDynError::new` and the 818325e1ecSAlex Crichton /// `dyn_error_and_concrete_error_layouts_are_compatible` test below. 828325e1ecSAlex Crichton #[repr(C)] 838325e1ecSAlex Crichton pub(crate) struct DynError { 848325e1ecSAlex Crichton // Safety: this vtable must always be associated with the `E` for the 858325e1ecSAlex Crichton // `ConcreteError<E>` that this `DynError` is punning. 868325e1ecSAlex Crichton pub(crate) vtable: &'static Vtable, 878325e1ecSAlex Crichton #[cfg(feature = "backtrace")] 888325e1ecSAlex Crichton pub(crate) backtrace: Option<Backtrace>, 898325e1ecSAlex Crichton // error: <?> 908325e1ecSAlex Crichton } 918325e1ecSAlex Crichton 928325e1ecSAlex Crichton /// A `dyn ErrorExt` trait object that we know the concrete type of. 938325e1ecSAlex Crichton /// 948325e1ecSAlex Crichton /// XXX: Must have a compatible layout with `DynError`. See the 958325e1ecSAlex Crichton /// assertions in `BoxedDynError::new` and the 968325e1ecSAlex Crichton /// `dyn_error_and_concrete_error_layouts_are_compatible` test below. 978325e1ecSAlex Crichton #[repr(C)] 988325e1ecSAlex Crichton pub(crate) struct ConcreteError<E> { 998325e1ecSAlex Crichton // Safety: this vtable must always be `E`'s vtable. This is ensured in 1008325e1ecSAlex Crichton // `BoxDynError::new`. 1018325e1ecSAlex Crichton pub(crate) vtable: &'static Vtable, 1028325e1ecSAlex Crichton #[cfg(feature = "backtrace")] 1038325e1ecSAlex Crichton pub(crate) backtrace: Option<Backtrace>, 1048325e1ecSAlex Crichton pub(crate) error: E, 1058325e1ecSAlex Crichton } 1068325e1ecSAlex Crichton 1078325e1ecSAlex Crichton pub(crate) struct BoxedDynError { 1088325e1ecSAlex Crichton inner: OwnedPtr<DynError>, 1098325e1ecSAlex Crichton } 1108325e1ecSAlex Crichton 1118325e1ecSAlex Crichton // Safety: `BoxedDynError::new` ensures that every concrete error type we make a 1128325e1ecSAlex Crichton // `BoxedDynError` from is `Send`. 1138325e1ecSAlex Crichton unsafe impl Send for BoxedDynError {} 1148325e1ecSAlex Crichton 1158325e1ecSAlex Crichton // Safety: `BoxedDynError::new` ensures that every concrete error type we make a 1168325e1ecSAlex Crichton // `BoxedDynError` from is `Sync`. 1178325e1ecSAlex Crichton unsafe impl Sync for BoxedDynError {} 1188325e1ecSAlex Crichton 1198325e1ecSAlex Crichton impl Drop for BoxedDynError { drop(&mut self)1208325e1ecSAlex Crichton fn drop(&mut self) { 1218325e1ecSAlex Crichton let ptr = self.inner.raw_copy(); 1228325e1ecSAlex Crichton // Safety: We own the pointer and it is valid for reading/writing 1238325e1ecSAlex Crichton // `DynError`s. 1248325e1ecSAlex Crichton let inner = unsafe { ptr.as_ref() }; 1258325e1ecSAlex Crichton let vtable = inner.vtable; 1268325e1ecSAlex Crichton // Safety: The vtable is for this pointer's concrete type and the 1278325e1ecSAlex Crichton // pointer is valid to deallocate because we are passing ownership in. 1288325e1ecSAlex Crichton unsafe { 1298325e1ecSAlex Crichton (vtable.drop_and_deallocate)(ptr); 1308325e1ecSAlex Crichton } 1318325e1ecSAlex Crichton } 1328325e1ecSAlex Crichton } 1338325e1ecSAlex Crichton 1348325e1ecSAlex Crichton impl BoxedDynError { 1358325e1ecSAlex Crichton #[inline] new<E>(mut error: E) -> Result<Self, OutOfMemory> where E: ErrorExt,1368325e1ecSAlex Crichton fn new<E>(mut error: E) -> Result<Self, OutOfMemory> 1378325e1ecSAlex Crichton where 1388325e1ecSAlex Crichton // NB: This implies `Send + Sync`, which is necessary for safety. 1398325e1ecSAlex Crichton E: ErrorExt, 1408325e1ecSAlex Crichton { 1418325e1ecSAlex Crichton #[cfg(not(feature = "backtrace"))] 1428325e1ecSAlex Crichton let _ = &mut error; 1438325e1ecSAlex Crichton 1448325e1ecSAlex Crichton // Note: do not use `Option::or_else` here to avoid an extra frame 1458325e1ecSAlex Crichton // showing up in the backtrace, which would create extra noise for users 1468325e1ecSAlex Crichton // to mentally filter out. 1478325e1ecSAlex Crichton #[cfg(feature = "backtrace")] 1488325e1ecSAlex Crichton let backtrace = match error.take_backtrace() { 1498325e1ecSAlex Crichton Some(bt) => bt, 1508325e1ecSAlex Crichton None => crate::error::backtrace::capture(), 1518325e1ecSAlex Crichton }; 1528325e1ecSAlex Crichton 1538325e1ecSAlex Crichton let boxed = try_new_uninit_box()?; 1548325e1ecSAlex Crichton let error = Box::write( 1558325e1ecSAlex Crichton boxed, 1568325e1ecSAlex Crichton ConcreteError { 1578325e1ecSAlex Crichton vtable: Vtable::of::<E>(), 1588325e1ecSAlex Crichton #[cfg(feature = "backtrace")] 1598325e1ecSAlex Crichton backtrace: Some(backtrace), 1608325e1ecSAlex Crichton error, 1618325e1ecSAlex Crichton }, 1628325e1ecSAlex Crichton ); 1638325e1ecSAlex Crichton 1648325e1ecSAlex Crichton // We are going to pun the `ConcreteError<E>` pointer into a `DynError` 1658325e1ecSAlex Crichton // pointer. Debug assert that their layouts are compatible first. 1668325e1ecSAlex Crichton #[cfg(debug_assertions)] 1678325e1ecSAlex Crichton { 1688325e1ecSAlex Crichton let dyn_size = mem::size_of::<DynError>(); 1698325e1ecSAlex Crichton let concrete_size = mem::size_of::<ConcreteError<E>>(); 1708325e1ecSAlex Crichton assert!( 1718325e1ecSAlex Crichton dyn_size <= concrete_size, 1728325e1ecSAlex Crichton "assertion failed: {dyn_size} <= {concrete_size}" 1738325e1ecSAlex Crichton ); 1748325e1ecSAlex Crichton 1758325e1ecSAlex Crichton let dyn_align = mem::align_of::<DynError>(); 1768325e1ecSAlex Crichton let concrete_align = mem::align_of::<ConcreteError<E>>(); 1778325e1ecSAlex Crichton assert!( 1788325e1ecSAlex Crichton dyn_align <= concrete_align, 1798325e1ecSAlex Crichton "assertion failed: {dyn_align} <= {concrete_align}" 1808325e1ecSAlex Crichton ); 1818325e1ecSAlex Crichton 1828325e1ecSAlex Crichton let dyn_offset = mem::offset_of!(DynError, vtable); 1838325e1ecSAlex Crichton let concrete_offset = mem::offset_of!(ConcreteError<E>, vtable); 1848325e1ecSAlex Crichton assert_eq!(dyn_offset, concrete_offset); 1858325e1ecSAlex Crichton 1868325e1ecSAlex Crichton #[cfg(feature = "backtrace")] 1878325e1ecSAlex Crichton { 1888325e1ecSAlex Crichton let dyn_offset = mem::offset_of!(DynError, backtrace); 1898325e1ecSAlex Crichton let concrete_offset = mem::offset_of!(ConcreteError<E>, backtrace); 1908325e1ecSAlex Crichton assert_eq!(dyn_offset, concrete_offset); 1918325e1ecSAlex Crichton } 1928325e1ecSAlex Crichton } 1938325e1ecSAlex Crichton 1948325e1ecSAlex Crichton let ptr = Box::into_raw(error); 1958325e1ecSAlex Crichton let ptr = ptr.cast::<DynError>(); 1968325e1ecSAlex Crichton // Safety: `Box::into_raw` always returns a non-null pointer. 1978325e1ecSAlex Crichton let ptr = unsafe { NonNull::new_unchecked(ptr) }; 1988325e1ecSAlex Crichton let ptr = OwnedPtr::new(ptr); 1998325e1ecSAlex Crichton // Safety: points to a valid `DynError`. 2008325e1ecSAlex Crichton Ok(unsafe { Self::from_owned_ptr(ptr) }) 2018325e1ecSAlex Crichton } 2028325e1ecSAlex Crichton into_owned_ptr(self) -> OwnedPtr<DynError>2038325e1ecSAlex Crichton fn into_owned_ptr(self) -> OwnedPtr<DynError> { 2048325e1ecSAlex Crichton let ptr = self.inner.raw_copy(); 2058325e1ecSAlex Crichton mem::forget(self); 2068325e1ecSAlex Crichton ptr 2078325e1ecSAlex Crichton } 2088325e1ecSAlex Crichton 2098325e1ecSAlex Crichton /// # Safety 2108325e1ecSAlex Crichton /// 2118325e1ecSAlex Crichton /// The given pointer must be a valid `DynError` pointer: punning a 2128325e1ecSAlex Crichton /// `ConcreteError<?>` and is safe to drop and deallocate with its 2138325e1ecSAlex Crichton /// `DynError::vtable` methods. from_owned_ptr(inner: OwnedPtr<DynError>) -> Self2148325e1ecSAlex Crichton unsafe fn from_owned_ptr(inner: OwnedPtr<DynError>) -> Self { 2158325e1ecSAlex Crichton BoxedDynError { inner } 2168325e1ecSAlex Crichton } 2178325e1ecSAlex Crichton } 2188325e1ecSAlex Crichton 2198325e1ecSAlex Crichton /// Wasmtime's universal error type. 2208325e1ecSAlex Crichton /// 2218325e1ecSAlex Crichton /// 99% API-compatible with `anyhow::Error` but additionally allows recovery 2228325e1ecSAlex Crichton /// from memory exhaustion (see the [`OutOfMemory`] error). 2238325e1ecSAlex Crichton /// 2248325e1ecSAlex Crichton /// `Error` is similar to `Box<dyn core::error::Error + Send + Sync + 'static>` 2258325e1ecSAlex Crichton /// but fits in one word instead of two. Additionally, `Result<(), Error>` also 2268325e1ecSAlex Crichton /// fits in a single word. 2278325e1ecSAlex Crichton /// 2288325e1ecSAlex Crichton /// When the `"backtrace"` cargo feature is enabled, `Error` contains a 2298325e1ecSAlex Crichton /// backtrace. 2308325e1ecSAlex Crichton /// 2318325e1ecSAlex Crichton /// # Creating an `Error` 2328325e1ecSAlex Crichton /// 2338325e1ecSAlex Crichton /// Because `Error` implements `From<E>` for all types `E` that implement 2348325e1ecSAlex Crichton /// `core::error::Error + Send + Sync + 'static`, you don't usually need to 2358325e1ecSAlex Crichton /// explicitly construct an `Error`. When you use `?`-style error propagation, 2368325e1ecSAlex Crichton /// it will automatically get constructed from the root cause error for you. 2378325e1ecSAlex Crichton /// 2388325e1ecSAlex Crichton /// Most often when creating an `Error`, you just want to early-exit from the 239bc4582c3SAlex Crichton /// function, returning `Err(...)`. The [`ensure!`](crate::ensure) macro 2408325e1ecSAlex Crichton /// early-returns an error when a condition is not met (similar to how `assert!` 241bc4582c3SAlex Crichton /// panics when a condition is not met) and the [`bail!`](crate::bail) macro 2428325e1ecSAlex Crichton /// early-returns an error unconditionally. 2438325e1ecSAlex Crichton /// 2448325e1ecSAlex Crichton /// ``` 2458325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 2468325e1ecSAlex Crichton /// use wasmtime::{bail, ensure, Result}; 2478325e1ecSAlex Crichton /// 2488325e1ecSAlex Crichton /// fn my_fallible_function(x: u32) -> Result<()> { 2498325e1ecSAlex Crichton /// // This `ensure!` macro invocation is equivalent to 2508325e1ecSAlex Crichton /// // 2518325e1ecSAlex Crichton /// // if x % 2 != 0 { 2528325e1ecSAlex Crichton /// // return Err(...); 2538325e1ecSAlex Crichton /// // } 2548325e1ecSAlex Crichton /// ensure!(x % 2 == 0, "{x} is not even!"); 2558325e1ecSAlex Crichton /// 2568325e1ecSAlex Crichton /// // This `bail!` macro invocation is equivalent to 2578325e1ecSAlex Crichton /// // 2588325e1ecSAlex Crichton /// // return Err(...); 2598325e1ecSAlex Crichton /// bail!("oops, another error! {x}") 2608325e1ecSAlex Crichton /// } 2618325e1ecSAlex Crichton /// ``` 2628325e1ecSAlex Crichton /// 2638325e1ecSAlex Crichton /// If you do not want to early-return, just to create the `Error`, then the 264bc4582c3SAlex Crichton /// [`format_err!`](crate::format_err) macro is preferred: 2658325e1ecSAlex Crichton /// 2668325e1ecSAlex Crichton /// ``` 2678325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 2688325e1ecSAlex Crichton /// use wasmtime::{format_err, Error}; 2698325e1ecSAlex Crichton /// 2708325e1ecSAlex Crichton /// let x = 42; 2718325e1ecSAlex Crichton /// let my_error: Error = format_err!("whoops! {x}"); 2728325e1ecSAlex Crichton /// ``` 2738325e1ecSAlex Crichton /// 2748325e1ecSAlex Crichton /// If, however, you happen to require a constructor function instead of a 2758325e1ecSAlex Crichton /// macro, you can use either [`Error::new`] or [`Error::msg`]: 2768325e1ecSAlex Crichton /// 2778325e1ecSAlex Crichton /// ``` 2788325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 2798325e1ecSAlex Crichton /// use wasmtime::Error; 2808325e1ecSAlex Crichton /// 2818325e1ecSAlex Crichton /// let messages = ["yikes", "uh oh", "ouch"]; 2828325e1ecSAlex Crichton /// let errors = messages 2838325e1ecSAlex Crichton /// .into_iter() 2848325e1ecSAlex Crichton /// .map(Error::msg) 2858325e1ecSAlex Crichton /// .collect::<Vec<_>>(); 2868325e1ecSAlex Crichton /// ``` 2878325e1ecSAlex Crichton /// 2888325e1ecSAlex Crichton /// # Printing an `Error` 2898325e1ecSAlex Crichton /// 2908325e1ecSAlex Crichton /// Different format strings will print an `Error` differently: 2918325e1ecSAlex Crichton /// 2928325e1ecSAlex Crichton /// * `{}`: Prints the `Display` of just the first error, without any of the 2938325e1ecSAlex Crichton /// other errors in the chain or the root cause. 2948325e1ecSAlex Crichton /// 2958325e1ecSAlex Crichton /// * `{:#}`: Prints the `Display` of the first error, then (if there are more 2968325e1ecSAlex Crichton /// errors in the chain) a colon, then the display of the second error in the 2978325e1ecSAlex Crichton /// chain, etc... 2988325e1ecSAlex Crichton /// 2998325e1ecSAlex Crichton /// * `{:?}`: Prints the `Display` of the first error, then (if there are more 3008325e1ecSAlex Crichton /// errors in the chain) a newline-separated list of the rest of the errors in 3018325e1ecSAlex Crichton /// the chain, and finally (if the `"backtrace"` cargo feature is enabled, the 3028325e1ecSAlex Crichton /// `RUST_BACKTRACE` environment variable is set and non-zero, and the 3038325e1ecSAlex Crichton /// platform is supported by Rust's standard library's `Backtrace` type) the 3048325e1ecSAlex Crichton /// captured backtrace is printed. 3058325e1ecSAlex Crichton /// 3068325e1ecSAlex Crichton /// This is the default formatting used when `fn main() -> 3078325e1ecSAlex Crichton /// wasmtime::Result<()>` returns an error. 3088325e1ecSAlex Crichton /// 3098325e1ecSAlex Crichton /// * `{:#?}`: Prints an internal, debugging representation of the `Error`. We 3108325e1ecSAlex Crichton /// make no guarantees about its stability. 3118325e1ecSAlex Crichton /// 3128325e1ecSAlex Crichton /// Here is an example showing the different formats for the same error: 3138325e1ecSAlex Crichton /// 3148325e1ecSAlex Crichton /// ``` 3158325e1ecSAlex Crichton /// # fn _foo() { 3168325e1ecSAlex Crichton /// #![cfg(all(feature = "backtrace", not(miri)))] 3178325e1ecSAlex Crichton /// # let _ = unsafe { std::env::set_var("RUST_BACKTRACE", "1") }; 3188325e1ecSAlex Crichton /// # use wasmtime_internal_core as wasmtime; 3198325e1ecSAlex Crichton /// use wasmtime::error::{bail, Context as _, Result}; 3208325e1ecSAlex Crichton /// 3218325e1ecSAlex Crichton /// fn uno() -> Result<()> { 3228325e1ecSAlex Crichton /// bail!("ouch") 3238325e1ecSAlex Crichton /// } 3248325e1ecSAlex Crichton /// 3258325e1ecSAlex Crichton /// fn dos() -> Result<()> { 3268325e1ecSAlex Crichton /// uno().context("whoops") 3278325e1ecSAlex Crichton /// } 3288325e1ecSAlex Crichton /// 3298325e1ecSAlex Crichton /// fn tres() -> Result<()> { 3308325e1ecSAlex Crichton /// dos().context("uh oh") 3318325e1ecSAlex Crichton /// } 3328325e1ecSAlex Crichton /// 3338325e1ecSAlex Crichton /// let error = tres().unwrap_err(); 3348325e1ecSAlex Crichton /// 3358325e1ecSAlex Crichton /// println!("{error}"); 3368325e1ecSAlex Crichton /// // Prints: 3378325e1ecSAlex Crichton /// // 3388325e1ecSAlex Crichton /// // uh oh 3398325e1ecSAlex Crichton /// 3408325e1ecSAlex Crichton /// println!("{error:#}"); 3418325e1ecSAlex Crichton /// // Prints: 3428325e1ecSAlex Crichton /// // 3438325e1ecSAlex Crichton /// // uh oh: whoops: ouch 3448325e1ecSAlex Crichton /// 3458325e1ecSAlex Crichton /// println!("{error:?}"); 3468325e1ecSAlex Crichton /// // Prints 3478325e1ecSAlex Crichton /// // 3488325e1ecSAlex Crichton /// // uh oh 3498325e1ecSAlex Crichton /// // 3508325e1ecSAlex Crichton /// // Caused by: 3518325e1ecSAlex Crichton /// // 0: whoops 3528325e1ecSAlex Crichton /// // 1: ouch 3538325e1ecSAlex Crichton /// // 3548325e1ecSAlex Crichton /// // Stack backtrace: 3558325e1ecSAlex Crichton /// // <...> 3568325e1ecSAlex Crichton /// // 7: example::uno 3578325e1ecSAlex Crichton /// // 8: example::dos 3588325e1ecSAlex Crichton /// // 9: example::tres 3598325e1ecSAlex Crichton /// // 10: example::main 3608325e1ecSAlex Crichton /// // <...> 3618325e1ecSAlex Crichton /// 3628325e1ecSAlex Crichton /// println!("{error:#?}"); 3638325e1ecSAlex Crichton /// // Prints 3648325e1ecSAlex Crichton /// // 3658325e1ecSAlex Crichton /// // Error { 3668325e1ecSAlex Crichton /// // <...> 3678325e1ecSAlex Crichton /// // } 3688325e1ecSAlex Crichton /// # } 3698325e1ecSAlex Crichton /// ``` 3708325e1ecSAlex Crichton /// 3718325e1ecSAlex Crichton /// # Converting a `wasmtime::Error` into an `anyhow::Error` 3728325e1ecSAlex Crichton /// 3738325e1ecSAlex Crichton /// When the `"anyhow"` feature is enabled, there is a `From<wasmtime::Error> 3748325e1ecSAlex Crichton /// for anyhow::Error` implementation. You can always call that implementation 3758325e1ecSAlex Crichton /// explicitly if needed, but `?`-propagation allows the conversion to happen 3768325e1ecSAlex Crichton /// seamlessly from functions that return a `Result<T, wasmtime::Error>` to 3778325e1ecSAlex Crichton /// those that return a `Result<U, anyhow::Error>`. 3788325e1ecSAlex Crichton /// 3798325e1ecSAlex Crichton /// ``` 3808325e1ecSAlex Crichton /// # fn _foo() { 3818325e1ecSAlex Crichton /// #![cfg(feature = "anyhow")] 3828325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 3838325e1ecSAlex Crichton /// 3848325e1ecSAlex Crichton /// fn foo() -> Result<(), wasmtime::Error> { 3858325e1ecSAlex Crichton /// wasmtime::bail!("decontamination failure") 3868325e1ecSAlex Crichton /// } 3878325e1ecSAlex Crichton /// 3888325e1ecSAlex Crichton /// fn bar() -> Result<(), anyhow::Error> { 3898325e1ecSAlex Crichton /// foo()?; // `?` is auto-converting here! 3908325e1ecSAlex Crichton /// Ok(()) 3918325e1ecSAlex Crichton /// } 3928325e1ecSAlex Crichton /// 3938325e1ecSAlex Crichton /// let error = bar().unwrap_err(); 3948325e1ecSAlex Crichton /// assert_eq!(error.to_string(), "decontamination failure"); 3958325e1ecSAlex Crichton /// # } 3968325e1ecSAlex Crichton /// ``` 3978325e1ecSAlex Crichton /// 3988325e1ecSAlex Crichton /// # Converting an `anyhow::Error` into a `wasmtime::Error` 3998325e1ecSAlex Crichton /// 4008325e1ecSAlex Crichton /// When the `"anyhow"` feature is enabled, there is an `Error::from_anyhow` 4018325e1ecSAlex Crichton /// constructor that you may use to convert an `anyhow::Error` into a 4028325e1ecSAlex Crichton /// `wasmtime::Error`. (Unfortunately trait coherence does not allow us a 4038325e1ecSAlex Crichton /// `From<anyhow::Error> for wasmtime::Error` implementation.) This will 4048325e1ecSAlex Crichton /// most-often be used in combination with `Result::map_err`: 4058325e1ecSAlex Crichton /// 4068325e1ecSAlex Crichton /// ``` 4078325e1ecSAlex Crichton /// # fn _foo() { 4088325e1ecSAlex Crichton /// #![cfg(feature = "anyhow")] 4098325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 4108325e1ecSAlex Crichton /// 4118325e1ecSAlex Crichton /// fn baz() -> Result<(), anyhow::Error> { 4128325e1ecSAlex Crichton /// anyhow::bail!("oops I ate worms") 4138325e1ecSAlex Crichton /// } 4148325e1ecSAlex Crichton /// 4158325e1ecSAlex Crichton /// fn qux() -> Result<(), wasmtime::Error> { 4168325e1ecSAlex Crichton /// baz().map_err(wasmtime::Error::from_anyhow)?; 4178325e1ecSAlex Crichton /// Ok(()) 4188325e1ecSAlex Crichton /// } 4198325e1ecSAlex Crichton /// 4208325e1ecSAlex Crichton /// let error = qux().unwrap_err(); 4218325e1ecSAlex Crichton /// assert_eq!(error.to_string(), "oops I ate worms"); 4228325e1ecSAlex Crichton /// # } 4238325e1ecSAlex Crichton /// ``` 4248325e1ecSAlex Crichton #[repr(transparent)] 4258325e1ecSAlex Crichton pub struct Error { 4268325e1ecSAlex Crichton pub(crate) inner: OomOrDynError, 4278325e1ecSAlex Crichton } 4288325e1ecSAlex Crichton 4298325e1ecSAlex Crichton /// For performance, it is important that `Error` and `Result<()>` fit in a 4308325e1ecSAlex Crichton /// single word so that they can be passed in registers by rustc/llvm, rather 4318325e1ecSAlex Crichton /// than on the stack, when used as a function's return type. 4328325e1ecSAlex Crichton const _ERROR_IS_ONE_WORD_LARGE: () = assert!(mem::size_of::<Error>() == mem::size_of::<usize>()); 4338325e1ecSAlex Crichton const _RESULT_OF_UNIT_IS_ONE_WORD_LARGE: () = 4348325e1ecSAlex Crichton assert!(mem::size_of::<Result<()>>() == mem::size_of::<usize>()); 4358325e1ecSAlex Crichton 4368325e1ecSAlex Crichton impl fmt::Debug for Error { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result4378325e1ecSAlex Crichton fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 4388325e1ecSAlex Crichton if f.alternate() { 4395afb6030SNick Fitzgerald return f.debug_struct("Error").field("inner", &self.inner).finish(); 4408325e1ecSAlex Crichton } 4418325e1ecSAlex Crichton 4425afb6030SNick Fitzgerald let inner = &self.inner; 4438325e1ecSAlex Crichton inner.display(f)?; 4448325e1ecSAlex Crichton 4458325e1ecSAlex Crichton if let Some(source) = inner.source() { 4468325e1ecSAlex Crichton f.write_str("\n\nCaused by:\n")?; 4478325e1ecSAlex Crichton let multiple_causes = source.source().is_some(); 4485afb6030SNick Fitzgerald for (i, e) in source.chain().enumerate() { 4498325e1ecSAlex Crichton if multiple_causes { 4508325e1ecSAlex Crichton write!(f, "{i: >5}: ")?; 4518325e1ecSAlex Crichton } else { 4528325e1ecSAlex Crichton write!(f, " ")?; 4538325e1ecSAlex Crichton } 4548325e1ecSAlex Crichton writeln!(f, "{e}")?; 4558325e1ecSAlex Crichton } 4568325e1ecSAlex Crichton } 4578325e1ecSAlex Crichton 4588325e1ecSAlex Crichton #[cfg(feature = "backtrace")] 4598325e1ecSAlex Crichton { 4608325e1ecSAlex Crichton let backtrace = inner.backtrace(); 4618325e1ecSAlex Crichton if let BacktraceStatus::Captured = backtrace.status() { 4628325e1ecSAlex Crichton f.write_str("\nStack backtrace:\n")?; 4638325e1ecSAlex Crichton fmt::Display::fmt(backtrace, f)?; 4648325e1ecSAlex Crichton } 4658325e1ecSAlex Crichton } 4668325e1ecSAlex Crichton 4678325e1ecSAlex Crichton Ok(()) 4688325e1ecSAlex Crichton } 4698325e1ecSAlex Crichton } 4708325e1ecSAlex Crichton 4718325e1ecSAlex Crichton impl fmt::Display for Error { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result4728325e1ecSAlex Crichton fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 4735afb6030SNick Fitzgerald let inner = &self.inner; 4748325e1ecSAlex Crichton inner.display(f)?; 4758325e1ecSAlex Crichton 4768325e1ecSAlex Crichton if f.alternate() { 4778325e1ecSAlex Crichton if let Some(e) = inner.source() { 4785afb6030SNick Fitzgerald for e in e.chain() { 4798325e1ecSAlex Crichton write!(f, ": {e}")?; 4808325e1ecSAlex Crichton } 4818325e1ecSAlex Crichton } 4828325e1ecSAlex Crichton } 4838325e1ecSAlex Crichton 4848325e1ecSAlex Crichton Ok(()) 4858325e1ecSAlex Crichton } 4868325e1ecSAlex Crichton } 4878325e1ecSAlex Crichton 4888325e1ecSAlex Crichton impl<E> From<E> for Error 4898325e1ecSAlex Crichton where 4908325e1ecSAlex Crichton E: core::error::Error + Send + Sync + 'static, 4918325e1ecSAlex Crichton { from(error: E) -> Self4928325e1ecSAlex Crichton fn from(error: E) -> Self { 4938325e1ecSAlex Crichton Self::new(error) 4948325e1ecSAlex Crichton } 4958325e1ecSAlex Crichton } 4968325e1ecSAlex Crichton 4978325e1ecSAlex Crichton impl From<Error> for Box<dyn core::error::Error + Send + Sync + 'static> { 4988325e1ecSAlex Crichton #[inline] from(error: Error) -> Self4998325e1ecSAlex Crichton fn from(error: Error) -> Self { 5008325e1ecSAlex Crichton error.into_boxed_dyn_error() 5018325e1ecSAlex Crichton } 5028325e1ecSAlex Crichton } 5038325e1ecSAlex Crichton 5048325e1ecSAlex Crichton impl From<Error> for Box<dyn core::error::Error + Send + 'static> { 5058325e1ecSAlex Crichton #[inline] from(error: Error) -> Self5068325e1ecSAlex Crichton fn from(error: Error) -> Self { 5078325e1ecSAlex Crichton error.into_boxed_dyn_error() 5088325e1ecSAlex Crichton } 5098325e1ecSAlex Crichton } 5108325e1ecSAlex Crichton 5118325e1ecSAlex Crichton impl From<Error> for Box<dyn core::error::Error + 'static> { 5128325e1ecSAlex Crichton #[inline] from(error: Error) -> Self5138325e1ecSAlex Crichton fn from(error: Error) -> Self { 5148325e1ecSAlex Crichton error.into_boxed_dyn_error() 5158325e1ecSAlex Crichton } 5168325e1ecSAlex Crichton } 5178325e1ecSAlex Crichton 518bc4582c3SAlex Crichton /// Convert a [`wasmtime::Error`](Error) into an [`anyhow::Error`]. 5198325e1ecSAlex Crichton /// 5208325e1ecSAlex Crichton /// # Example 5218325e1ecSAlex Crichton /// 5228325e1ecSAlex Crichton /// ``` 5238325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 5248325e1ecSAlex Crichton /// let wasmtime_error = wasmtime::Error::msg("whoops"); 5258325e1ecSAlex Crichton /// let anyhow_error = anyhow::Error::from(wasmtime_error); 5268325e1ecSAlex Crichton /// ``` 5278325e1ecSAlex Crichton // 5288325e1ecSAlex Crichton // Unfortunately, we can't also implement `From<anyhow::Error> for Error` 5298325e1ecSAlex Crichton // because of trait coherence. From Rust's trait system's point of view, 5308325e1ecSAlex Crichton // `anyhow` could theoretically add an `core::error::Error for anyhow::Error` 5318325e1ecSAlex Crichton // implementation, which would make our desired `From<anyhow::Error>` 5328325e1ecSAlex Crichton // implementation conflict with our existing `From<E: core::error::Error>` 5338325e1ecSAlex Crichton // implementation. They cannot in fact add that implementation, however, because 5348325e1ecSAlex Crichton // they already have a `From<E: core::error::Error> for anyhow::Error` 5358325e1ecSAlex Crichton // implementation and so adding `core::error::Error for anyhow::Error` would 5368325e1ecSAlex Crichton // cause that impl to conflict with `From<T> for T` (which is the same reason we 5378325e1ecSAlex Crichton // cannot implement `core::error::Error for Error`). Nonetheless, our hands are 5388325e1ecSAlex Crichton // tied here. 5398325e1ecSAlex Crichton #[cfg(feature = "anyhow")] 5408325e1ecSAlex Crichton impl From<Error> for anyhow::Error { 5418325e1ecSAlex Crichton #[inline] from(e: Error) -> Self5428325e1ecSAlex Crichton fn from(e: Error) -> Self { 5434fd25c07SAlex Crichton e.inner.into_anyhow() 5448325e1ecSAlex Crichton } 5458325e1ecSAlex Crichton } 5468325e1ecSAlex Crichton 5478325e1ecSAlex Crichton impl core::ops::Deref for Error { 5488325e1ecSAlex Crichton type Target = dyn core::error::Error + Send + Sync + 'static; 5498325e1ecSAlex Crichton deref(&self) -> &Self::Target5508325e1ecSAlex Crichton fn deref(&self) -> &Self::Target { 5518325e1ecSAlex Crichton self.as_ref() 5528325e1ecSAlex Crichton } 5538325e1ecSAlex Crichton } 5548325e1ecSAlex Crichton 5558325e1ecSAlex Crichton impl AsRef<dyn core::error::Error> for Error { 5568325e1ecSAlex Crichton #[inline] as_ref(&self) -> &(dyn core::error::Error + 'static)5578325e1ecSAlex Crichton fn as_ref(&self) -> &(dyn core::error::Error + 'static) { 5585afb6030SNick Fitzgerald self.inner.as_dyn_core_error() 5598325e1ecSAlex Crichton } 5608325e1ecSAlex Crichton } 5618325e1ecSAlex Crichton 5628325e1ecSAlex Crichton impl AsRef<dyn core::error::Error + Send + Sync> for Error { 5638325e1ecSAlex Crichton #[inline] as_ref(&self) -> &(dyn core::error::Error + Send + Sync + 'static)5648325e1ecSAlex Crichton fn as_ref(&self) -> &(dyn core::error::Error + Send + Sync + 'static) { 5655afb6030SNick Fitzgerald self.inner.as_dyn_core_error() 5668325e1ecSAlex Crichton } 5678325e1ecSAlex Crichton } 5688325e1ecSAlex Crichton 5698325e1ecSAlex Crichton impl Error { 5708325e1ecSAlex Crichton /// Construct a new `Error` from a type that implements 5718325e1ecSAlex Crichton /// `core::error::Error`. 5728325e1ecSAlex Crichton /// 573bc4582c3SAlex Crichton /// Calling [`error.is::<E>()`](Error::is) will return `true` for the new 5748325e1ecSAlex Crichton /// error (unless there was a memory allocation failure). 5758325e1ecSAlex Crichton /// 5768325e1ecSAlex Crichton /// This boxes the inner error, but if that box allocation fails, then this 5778325e1ecSAlex Crichton /// function returns an `Error` where 578bc4582c3SAlex Crichton /// [`error.is::<OutOfMemory>()`](OutOfMemory) is true. 5798325e1ecSAlex Crichton /// 5808325e1ecSAlex Crichton /// # Example 5818325e1ecSAlex Crichton /// 5828325e1ecSAlex Crichton /// ``` 5838325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 5848325e1ecSAlex Crichton /// use wasmtime::Error; 5858325e1ecSAlex Crichton /// 5868325e1ecSAlex Crichton /// let error = Error::new(std::fmt::Error); 5878325e1ecSAlex Crichton /// ``` new<E>(error: E) -> Self where E: core::error::Error + Send + Sync + 'static,5888325e1ecSAlex Crichton pub fn new<E>(error: E) -> Self 5898325e1ecSAlex Crichton where 5908325e1ecSAlex Crichton E: core::error::Error + Send + Sync + 'static, 5918325e1ecSAlex Crichton { 5928325e1ecSAlex Crichton if TypeId::of::<E>() == TypeId::of::<OutOfMemory>() { 5938325e1ecSAlex Crichton // Although we know that `E == OutOfMemory` in this block, the 594*ab78bd82SHo Kim // compiler doesn't understand that, and we have to do this little 5958325e1ecSAlex Crichton // dance. 5968325e1ecSAlex Crichton union ToOom<T> { 5978325e1ecSAlex Crichton oom: OutOfMemory, 5988325e1ecSAlex Crichton error: mem::ManuallyDrop<T>, 5998325e1ecSAlex Crichton } 6008325e1ecSAlex Crichton let error = mem::ManuallyDrop::new(error); 6018325e1ecSAlex Crichton // Safety: `E == OutOfMemory`. 6028325e1ecSAlex Crichton let oom = unsafe { (ToOom { error }).oom }; 6038325e1ecSAlex Crichton return Error { inner: oom.into() }; 6048325e1ecSAlex Crichton } 6058325e1ecSAlex Crichton 6068325e1ecSAlex Crichton Self::from_error_ext(ForeignError(error)) 6078325e1ecSAlex Crichton } 6088325e1ecSAlex Crichton 6098325e1ecSAlex Crichton /// Construct a new `Error` from any type that implements `Debug` and 6108325e1ecSAlex Crichton /// `Display`. 6118325e1ecSAlex Crichton /// 612bc4582c3SAlex Crichton /// Calling [`error.is::<M>()`](Error::is) will return `true` for the new 6138325e1ecSAlex Crichton /// error (unless there was a memory allocation failure). 6148325e1ecSAlex Crichton /// 6158325e1ecSAlex Crichton /// This boxes the inner `M` type, but if that box allocation fails, then 6168325e1ecSAlex Crichton /// this function returns an `Error` where 617bc4582c3SAlex Crichton /// [`error.is::<OutOfMemory>()`](OutOfMemory) is true. 6188325e1ecSAlex Crichton /// 6198325e1ecSAlex Crichton /// # Example 6208325e1ecSAlex Crichton /// 6218325e1ecSAlex Crichton /// ``` 6228325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 6238325e1ecSAlex Crichton /// use wasmtime::Error; 6248325e1ecSAlex Crichton /// 6258325e1ecSAlex Crichton /// let error = Error::msg("hello"); 6268325e1ecSAlex Crichton /// ``` msg<M>(message: M) -> Self where M: fmt::Debug + fmt::Display + Send + Sync + 'static,6278325e1ecSAlex Crichton pub fn msg<M>(message: M) -> Self 6288325e1ecSAlex Crichton where 6298325e1ecSAlex Crichton M: fmt::Debug + fmt::Display + Send + Sync + 'static, 6308325e1ecSAlex Crichton { 6318325e1ecSAlex Crichton Self::from_error_ext(MessageError(message)) 6328325e1ecSAlex Crichton } 6338325e1ecSAlex Crichton 6348325e1ecSAlex Crichton /// Create an `Error` from a `Box<dyn core::error::Error>`. 6358325e1ecSAlex Crichton /// 6368325e1ecSAlex Crichton /// This is useful when converting errors from other universal-error 6378325e1ecSAlex Crichton /// libraries into this crate's `Error` type. Prefer [`Error::from_anyhow`] 6388325e1ecSAlex Crichton /// for converting `anyhow::Error`s into `Error`s, as that preserves 6398325e1ecSAlex Crichton /// `error.is::<anyhow::Error>()`. 6408325e1ecSAlex Crichton /// 6418325e1ecSAlex Crichton /// Calling [`error.is::<Box<dyn core::error::Error + Send + Sync + 642bc4582c3SAlex Crichton /// 'static>>()`](Error::is) will return `true` for the new error (unless 6438325e1ecSAlex Crichton /// there was a memory allocation failure). 6448325e1ecSAlex Crichton /// 6458325e1ecSAlex Crichton /// This reboxes the inner error, but if that box allocation fails, then 6468325e1ecSAlex Crichton /// this function returns an `Error` where 647bc4582c3SAlex Crichton /// [`error.is::<OutOfMemory>()`](OutOfMemory) is true. 6488325e1ecSAlex Crichton /// 6498325e1ecSAlex Crichton /// # Example 6508325e1ecSAlex Crichton /// 6518325e1ecSAlex Crichton /// ``` 6528325e1ecSAlex Crichton /// # fn _foo() { 6538325e1ecSAlex Crichton /// #![cfg(all(feature = "std", feature = "anyhow"))] 6548325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 6558325e1ecSAlex Crichton /// use std::error::Error; 6568325e1ecSAlex Crichton /// 6578325e1ecSAlex Crichton /// // You happen to have a boxed error trait object. 6588325e1ecSAlex Crichton /// let orig_error = std::fs::read("XXX: some file that doesn't exist").unwrap_err(); 6598325e1ecSAlex Crichton /// let boxed_error: Box<dyn Error + Send + Sync + 'static> = Box::new(orig_error) as _; 6608325e1ecSAlex Crichton /// 6618325e1ecSAlex Crichton /// // You can turn it into a `wasmtime::Error` via `from_boxed`. 6628325e1ecSAlex Crichton /// let wasmtime_error = wasmtime::Error::from_boxed(boxed_error); 6638325e1ecSAlex Crichton /// # } 6648325e1ecSAlex Crichton /// ``` from_boxed(error: Box<dyn core::error::Error + Send + Sync + 'static>) -> Self6658325e1ecSAlex Crichton pub fn from_boxed(error: Box<dyn core::error::Error + Send + Sync + 'static>) -> Self { 6668325e1ecSAlex Crichton Self::from_error_ext(BoxedError(error)) 6678325e1ecSAlex Crichton } 6688325e1ecSAlex Crichton 6698325e1ecSAlex Crichton /// Convert an `anyhow::Error` into an `Error`. 6708325e1ecSAlex Crichton /// 671bc4582c3SAlex Crichton /// Calling [`error.is::<anyhow::Error>()`](Error::is) will return `true` 6728325e1ecSAlex Crichton /// for the new error (unless there was a memory allocation failure). 6738325e1ecSAlex Crichton /// 6748325e1ecSAlex Crichton /// This reboxes the `anyhow::Error`, but if that box allocation fails, then 6758325e1ecSAlex Crichton /// this function returns an `Error` where 676bc4582c3SAlex Crichton /// [`error.is::<OutOfMemory>()`](OutOfMemory) is true. 6778325e1ecSAlex Crichton /// 6788325e1ecSAlex Crichton /// # Example 6798325e1ecSAlex Crichton /// 6808325e1ecSAlex Crichton /// ``` 6818325e1ecSAlex Crichton /// # fn _foo() { 6828325e1ecSAlex Crichton /// #![cfg(all(feature = "std", feature = "anyhow"))] 6838325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 6848325e1ecSAlex Crichton /// let anyhow_error = anyhow::Error::msg("failed to flim the flam"); 6858325e1ecSAlex Crichton /// let wasmtime_error = wasmtime::Error::from_anyhow(anyhow_error); 6868325e1ecSAlex Crichton /// assert_eq!( 6878325e1ecSAlex Crichton /// wasmtime_error.to_string(), 6888325e1ecSAlex Crichton /// "failed to flim the flam", 6898325e1ecSAlex Crichton /// ); 6908325e1ecSAlex Crichton /// # } 6918325e1ecSAlex Crichton /// ``` 6928325e1ecSAlex Crichton #[cfg(feature = "anyhow")] 6938325e1ecSAlex Crichton #[inline] from_anyhow(error: anyhow::Error) -> Self6948325e1ecSAlex Crichton pub fn from_anyhow(error: anyhow::Error) -> Self { 6958325e1ecSAlex Crichton Self::from_error_ext(AnyhowError(error)) 6968325e1ecSAlex Crichton } 6978325e1ecSAlex Crichton 6988325e1ecSAlex Crichton /// Add additional context to this error. 6998325e1ecSAlex Crichton /// 7008325e1ecSAlex Crichton /// The new context will show up first in the error chain, and the original 7018325e1ecSAlex Crichton /// error will come next. 7028325e1ecSAlex Crichton /// 7038325e1ecSAlex Crichton /// This is similar to the [`Context::context`] trait method, but because it 7048325e1ecSAlex Crichton /// is a method directly on [`Error`], there is no need for lazily-computing 7058325e1ecSAlex Crichton /// the error context (like `with_context` does). 7068325e1ecSAlex Crichton /// 707bc4582c3SAlex Crichton /// Calling [`error.is::<C>()`](Error::is) will return `true` for the new 7088325e1ecSAlex Crichton /// error (unless there was a memory allocation failure) in addition to any 7098325e1ecSAlex Crichton /// other types `T` for which it was already the case that 7108325e1ecSAlex Crichton /// `error.is::<T>()`. 7118325e1ecSAlex Crichton /// 7128325e1ecSAlex Crichton /// This boxes the inner `C` type, but if that box allocation fails, then 7138325e1ecSAlex Crichton /// this function returns an `Error` where 714bc4582c3SAlex Crichton /// [`error.is::<OutOfMemory>()`](OutOfMemory) is true. 715bc4582c3SAlex Crichton /// 716bc4582c3SAlex Crichton /// [`Context::context`]: crate::error::Context::context 7178325e1ecSAlex Crichton /// 7188325e1ecSAlex Crichton /// # Example 7198325e1ecSAlex Crichton /// 7208325e1ecSAlex Crichton /// ``` 7218325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 7228325e1ecSAlex Crichton /// use wasmtime::Error; 7238325e1ecSAlex Crichton /// 7248325e1ecSAlex Crichton /// let error = Error::msg("root cause"); 7258325e1ecSAlex Crichton /// let error = error.context("failed to bonkinate"); 7268325e1ecSAlex Crichton /// let error = error.context("cannot frob the blobbins"); 7278325e1ecSAlex Crichton /// 7288325e1ecSAlex Crichton /// assert!( 7298325e1ecSAlex Crichton /// format!("{error:?}").contains( 7308325e1ecSAlex Crichton /// r#" 7318325e1ecSAlex Crichton /// cannot frob the blobbins 7328325e1ecSAlex Crichton /// 7338325e1ecSAlex Crichton /// Caused by: 7348325e1ecSAlex Crichton /// 0: failed to bonkinate 7358325e1ecSAlex Crichton /// 1: root cause 7368325e1ecSAlex Crichton /// "#.trim(), 7378325e1ecSAlex Crichton /// ), 7388325e1ecSAlex Crichton /// ); 7398325e1ecSAlex Crichton /// ``` context<C>(self, context: C) -> Self where C: fmt::Display + Send + Sync + 'static,7408325e1ecSAlex Crichton pub fn context<C>(self, context: C) -> Self 7418325e1ecSAlex Crichton where 7428325e1ecSAlex Crichton C: fmt::Display + Send + Sync + 'static, 7438325e1ecSAlex Crichton { 7448325e1ecSAlex Crichton if self.inner.is_oom() { 7458325e1ecSAlex Crichton self 7468325e1ecSAlex Crichton } else { 7478325e1ecSAlex Crichton Self::from_error_ext(ContextError { 7488325e1ecSAlex Crichton context, 7498325e1ecSAlex Crichton error: Some(self), 7508325e1ecSAlex Crichton }) 7518325e1ecSAlex Crichton } 7528325e1ecSAlex Crichton } 7538325e1ecSAlex Crichton 7548325e1ecSAlex Crichton #[inline] from_error_ext(error: impl ErrorExt) -> Self7558325e1ecSAlex Crichton pub(crate) fn from_error_ext(error: impl ErrorExt) -> Self { 7568325e1ecSAlex Crichton match BoxedDynError::new(error) { 7578325e1ecSAlex Crichton Ok(boxed) => Error { 7588325e1ecSAlex Crichton inner: boxed.into(), 7598325e1ecSAlex Crichton }, 7608325e1ecSAlex Crichton Err(oom) => Error { inner: oom.into() }, 7618325e1ecSAlex Crichton } 7628325e1ecSAlex Crichton } 7638325e1ecSAlex Crichton 7648325e1ecSAlex Crichton /// Get this error's backtrace. 7658325e1ecSAlex Crichton /// 7668325e1ecSAlex Crichton /// Backtraces will be automatically captured on initial `Error` creation 7678325e1ecSAlex Crichton /// when all of the following conditions are met: 7688325e1ecSAlex Crichton /// 7698325e1ecSAlex Crichton /// * This crate's `"backtrace"` cargo feature is enabled 7708325e1ecSAlex Crichton /// * Rust's `std::backtrace::Backtrace` supports the platform 7718325e1ecSAlex Crichton /// * The `RUST_BACKTRACE` or `RUST_LIB_BACKTRACE` environment variables 7728325e1ecSAlex Crichton /// are set and non-zero 7738325e1ecSAlex Crichton /// 7748325e1ecSAlex Crichton /// See [the `std::backtrace::Backtrace` 7758325e1ecSAlex Crichton /// documentation](https://doc.rust-lang.org/stable/std/backtrace/struct.Backtrace.html) 7768325e1ecSAlex Crichton /// for more details on backtraces. 7778325e1ecSAlex Crichton /// 7788325e1ecSAlex Crichton /// Note that `std::backtrace::Backtrace` does not provide a 7798325e1ecSAlex Crichton /// fallible-capture mechanism that returns an error, rather than aborting 7808325e1ecSAlex Crichton /// the process, when it encounters memory exhaustion. If you require 7818325e1ecSAlex Crichton /// out-of-memory error handling, do not enable this crate's `"backtrace"` 7828325e1ecSAlex Crichton /// cargo feature. 7838325e1ecSAlex Crichton /// 7848325e1ecSAlex Crichton /// # Example 7858325e1ecSAlex Crichton /// 7868325e1ecSAlex Crichton /// ``` 7878325e1ecSAlex Crichton /// # fn _foo() { 7888325e1ecSAlex Crichton /// #![cfg(feature = "backtrace")] 7898325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 7908325e1ecSAlex Crichton /// use std::backtrace::BacktraceStatus; 7918325e1ecSAlex Crichton /// use wasmtime::Error; 7928325e1ecSAlex Crichton /// 7938325e1ecSAlex Crichton /// let error = Error::msg("whoops"); 7948325e1ecSAlex Crichton /// 7958325e1ecSAlex Crichton /// let backtrace = error.backtrace(); 7968325e1ecSAlex Crichton /// if let BacktraceStatus::Captured = backtrace.status() { 7978325e1ecSAlex Crichton /// println!("error backtrace is:\n{backtrace}"); 7988325e1ecSAlex Crichton /// } 7998325e1ecSAlex Crichton /// # } 8008325e1ecSAlex Crichton /// ``` 8018325e1ecSAlex Crichton #[inline] 8028325e1ecSAlex Crichton #[cfg(feature = "backtrace")] backtrace(&self) -> &Backtrace8038325e1ecSAlex Crichton pub fn backtrace(&self) -> &Backtrace { 8045afb6030SNick Fitzgerald self.inner.backtrace() 8058325e1ecSAlex Crichton } 8068325e1ecSAlex Crichton 8078325e1ecSAlex Crichton /// Iterate over this error's context chain. 8088325e1ecSAlex Crichton /// 8098325e1ecSAlex Crichton /// The iterator yields `&(dyn core::error::Error + 'static)` items. 8108325e1ecSAlex Crichton /// 8118325e1ecSAlex Crichton /// Iterates from the most recently added error context towards the root 8128325e1ecSAlex Crichton /// cause. 8138325e1ecSAlex Crichton /// 8148325e1ecSAlex Crichton /// # Example 8158325e1ecSAlex Crichton /// 8168325e1ecSAlex Crichton /// ``` 8178325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 8188325e1ecSAlex Crichton /// use wasmtime::Error; 8198325e1ecSAlex Crichton /// 8208325e1ecSAlex Crichton /// let error = Error::msg("root cause"); 8218325e1ecSAlex Crichton /// let error = error.context("failed to reticulate splines"); 8228325e1ecSAlex Crichton /// let error = error.context("aborting launch"); 8238325e1ecSAlex Crichton /// 8248325e1ecSAlex Crichton /// let messages: Vec<_> = error.chain().map(|e| e.to_string()).collect(); 8258325e1ecSAlex Crichton /// assert_eq!( 8268325e1ecSAlex Crichton /// messages, 8278325e1ecSAlex Crichton /// ["aborting launch", "failed to reticulate splines", "root cause"], 8288325e1ecSAlex Crichton /// ); 8298325e1ecSAlex Crichton /// ``` 8308325e1ecSAlex Crichton #[inline] chain(&self) -> Chain<'_>8318325e1ecSAlex Crichton pub fn chain(&self) -> Chain<'_> { 8325afb6030SNick Fitzgerald Chain::new(self) 8338325e1ecSAlex Crichton } 8348325e1ecSAlex Crichton 8358325e1ecSAlex Crichton /// Get the last error in the context chain. 8368325e1ecSAlex Crichton /// 8378325e1ecSAlex Crichton /// # Example 8388325e1ecSAlex Crichton /// 8398325e1ecSAlex Crichton /// ``` 8408325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 8418325e1ecSAlex Crichton /// use wasmtime::Error; 8428325e1ecSAlex Crichton /// 8438325e1ecSAlex Crichton /// let error = Error::msg("ghosts"); 8448325e1ecSAlex Crichton /// let error = error.context("failed to reticulate splines"); 8458325e1ecSAlex Crichton /// let error = error.context("aborting launch"); 8468325e1ecSAlex Crichton /// 8478325e1ecSAlex Crichton /// assert_eq!( 8488325e1ecSAlex Crichton /// error.root_cause().to_string(), 8498325e1ecSAlex Crichton /// "ghosts", 8508325e1ecSAlex Crichton /// ); 8518325e1ecSAlex Crichton /// ``` 8528325e1ecSAlex Crichton #[inline] root_cause(&self) -> &(dyn core::error::Error + 'static)8538325e1ecSAlex Crichton pub fn root_cause(&self) -> &(dyn core::error::Error + 'static) { 8548325e1ecSAlex Crichton self.chain().last().expect("chain is always non-empty") 8558325e1ecSAlex Crichton } 8568325e1ecSAlex Crichton 8575afb6030SNick Fitzgerald #[inline] error_ext_chain<'a>(&'a self) -> impl Iterator<Item = &'a Error> + 'a8585afb6030SNick Fitzgerald fn error_ext_chain<'a>(&'a self) -> impl Iterator<Item = &'a Error> + 'a { 8595afb6030SNick Fitzgerald let mut cur = Some(self); 8605afb6030SNick Fitzgerald core::iter::from_fn(move || { 8615afb6030SNick Fitzgerald let ret = cur.take()?; 8625afb6030SNick Fitzgerald cur = ret.inner.source(); 8635afb6030SNick Fitzgerald Some(ret) 8645afb6030SNick Fitzgerald }) 8655afb6030SNick Fitzgerald } 8665afb6030SNick Fitzgerald 8675afb6030SNick Fitzgerald #[inline] error_ext_chain_mut<T>( &mut self, mut f: impl FnMut(&mut Error) -> Option<&mut T>, ) -> Option<&mut T>8685afb6030SNick Fitzgerald fn error_ext_chain_mut<T>( 8695afb6030SNick Fitzgerald &mut self, 8705afb6030SNick Fitzgerald mut f: impl FnMut(&mut Error) -> Option<&mut T>, 8715afb6030SNick Fitzgerald ) -> Option<&mut T> { 8725afb6030SNick Fitzgerald let mut cur = self; 8735afb6030SNick Fitzgerald loop { 8745afb6030SNick Fitzgerald { 8755afb6030SNick Fitzgerald // Safety: We are running into "problem case #3" of non-lexical 8765afb6030SNick Fitzgerald // lifetimes: we are returning a mutable reference, which must 8775afb6030SNick Fitzgerald // be live for the whole function's scope, but accessing it 8785afb6030SNick Fitzgerald // again below in `cur.inner.source_mut()`. This is safe because 8795afb6030SNick Fitzgerald // control flow ensures that the borrow is not actually active 8805afb6030SNick Fitzgerald // anymore in the case where we didn't return. 8815afb6030SNick Fitzgerald // 8825afb6030SNick Fitzgerald // https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md#problem-case-3-conditional-control-flow-across-functions 8835afb6030SNick Fitzgerald let cur = unsafe { NonNull::from(&mut *cur).as_mut() }; 8845afb6030SNick Fitzgerald if let Some(x) = f(cur) { 8855afb6030SNick Fitzgerald return Some(x); 8865afb6030SNick Fitzgerald } 8875afb6030SNick Fitzgerald } 8885afb6030SNick Fitzgerald 8895afb6030SNick Fitzgerald cur = cur.inner.source_mut()?; 8905afb6030SNick Fitzgerald } 8915afb6030SNick Fitzgerald } 8925afb6030SNick Fitzgerald 8935afb6030SNick Fitzgerald #[inline] error_ext_zip<T>(mut self, mut f: impl FnMut(Error) -> Result<T, Error>) -> Result<T, Self>8945afb6030SNick Fitzgerald fn error_ext_zip<T>(mut self, mut f: impl FnMut(Error) -> Result<T, Error>) -> Result<T, Self> { 8955afb6030SNick Fitzgerald let mut maybe_link = Some(&mut self); 8965afb6030SNick Fitzgerald while let Some(link) = maybe_link.take() { 8975afb6030SNick Fitzgerald let e = mem::replace(link, OutOfMemory::new(1).into()); 8985afb6030SNick Fitzgerald *link = match f(e) { 8995afb6030SNick Fitzgerald Ok(x) => return Ok(x), 9005afb6030SNick Fitzgerald Err(e) => e, 9015afb6030SNick Fitzgerald }; 9025afb6030SNick Fitzgerald maybe_link = link.inner.source_mut(); 9035afb6030SNick Fitzgerald } 9045afb6030SNick Fitzgerald Err(self) 9055afb6030SNick Fitzgerald } 9065afb6030SNick Fitzgerald 9078325e1ecSAlex Crichton /// Is this an `E` error? 9088325e1ecSAlex Crichton /// 9098325e1ecSAlex Crichton /// Returns true if any error in the context chain is an `E`. 9108325e1ecSAlex Crichton /// 9118325e1ecSAlex Crichton /// # Example 9128325e1ecSAlex Crichton /// 9138325e1ecSAlex Crichton /// ``` 9148325e1ecSAlex Crichton /// # use wasmtime_internal_core as wasmtime; 9158325e1ecSAlex Crichton /// use wasmtime::error::{Error, OutOfMemory}; 9168325e1ecSAlex Crichton /// 9178325e1ecSAlex Crichton /// let oom = Error::from(OutOfMemory::new(1234)); 9188325e1ecSAlex Crichton /// assert!(oom.is::<OutOfMemory>()); 9198325e1ecSAlex Crichton /// assert!(!oom.is::<std::num::TryFromIntError>()); 9208325e1ecSAlex Crichton /// 9218325e1ecSAlex Crichton /// // Here is an example with additional error context. 9228325e1ecSAlex Crichton /// let error = Error::from(u8::try_from(u32::MAX).unwrap_err()); 9238325e1ecSAlex Crichton /// let error = error.context(format!("cannot convert {} into a u8", u32::MAX)); 9248325e1ecSAlex Crichton /// assert!( 9258325e1ecSAlex Crichton /// error.is::<std::num::TryFromIntError>(), 9268325e1ecSAlex Crichton /// "root cause is an int conversion failure", 9278325e1ecSAlex Crichton /// ); 9288325e1ecSAlex Crichton /// assert!( 9298325e1ecSAlex Crichton /// error.is::<String>(), 9308325e1ecSAlex Crichton /// "additional context is a `String`", 9318325e1ecSAlex Crichton /// ); 9328325e1ecSAlex Crichton /// assert!( 9338325e1ecSAlex Crichton /// !error.is::<OutOfMemory>(), 9348325e1ecSAlex Crichton /// "no error in the chain is an out-of-memory error", 9358325e1ecSAlex Crichton /// ); 9368325e1ecSAlex Crichton /// ``` is<E>(&self) -> bool where E: fmt::Display + fmt::Debug + Send + Sync + 'static,9378325e1ecSAlex Crichton pub fn is<E>(&self) -> bool 9388325e1ecSAlex Crichton where 9398325e1ecSAlex Crichton E: fmt::Display + fmt::Debug + Send + Sync + 'static, 9408325e1ecSAlex Crichton { 9415afb6030SNick Fitzgerald self.error_ext_chain().any(|e| { 9425afb6030SNick Fitzgerald let result = e.inner.is::<E>(); 9435afb6030SNick Fitzgerald 9445afb6030SNick Fitzgerald #[cfg(feature = "anyhow")] 9455afb6030SNick Fitzgerald let result = result 9465afb6030SNick Fitzgerald || e.inner 9475afb6030SNick Fitzgerald .downcast_ref::<anyhow::Error>() 9485afb6030SNick Fitzgerald .is_some_and(|e| e.is::<E>()); 9495afb6030SNick Fitzgerald 9505afb6030SNick Fitzgerald result 9515afb6030SNick Fitzgerald }) 9528325e1ecSAlex Crichton } 9538325e1ecSAlex Crichton 9548325e1ecSAlex Crichton /// Downcast this error into an `E`, taking ownership. 9558325e1ecSAlex Crichton /// 9568325e1ecSAlex Crichton /// If this error is an `E`, then `Ok(E)` is returned. Otherwise, 9578325e1ecSAlex Crichton /// `Err(self)` is returned. 9588325e1ecSAlex Crichton /// 9598325e1ecSAlex Crichton /// If there are multiple instances of `E` in this error's chain, then the 9608325e1ecSAlex Crichton /// first (as encountered by [`Error::chain`]'s iteration order) is 9618325e1ecSAlex Crichton /// returned. 9628325e1ecSAlex Crichton /// 9638325e1ecSAlex Crichton /// # Example 9648325e1ecSAlex Crichton /// 9658325e1ecSAlex Crichton /// ``` 9668325e1ecSAlex Crichton /// # use wasmtime_internal_core as wasmtime; 9678325e1ecSAlex Crichton /// use wasmtime::error::{Error, OutOfMemory}; 9688325e1ecSAlex Crichton /// 9698325e1ecSAlex Crichton /// let error = Error::msg("whoops"); 9708325e1ecSAlex Crichton /// 9718325e1ecSAlex Crichton /// // `error` is not an `OutOfMemory`. 9728325e1ecSAlex Crichton /// let downcasted = error.downcast::<OutOfMemory>(); 9738325e1ecSAlex Crichton /// assert!(downcasted.is_err()); 9748325e1ecSAlex Crichton /// 9758325e1ecSAlex Crichton /// // Get the original `error` back. 9768325e1ecSAlex Crichton /// let error = downcasted.unwrap_err(); 9778325e1ecSAlex Crichton /// 9788325e1ecSAlex Crichton /// // `error` is an `&str`. 9798325e1ecSAlex Crichton /// let downcasted = error.downcast::<&str>(); 9808325e1ecSAlex Crichton /// assert!(downcasted.is_ok()); 9818325e1ecSAlex Crichton /// assert_eq!(downcasted.unwrap(), "whoops"); 9828325e1ecSAlex Crichton /// 9838325e1ecSAlex Crichton /// // If there are multiple `E`s in the chain, the first in the chain is 9848325e1ecSAlex Crichton /// // returned. 9858325e1ecSAlex Crichton /// let error = Error::msg("root cause"); 9868325e1ecSAlex Crichton /// let error = error.context("failed to recombobulate"); 9878325e1ecSAlex Crichton /// assert_eq!( 9888325e1ecSAlex Crichton /// error.downcast::<&str>().unwrap(), 9898325e1ecSAlex Crichton /// "failed to recombobulate", 9908325e1ecSAlex Crichton /// ); 9918325e1ecSAlex Crichton /// ``` downcast<E>(self) -> Result<E, Self> where E: fmt::Display + fmt::Debug + Send + Sync + 'static,9928325e1ecSAlex Crichton pub fn downcast<E>(self) -> Result<E, Self> 9938325e1ecSAlex Crichton where 9948325e1ecSAlex Crichton E: fmt::Display + fmt::Debug + Send + Sync + 'static, 9958325e1ecSAlex Crichton { 9965afb6030SNick Fitzgerald self.error_ext_zip(|e| { 9975afb6030SNick Fitzgerald let result = e.inner.downcast::<E>().map_err(|inner| Self { inner }); 9985afb6030SNick Fitzgerald 9995afb6030SNick Fitzgerald #[cfg(feature = "anyhow")] 10005afb6030SNick Fitzgerald let result = result.or_else(|e| { 10015afb6030SNick Fitzgerald if e.inner 10025afb6030SNick Fitzgerald .downcast_ref::<anyhow::Error>() 10035afb6030SNick Fitzgerald .is_some_and(|e| e.is::<E>()) 10045afb6030SNick Fitzgerald { 10055afb6030SNick Fitzgerald let anyhow = match e.inner.downcast::<anyhow::Error>() { 10065afb6030SNick Fitzgerald Ok(e) => e, 10075afb6030SNick Fitzgerald Err(_) => unreachable!(), 10085afb6030SNick Fitzgerald }; 10095afb6030SNick Fitzgerald Ok(anyhow.downcast::<E>().unwrap()) 10105afb6030SNick Fitzgerald } else { 10115afb6030SNick Fitzgerald Err(e) 10128325e1ecSAlex Crichton } 10135afb6030SNick Fitzgerald }); 10148325e1ecSAlex Crichton 10155afb6030SNick Fitzgerald result 10165afb6030SNick Fitzgerald }) 10178325e1ecSAlex Crichton } 10188325e1ecSAlex Crichton 10198325e1ecSAlex Crichton /// Downcast this error into a shared `&E` borrow. 10208325e1ecSAlex Crichton /// 10218325e1ecSAlex Crichton /// If this error is an `E`, then `Some(&E)` is returned. Otherwise, `None` 10228325e1ecSAlex Crichton /// is returned. 10238325e1ecSAlex Crichton /// 10248325e1ecSAlex Crichton /// If there are multiple instances of `E` in this error's chain, then the 10258325e1ecSAlex Crichton /// first (as encountered by [`Error::chain`]'s iteration order) is 10268325e1ecSAlex Crichton /// returned. 10278325e1ecSAlex Crichton /// 10288325e1ecSAlex Crichton /// # Example 10298325e1ecSAlex Crichton /// 10308325e1ecSAlex Crichton /// ``` 10318325e1ecSAlex Crichton /// # use wasmtime_internal_core as wasmtime; 10328325e1ecSAlex Crichton /// use wasmtime::error::{Error, OutOfMemory}; 10338325e1ecSAlex Crichton /// 10348325e1ecSAlex Crichton /// let error = Error::msg("whoops"); 10358325e1ecSAlex Crichton /// 10368325e1ecSAlex Crichton /// // `error` is not an `OutOfMemory`. 10378325e1ecSAlex Crichton /// assert!(error.downcast_ref::<OutOfMemory>().is_none()); 10388325e1ecSAlex Crichton /// 10398325e1ecSAlex Crichton /// // `error` is an `&str`. 10408325e1ecSAlex Crichton /// assert!(error.downcast_ref::<&str>().is_some()); 10418325e1ecSAlex Crichton /// assert_eq!(*error.downcast_ref::<&str>().unwrap(), "whoops"); 10428325e1ecSAlex Crichton /// 10438325e1ecSAlex Crichton /// // If there are multiple `E`s in the chain, the first in the chain is 10448325e1ecSAlex Crichton /// // returned. 10458325e1ecSAlex Crichton /// let error = Error::msg("root cause"); 10468325e1ecSAlex Crichton /// let error = error.context("failed to recombobulate"); 10478325e1ecSAlex Crichton /// assert_eq!( 10488325e1ecSAlex Crichton /// *error.downcast_ref::<&str>().unwrap(), 10498325e1ecSAlex Crichton /// "failed to recombobulate", 10508325e1ecSAlex Crichton /// ); 10518325e1ecSAlex Crichton /// ``` downcast_ref<E>(&self) -> Option<&E> where E: fmt::Display + fmt::Debug + Send + Sync + 'static,10528325e1ecSAlex Crichton pub fn downcast_ref<E>(&self) -> Option<&E> 10538325e1ecSAlex Crichton where 10548325e1ecSAlex Crichton E: fmt::Display + fmt::Debug + Send + Sync + 'static, 10558325e1ecSAlex Crichton { 10565afb6030SNick Fitzgerald self.error_ext_chain().find_map(|e| { 10575afb6030SNick Fitzgerald let result = e.inner.downcast_ref::<E>(); 10585afb6030SNick Fitzgerald 10595afb6030SNick Fitzgerald #[cfg(feature = "anyhow")] 10605afb6030SNick Fitzgerald let result = result.or_else(|| { 10615afb6030SNick Fitzgerald e.inner 10625afb6030SNick Fitzgerald .downcast_ref::<anyhow::Error>() 10635afb6030SNick Fitzgerald .and_then(|anyhow| anyhow.downcast_ref::<E>()) 10648325e1ecSAlex Crichton }); 10655afb6030SNick Fitzgerald 10665afb6030SNick Fitzgerald result 10675afb6030SNick Fitzgerald }) 10688325e1ecSAlex Crichton } 10698325e1ecSAlex Crichton 10708325e1ecSAlex Crichton /// Downcast this error into an exclusive `&mut E` borrow. 10718325e1ecSAlex Crichton /// 10728325e1ecSAlex Crichton /// If this error is an `E`, then `Some(&mut E)` is returned. Otherwise, 10738325e1ecSAlex Crichton /// `None` is returned. 10748325e1ecSAlex Crichton /// 10758325e1ecSAlex Crichton /// If there are multiple instances of `E` in this error's chain, then the 10768325e1ecSAlex Crichton /// first (as encountered by [`Error::chain`]'s iteration order) is 10778325e1ecSAlex Crichton /// returned. 10788325e1ecSAlex Crichton /// 10798325e1ecSAlex Crichton /// # Example 10808325e1ecSAlex Crichton /// 10818325e1ecSAlex Crichton /// ``` 10828325e1ecSAlex Crichton /// # use wasmtime_internal_core as wasmtime; 10838325e1ecSAlex Crichton /// use wasmtime::error::{Error, OutOfMemory}; 10848325e1ecSAlex Crichton /// 10858325e1ecSAlex Crichton /// let mut error = Error::msg("whoops"); 10868325e1ecSAlex Crichton /// 10878325e1ecSAlex Crichton /// // `error` is not an `OutOfMemory`. 10888325e1ecSAlex Crichton /// assert!(error.downcast_mut::<OutOfMemory>().is_none()); 10898325e1ecSAlex Crichton /// 10908325e1ecSAlex Crichton /// // `error` is an `&str`. 10918325e1ecSAlex Crichton /// assert!(error.downcast_mut::<&str>().is_some()); 10928325e1ecSAlex Crichton /// assert_eq!(*error.downcast_mut::<&str>().unwrap(), "whoops"); 10938325e1ecSAlex Crichton /// *error.downcast_mut::<&str>().unwrap() = "yikes"; 10948325e1ecSAlex Crichton /// assert_eq!(*error.downcast_mut::<&str>().unwrap(), "yikes"); 10958325e1ecSAlex Crichton /// 10968325e1ecSAlex Crichton /// // If there are multiple `E`s in the chain, the first in the chain is 10978325e1ecSAlex Crichton /// // returned. 10988325e1ecSAlex Crichton /// let error = Error::msg("root cause"); 10998325e1ecSAlex Crichton /// let mut error = error.context("failed to recombobulate"); 11008325e1ecSAlex Crichton /// assert_eq!( 11018325e1ecSAlex Crichton /// *error.downcast_mut::<&str>().unwrap(), 11028325e1ecSAlex Crichton /// "failed to recombobulate", 11038325e1ecSAlex Crichton /// ); 11048325e1ecSAlex Crichton /// ``` downcast_mut<E>(&mut self) -> Option<&mut E> where E: fmt::Display + fmt::Debug + Send + Sync + 'static,11058325e1ecSAlex Crichton pub fn downcast_mut<E>(&mut self) -> Option<&mut E> 11068325e1ecSAlex Crichton where 11078325e1ecSAlex Crichton E: fmt::Display + fmt::Debug + Send + Sync + 'static, 11088325e1ecSAlex Crichton { 11095afb6030SNick Fitzgerald self.error_ext_chain_mut(|e| { 11105afb6030SNick Fitzgerald { 11115afb6030SNick Fitzgerald // Safety: We are running into "problem case #3" of non-lexical 11125afb6030SNick Fitzgerald // lifetimes: we are returning a mutable reference, which must 11135afb6030SNick Fitzgerald // be live for the whole function's scope, but are accessing it 11145afb6030SNick Fitzgerald // again below in the `anyhow` downcast. This is safe because 11155afb6030SNick Fitzgerald // control flow ensures that the original borrow is not actually 11165afb6030SNick Fitzgerald // active anymore if we didn't return. 11175afb6030SNick Fitzgerald // 11185afb6030SNick Fitzgerald // https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md#problem-case-3-conditional-control-flow-across-functions 11195afb6030SNick Fitzgerald let e = unsafe { NonNull::from(&mut *e).as_mut() }; 11205afb6030SNick Fitzgerald if let Some(r) = e.inner.downcast_mut::<E>() { 11215afb6030SNick Fitzgerald return Some(r); 11228325e1ecSAlex Crichton } 11238325e1ecSAlex Crichton } 11245afb6030SNick Fitzgerald 11255afb6030SNick Fitzgerald #[cfg(feature = "anyhow")] 11265afb6030SNick Fitzgerald { 11275afb6030SNick Fitzgerald if let Some(result) = e 11285afb6030SNick Fitzgerald .inner 11295afb6030SNick Fitzgerald .downcast_mut::<anyhow::Error>() 11305afb6030SNick Fitzgerald .and_then(|anyhow| anyhow.downcast_mut::<E>()) 11315afb6030SNick Fitzgerald { 11325afb6030SNick Fitzgerald return Some(result); 11335afb6030SNick Fitzgerald } 11345afb6030SNick Fitzgerald } 11355afb6030SNick Fitzgerald 11368325e1ecSAlex Crichton None 11375afb6030SNick Fitzgerald }) 11388325e1ecSAlex Crichton } 11398325e1ecSAlex Crichton 11408325e1ecSAlex Crichton /// Convert this error into a `Box<dyn core::error::Error>`. 11418325e1ecSAlex Crichton /// 11428325e1ecSAlex Crichton /// This is useful for integrating this crate's `Error`s into other 11438325e1ecSAlex Crichton /// universal-error libraries. 11448325e1ecSAlex Crichton /// 11458325e1ecSAlex Crichton /// This functionality is also available via a `From<Error> for Box<dyn 11468325e1ecSAlex Crichton /// core::error::Error + Send + Sync + 'static>>` implementation. 11478325e1ecSAlex Crichton /// 11488325e1ecSAlex Crichton /// # Example 11498325e1ecSAlex Crichton /// 11508325e1ecSAlex Crichton /// ``` 11518325e1ecSAlex Crichton /// # fn _foo() { 11528325e1ecSAlex Crichton /// #![cfg(feature = "std")] 11538325e1ecSAlex Crichton /// use std::fmt; 11548325e1ecSAlex Crichton /// 11558325e1ecSAlex Crichton /// /// A stub representing some other error library. 11568325e1ecSAlex Crichton /// #[derive(Debug)] 11578325e1ecSAlex Crichton /// pub struct OtherError { 11588325e1ecSAlex Crichton /// inner: Box<dyn std::error::Error + Send + Sync + 'static>, 11598325e1ecSAlex Crichton /// } 11608325e1ecSAlex Crichton /// 11618325e1ecSAlex Crichton /// impl fmt::Display for OtherError { 11628325e1ecSAlex Crichton /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 11638325e1ecSAlex Crichton /// fmt::Display::fmt(&self.inner, f) 11648325e1ecSAlex Crichton /// } 11658325e1ecSAlex Crichton /// } 11668325e1ecSAlex Crichton /// 11678325e1ecSAlex Crichton /// impl std::error::Error for OtherError { 11688325e1ecSAlex Crichton /// fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 11698325e1ecSAlex Crichton /// self.inner.source() 11708325e1ecSAlex Crichton /// } 11718325e1ecSAlex Crichton /// } 11728325e1ecSAlex Crichton /// 11738325e1ecSAlex Crichton /// impl OtherError { 11748325e1ecSAlex Crichton /// /// Create an `OtherError` from another error. 11758325e1ecSAlex Crichton /// pub fn new<E>(error: E) -> Self 11768325e1ecSAlex Crichton /// where 11778325e1ecSAlex Crichton /// E: std::error::Error + Send + Sync + 'static, 11788325e1ecSAlex Crichton /// { 11798325e1ecSAlex Crichton /// OtherError { inner: Box::new(error) } 11808325e1ecSAlex Crichton /// } 11818325e1ecSAlex Crichton /// 11828325e1ecSAlex Crichton /// /// Create an `OtherError` from another, already-boxed error. 11838325e1ecSAlex Crichton /// pub fn from_boxed(error: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self { 11848325e1ecSAlex Crichton /// OtherError { inner: error } 11858325e1ecSAlex Crichton /// } 11868325e1ecSAlex Crichton /// } 11878325e1ecSAlex Crichton /// 11888325e1ecSAlex Crichton /// # use wasmtime_internal_core::error as wasmtime; 11898325e1ecSAlex Crichton /// use wasmtime::Error; 11908325e1ecSAlex Crichton /// 11918325e1ecSAlex Crichton /// // Create an `Error`. 11928325e1ecSAlex Crichton /// let error = Error::msg("whoopsies"); 11938325e1ecSAlex Crichton /// 11948325e1ecSAlex Crichton /// // Convert it into an `OtherError`. 11958325e1ecSAlex Crichton /// let error = OtherError::from_boxed(error.into_boxed_dyn_error()); 11968325e1ecSAlex Crichton /// # } 11978325e1ecSAlex Crichton /// ``` 11988325e1ecSAlex Crichton #[inline] into_boxed_dyn_error(self) -> Box<dyn core::error::Error + Send + Sync + 'static>11998325e1ecSAlex Crichton pub fn into_boxed_dyn_error(self) -> Box<dyn core::error::Error + Send + Sync + 'static> { 12008325e1ecSAlex Crichton /// A specialized OOM error that is zero-sized, so that it can always be 12018325e1ecSAlex Crichton /// boxed without allocation, and we can keep this method infallible (to 12028325e1ecSAlex Crichton /// match `anyhow`'s API). 12038325e1ecSAlex Crichton #[derive(Debug)] 12048325e1ecSAlex Crichton struct IntoBoxedDynCoreErrorFailure; 12058325e1ecSAlex Crichton 12068325e1ecSAlex Crichton impl core::fmt::Display for IntoBoxedDynCoreErrorFailure { 12078325e1ecSAlex Crichton fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 12088325e1ecSAlex Crichton write!( 12098325e1ecSAlex Crichton f, 12108325e1ecSAlex Crichton "failed to box error into `Box<dyn core::error::Error>` \ 12118325e1ecSAlex Crichton (allocation of {} bytes failed)", 12128325e1ecSAlex Crichton mem::size_of::<Error>() 12138325e1ecSAlex Crichton ) 12148325e1ecSAlex Crichton } 12158325e1ecSAlex Crichton } 12168325e1ecSAlex Crichton 12178325e1ecSAlex Crichton impl core::error::Error for IntoBoxedDynCoreErrorFailure {} 12188325e1ecSAlex Crichton 12198325e1ecSAlex Crichton match self.inner.into_boxed_dyn_core_error() { 12208325e1ecSAlex Crichton Ok(boxed) => boxed, 12218325e1ecSAlex Crichton Err(_oom) => { 12228325e1ecSAlex Crichton // NB: `Box::new` will never actually allocate for zero-sized types. 12238325e1ecSAlex Crichton Box::new(IntoBoxedDynCoreErrorFailure) as _ 12248325e1ecSAlex Crichton } 12258325e1ecSAlex Crichton } 12268325e1ecSAlex Crichton } 12275afb6030SNick Fitzgerald 12285afb6030SNick Fitzgerald #[cfg(feature = "backtrace")] take_backtrace(&mut self) -> Option<Backtrace>12295afb6030SNick Fitzgerald pub(crate) fn take_backtrace(&mut self) -> Option<Backtrace> { 12305afb6030SNick Fitzgerald match self.inner.unpack_mut() { 12315afb6030SNick Fitzgerald OomOrDynErrorMut::Oom(_) => None, 12325afb6030SNick Fitzgerald OomOrDynErrorMut::DynError(mut e) => { 12335afb6030SNick Fitzgerald let r = unsafe { e.as_mut() }; 12345afb6030SNick Fitzgerald r.backtrace.take() 12355afb6030SNick Fitzgerald } 12365afb6030SNick Fitzgerald } 12375afb6030SNick Fitzgerald } 12388325e1ecSAlex Crichton } 12398325e1ecSAlex Crichton 12408325e1ecSAlex Crichton /// `ErrorExt` wrapper for foreign `core::error::Error` implementations. 12418325e1ecSAlex Crichton /// 12428325e1ecSAlex Crichton /// For `Error::new`'s use only. 12438325e1ecSAlex Crichton /// 12448325e1ecSAlex Crichton /// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is` 12458325e1ecSAlex Crichton /// implementation and the casts that are performed using that method's return 12468325e1ecSAlex Crichton /// value. 12478325e1ecSAlex Crichton #[repr(transparent)] 12488325e1ecSAlex Crichton struct ForeignError<E>(E); 12498325e1ecSAlex Crichton 12508325e1ecSAlex Crichton // Safety: `ext_is` is correct, `ext_move` always writes to `dest`. 12518325e1ecSAlex Crichton unsafe impl<E> ErrorExt for ForeignError<E> 12528325e1ecSAlex Crichton where 12538325e1ecSAlex Crichton E: core::error::Error + Send + Sync + 'static, 12548325e1ecSAlex Crichton { ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static)12558325e1ecSAlex Crichton fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) { 12568325e1ecSAlex Crichton &self.0 12578325e1ecSAlex Crichton } 12588325e1ecSAlex Crichton ext_into_boxed_dyn_core_error( self, ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory>12598325e1ecSAlex Crichton fn ext_into_boxed_dyn_core_error( 12608325e1ecSAlex Crichton self, 12618325e1ecSAlex Crichton ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> { 12628325e1ecSAlex Crichton let boxed = try_new_uninit_box()?; 12638325e1ecSAlex Crichton Ok(Box::write(boxed, self.0) as _) 12648325e1ecSAlex Crichton } 12658325e1ecSAlex Crichton ext_source(&self) -> Option<&Error>12665afb6030SNick Fitzgerald fn ext_source(&self) -> Option<&Error> { 12678325e1ecSAlex Crichton None 12688325e1ecSAlex Crichton } 12698325e1ecSAlex Crichton ext_source_mut(&mut self) -> Option<&mut Error>12705afb6030SNick Fitzgerald fn ext_source_mut(&mut self) -> Option<&mut Error> { 12718325e1ecSAlex Crichton None 12728325e1ecSAlex Crichton } 12738325e1ecSAlex Crichton ext_move(self, dest: NonNull<u8>)12748325e1ecSAlex Crichton unsafe fn ext_move(self, dest: NonNull<u8>) { 12758325e1ecSAlex Crichton // Safety: implied by this trait method's safety contract. 12768325e1ecSAlex Crichton unsafe { 12778325e1ecSAlex Crichton dest.cast::<E>().write(self.0); 12788325e1ecSAlex Crichton } 12798325e1ecSAlex Crichton } 12808325e1ecSAlex Crichton ext_is(&self, type_id: TypeId) -> bool12818325e1ecSAlex Crichton fn ext_is(&self, type_id: TypeId) -> bool { 12828325e1ecSAlex Crichton // NB: need to check type id of `E`, not `Self` aka 12838325e1ecSAlex Crichton // `ForeignError<E>`. 12848325e1ecSAlex Crichton type_id == TypeId::of::<E>() 12858325e1ecSAlex Crichton } 12868325e1ecSAlex Crichton 12878325e1ecSAlex Crichton #[cfg(feature = "backtrace")] take_backtrace(&mut self) -> Option<Backtrace>12888325e1ecSAlex Crichton fn take_backtrace(&mut self) -> Option<Backtrace> { 12898325e1ecSAlex Crichton None 12908325e1ecSAlex Crichton } 12914fd25c07SAlex Crichton 12924fd25c07SAlex Crichton #[cfg(feature = "anyhow")] ext_into_anyhow(self) -> anyhow::Error12934fd25c07SAlex Crichton fn ext_into_anyhow(self) -> anyhow::Error { 12944fd25c07SAlex Crichton anyhow::Error::new(self.0) 12954fd25c07SAlex Crichton } 12968325e1ecSAlex Crichton } 12978325e1ecSAlex Crichton 12988325e1ecSAlex Crichton /// `ErrorExt` wrapper for types given to `Error::msg`. 12998325e1ecSAlex Crichton /// 13008325e1ecSAlex Crichton /// For `Error::msg`'s use only. 13018325e1ecSAlex Crichton /// 13028325e1ecSAlex Crichton /// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is` 13038325e1ecSAlex Crichton /// implementation and the casts that are performed using that method's return 13048325e1ecSAlex Crichton /// value. 13058325e1ecSAlex Crichton #[repr(transparent)] 13068325e1ecSAlex Crichton struct MessageError<M>(M); 13078325e1ecSAlex Crichton 13088325e1ecSAlex Crichton impl<M> fmt::Debug for MessageError<M> 13098325e1ecSAlex Crichton where 13108325e1ecSAlex Crichton M: fmt::Debug, 13118325e1ecSAlex Crichton { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result13128325e1ecSAlex Crichton fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 13138325e1ecSAlex Crichton self.0.fmt(f) 13148325e1ecSAlex Crichton } 13158325e1ecSAlex Crichton } 13168325e1ecSAlex Crichton 13178325e1ecSAlex Crichton impl<M> fmt::Display for MessageError<M> 13188325e1ecSAlex Crichton where 13198325e1ecSAlex Crichton M: fmt::Display, 13208325e1ecSAlex Crichton { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result13218325e1ecSAlex Crichton fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 13228325e1ecSAlex Crichton self.0.fmt(f) 13238325e1ecSAlex Crichton } 13248325e1ecSAlex Crichton } 13258325e1ecSAlex Crichton 13268325e1ecSAlex Crichton impl<M> core::error::Error for MessageError<M> where M: fmt::Debug + fmt::Display {} 13278325e1ecSAlex Crichton 13288325e1ecSAlex Crichton // Safety: `ext_is` is implemented correctly and `ext_move` always 13298325e1ecSAlex Crichton // writes to its pointer. 13308325e1ecSAlex Crichton unsafe impl<M> ErrorExt for MessageError<M> 13318325e1ecSAlex Crichton where 13328325e1ecSAlex Crichton M: fmt::Debug + fmt::Display + Send + Sync + 'static, 13338325e1ecSAlex Crichton { ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static)13348325e1ecSAlex Crichton fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) { 13358325e1ecSAlex Crichton self 13368325e1ecSAlex Crichton } 13378325e1ecSAlex Crichton ext_into_boxed_dyn_core_error( self, ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory>13388325e1ecSAlex Crichton fn ext_into_boxed_dyn_core_error( 13398325e1ecSAlex Crichton self, 13408325e1ecSAlex Crichton ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> { 13418325e1ecSAlex Crichton let boxed = try_new_uninit_box()?; 13428325e1ecSAlex Crichton Ok(Box::write(boxed, self) as _) 13438325e1ecSAlex Crichton } 13448325e1ecSAlex Crichton ext_source(&self) -> Option<&Error>13455afb6030SNick Fitzgerald fn ext_source(&self) -> Option<&Error> { 13468325e1ecSAlex Crichton None 13478325e1ecSAlex Crichton } 13488325e1ecSAlex Crichton ext_source_mut(&mut self) -> Option<&mut Error>13495afb6030SNick Fitzgerald fn ext_source_mut(&mut self) -> Option<&mut Error> { 13508325e1ecSAlex Crichton None 13518325e1ecSAlex Crichton } 13528325e1ecSAlex Crichton ext_is(&self, type_id: TypeId) -> bool13538325e1ecSAlex Crichton fn ext_is(&self, type_id: TypeId) -> bool { 13548325e1ecSAlex Crichton // NB: need to check type id of `M`, not `Self` aka 13558325e1ecSAlex Crichton // `MessageError<M>`. 13568325e1ecSAlex Crichton type_id == TypeId::of::<M>() 13578325e1ecSAlex Crichton } 13588325e1ecSAlex Crichton ext_move(self, dest: NonNull<u8>)13598325e1ecSAlex Crichton unsafe fn ext_move(self, dest: NonNull<u8>) { 13608325e1ecSAlex Crichton // Safety: implied by this trait method's contract. 13618325e1ecSAlex Crichton unsafe { 13628325e1ecSAlex Crichton dest.cast::<M>().write(self.0); 13638325e1ecSAlex Crichton } 13648325e1ecSAlex Crichton } 13658325e1ecSAlex Crichton 13668325e1ecSAlex Crichton #[cfg(feature = "backtrace")] take_backtrace(&mut self) -> Option<Backtrace>13678325e1ecSAlex Crichton fn take_backtrace(&mut self) -> Option<Backtrace> { 13688325e1ecSAlex Crichton None 13698325e1ecSAlex Crichton } 13704fd25c07SAlex Crichton 13714fd25c07SAlex Crichton #[cfg(feature = "anyhow")] ext_into_anyhow(self) -> anyhow::Error13724fd25c07SAlex Crichton fn ext_into_anyhow(self) -> anyhow::Error { 13734fd25c07SAlex Crichton anyhow::Error::msg(self.0) 13744fd25c07SAlex Crichton } 13758325e1ecSAlex Crichton } 13768325e1ecSAlex Crichton 13778325e1ecSAlex Crichton /// `ErrorExt` wrapper for `Box<dyn core::error::Error>`. 13788325e1ecSAlex Crichton /// 13798325e1ecSAlex Crichton /// For `Error::from_boxed`'s use only. 13808325e1ecSAlex Crichton /// 13818325e1ecSAlex Crichton /// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is` 13828325e1ecSAlex Crichton /// implementation and the casts that are performed using that method's return 13838325e1ecSAlex Crichton /// value. 13848325e1ecSAlex Crichton #[repr(transparent)] 13858325e1ecSAlex Crichton struct BoxedError(Box<dyn core::error::Error + Send + Sync + 'static>); 13868325e1ecSAlex Crichton 13878325e1ecSAlex Crichton // Safety: `ext_is` is implemented correctly and `ext_move` always 13888325e1ecSAlex Crichton // writes to its pointer. 13898325e1ecSAlex Crichton unsafe impl ErrorExt for BoxedError { ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static)13908325e1ecSAlex Crichton fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) { 13918325e1ecSAlex Crichton &*self.0 13928325e1ecSAlex Crichton } 13938325e1ecSAlex Crichton ext_into_boxed_dyn_core_error( self, ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory>13948325e1ecSAlex Crichton fn ext_into_boxed_dyn_core_error( 13958325e1ecSAlex Crichton self, 13968325e1ecSAlex Crichton ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> { 13978325e1ecSAlex Crichton Ok(self.0) 13988325e1ecSAlex Crichton } 13998325e1ecSAlex Crichton ext_source(&self) -> Option<&Error>14005afb6030SNick Fitzgerald fn ext_source(&self) -> Option<&Error> { 14018325e1ecSAlex Crichton None 14028325e1ecSAlex Crichton } 14038325e1ecSAlex Crichton ext_source_mut(&mut self) -> Option<&mut Error>14045afb6030SNick Fitzgerald fn ext_source_mut(&mut self) -> Option<&mut Error> { 14058325e1ecSAlex Crichton None 14068325e1ecSAlex Crichton } 14078325e1ecSAlex Crichton ext_is(&self, type_id: TypeId) -> bool14088325e1ecSAlex Crichton fn ext_is(&self, type_id: TypeId) -> bool { 14098325e1ecSAlex Crichton // NB: need to check type id of `BoxDynSendSyncError`, not 14108325e1ecSAlex Crichton // `BoxedError`. 14118325e1ecSAlex Crichton type_id == TypeId::of::<Box<dyn core::error::Error + Send + Sync + 'static>>() 14128325e1ecSAlex Crichton } 14138325e1ecSAlex Crichton ext_move(self, dest: NonNull<u8>)14148325e1ecSAlex Crichton unsafe fn ext_move(self, dest: NonNull<u8>) { 14158325e1ecSAlex Crichton // Safety: implied by this trait method's contract. 14168325e1ecSAlex Crichton unsafe { 14178325e1ecSAlex Crichton dest.cast::<Box<dyn core::error::Error + Send + Sync + 'static>>() 14188325e1ecSAlex Crichton .write(self.0); 14198325e1ecSAlex Crichton } 14208325e1ecSAlex Crichton } 14218325e1ecSAlex Crichton 14228325e1ecSAlex Crichton #[cfg(feature = "backtrace")] take_backtrace(&mut self) -> Option<Backtrace>14238325e1ecSAlex Crichton fn take_backtrace(&mut self) -> Option<Backtrace> { 14248325e1ecSAlex Crichton None 14258325e1ecSAlex Crichton } 14264fd25c07SAlex Crichton 14274fd25c07SAlex Crichton #[cfg(feature = "anyhow")] ext_into_anyhow(self) -> anyhow::Error14284fd25c07SAlex Crichton fn ext_into_anyhow(self) -> anyhow::Error { 14294fd25c07SAlex Crichton anyhow::Error::from_boxed(self.0) 14304fd25c07SAlex Crichton } 14318325e1ecSAlex Crichton } 14328325e1ecSAlex Crichton 14338325e1ecSAlex Crichton /// `ErrorExt` wrapper for `anyhow::Error`. 14348325e1ecSAlex Crichton /// 14358325e1ecSAlex Crichton /// For `Error::from_anyhow`'s use only. 14368325e1ecSAlex Crichton /// 14378325e1ecSAlex Crichton /// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is` 14388325e1ecSAlex Crichton /// implementation and the casts that are performed using that method's return 14398325e1ecSAlex Crichton /// value. 14408325e1ecSAlex Crichton #[repr(transparent)] 14418325e1ecSAlex Crichton #[cfg(feature = "anyhow")] 14428325e1ecSAlex Crichton struct AnyhowError(anyhow::Error); 14438325e1ecSAlex Crichton 14448325e1ecSAlex Crichton // Safety: `ext_is` is implemented correctly and `ext_move` always 14458325e1ecSAlex Crichton // writes to its pointer. 14468325e1ecSAlex Crichton #[cfg(feature = "anyhow")] 14478325e1ecSAlex Crichton unsafe impl ErrorExt for AnyhowError { ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static)14488325e1ecSAlex Crichton fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) { 14498325e1ecSAlex Crichton self.0.as_ref() 14508325e1ecSAlex Crichton } 14518325e1ecSAlex Crichton ext_into_boxed_dyn_core_error( self, ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory>14528325e1ecSAlex Crichton fn ext_into_boxed_dyn_core_error( 14538325e1ecSAlex Crichton self, 14548325e1ecSAlex Crichton ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> { 14558325e1ecSAlex Crichton Ok(self.0.into_boxed_dyn_error()) 14568325e1ecSAlex Crichton } 14578325e1ecSAlex Crichton ext_source(&self) -> Option<&Error>14585afb6030SNick Fitzgerald fn ext_source(&self) -> Option<&Error> { 14598325e1ecSAlex Crichton None 14608325e1ecSAlex Crichton } 14618325e1ecSAlex Crichton ext_source_mut(&mut self) -> Option<&mut Error>14625afb6030SNick Fitzgerald fn ext_source_mut(&mut self) -> Option<&mut Error> { 14638325e1ecSAlex Crichton None 14648325e1ecSAlex Crichton } 14658325e1ecSAlex Crichton ext_is(&self, type_id: TypeId) -> bool14668325e1ecSAlex Crichton fn ext_is(&self, type_id: TypeId) -> bool { 14678325e1ecSAlex Crichton // NB: need to check type id of `BoxDynSendSyncError`, not 14688325e1ecSAlex Crichton // `AnyhowError`. 14698325e1ecSAlex Crichton type_id == TypeId::of::<anyhow::Error>() 14708325e1ecSAlex Crichton } 14718325e1ecSAlex Crichton ext_move(self, dest: NonNull<u8>)14728325e1ecSAlex Crichton unsafe fn ext_move(self, dest: NonNull<u8>) { 14738325e1ecSAlex Crichton // Safety: implied by this trait method's contract. 14748325e1ecSAlex Crichton unsafe { 14758325e1ecSAlex Crichton dest.cast::<anyhow::Error>().write(self.0); 14768325e1ecSAlex Crichton } 14778325e1ecSAlex Crichton } 14788325e1ecSAlex Crichton 14798325e1ecSAlex Crichton #[cfg(feature = "backtrace")] take_backtrace(&mut self) -> Option<Backtrace>14808325e1ecSAlex Crichton fn take_backtrace(&mut self) -> Option<Backtrace> { 14818325e1ecSAlex Crichton None 14828325e1ecSAlex Crichton } 14834fd25c07SAlex Crichton 14844fd25c07SAlex Crichton #[cfg(feature = "anyhow")] ext_into_anyhow(self) -> anyhow::Error14854fd25c07SAlex Crichton fn ext_into_anyhow(self) -> anyhow::Error { 14864fd25c07SAlex Crichton self.0 14874fd25c07SAlex Crichton } 14888325e1ecSAlex Crichton } 14898325e1ecSAlex Crichton 14905afb6030SNick Fitzgerald #[derive(Clone, Copy)] 14918325e1ecSAlex Crichton pub(crate) enum OomOrDynErrorRef<'a> { 14928325e1ecSAlex Crichton // Safety: this must always be a valid pointer to read a `DynError` from for 14938325e1ecSAlex Crichton // the `'a` lifetime. 14948325e1ecSAlex Crichton DynError(SharedPtr<'a, DynError>), 14958325e1ecSAlex Crichton 14968325e1ecSAlex Crichton Oom(&'a OutOfMemory), 14978325e1ecSAlex Crichton } 14988325e1ecSAlex Crichton 14998325e1ecSAlex Crichton pub(crate) enum OomOrDynErrorMut<'a> { 15008325e1ecSAlex Crichton // Safety: this must always be a valid pointer to read and write a 15018325e1ecSAlex Crichton // `DynError` from for the `'a` lifetime. 15028325e1ecSAlex Crichton DynError(MutPtr<'a, DynError>), 15038325e1ecSAlex Crichton 15048325e1ecSAlex Crichton Oom(&'a mut OutOfMemory), 15058325e1ecSAlex Crichton } 15068325e1ecSAlex Crichton 15078325e1ecSAlex Crichton /// Bit packed version of `enum { BoxedDynError, OutOfMemory }` that relies on 15088325e1ecSAlex Crichton /// implicit pointer tagging and `OutOfMemory` being zero-sized. 15098325e1ecSAlex Crichton #[repr(transparent)] 15108325e1ecSAlex Crichton pub(crate) struct OomOrDynError { 15118325e1ecSAlex Crichton // Safety: this must always be the casted-to-`u8` version of either (a) 15128325e1ecSAlex Crichton // `0x1`, or (b) a valid, owned `DynError` pointer. (Note that these cases 15138325e1ecSAlex Crichton // cannot overlap because `DynError`'s alignment is greater than `0x1`.) 15148325e1ecSAlex Crichton inner: NonNull<u8>, 15158325e1ecSAlex Crichton } 15168325e1ecSAlex Crichton 15178325e1ecSAlex Crichton // Safety: `OomOrDynError` is either an `OutOfMemory` or a `BoxedDynError` and 15188325e1ecSAlex Crichton // both are `Send`. 15198325e1ecSAlex Crichton unsafe impl Send for OomOrDynError {} 15208325e1ecSAlex Crichton 15218325e1ecSAlex Crichton // Safety: `OomOrDynError` is either an `OutOfMemory` or a `BoxedDynError` and 15228325e1ecSAlex Crichton // both are `Sync`. 15238325e1ecSAlex Crichton unsafe impl Sync for OomOrDynError {} 15248325e1ecSAlex Crichton 15258325e1ecSAlex Crichton const _OOM_OR_DYN_ERROR_SEND_SYNC_SAFETY: () = { assert_send_sync<T: Send + Sync>()15268325e1ecSAlex Crichton const fn assert_send_sync<T: Send + Sync>() {} 15278325e1ecSAlex Crichton assert_send_sync::<OutOfMemory>(); 15288325e1ecSAlex Crichton assert_send_sync::<BoxedDynError>(); 15298325e1ecSAlex Crichton }; 15308325e1ecSAlex Crichton 15318325e1ecSAlex Crichton impl Drop for OomOrDynError { drop(&mut self)15328325e1ecSAlex Crichton fn drop(&mut self) { 15338325e1ecSAlex Crichton if self.is_boxed_dyn_error() { 15348325e1ecSAlex Crichton let inner = self.inner.cast::<DynError>(); 15358325e1ecSAlex Crichton let inner = OwnedPtr::new(inner); 15368325e1ecSAlex Crichton // Safety: the pointer is a valid `DynError` pointer. 15378325e1ecSAlex Crichton let _ = unsafe { BoxedDynError::from_owned_ptr(inner) }; 15388325e1ecSAlex Crichton } else { 15398325e1ecSAlex Crichton debug_assert!(self.is_oom()); 15408325e1ecSAlex Crichton } 15418325e1ecSAlex Crichton } 15428325e1ecSAlex Crichton } 15438325e1ecSAlex Crichton 15448325e1ecSAlex Crichton impl From<BoxedDynError> for OomOrDynError { from(boxed: BoxedDynError) -> Self15458325e1ecSAlex Crichton fn from(boxed: BoxedDynError) -> Self { 15468325e1ecSAlex Crichton let inner = boxed.into_owned_ptr().into_non_null().cast::<u8>(); 15478325e1ecSAlex Crichton debug_assert!(!Self::is_oom_ptr(inner)); 15488325e1ecSAlex Crichton OomOrDynError { inner } 15498325e1ecSAlex Crichton } 15508325e1ecSAlex Crichton } 15518325e1ecSAlex Crichton 15525afb6030SNick Fitzgerald impl fmt::Debug for OomOrDynError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result15535afb6030SNick Fitzgerald fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 15545afb6030SNick Fitzgerald self.debug(f) 15555afb6030SNick Fitzgerald } 15565afb6030SNick Fitzgerald } 15575afb6030SNick Fitzgerald 15588325e1ecSAlex Crichton impl OomOrDynError { 15598325e1ecSAlex Crichton const _SIZE: () = assert!(mem::size_of::<OomOrDynError>() == mem::size_of::<usize>()); 15608325e1ecSAlex Crichton 15618325e1ecSAlex Crichton /// Our pointer tagging relies on this property, which implies that 15628325e1ecSAlex Crichton /// `Self::OOM_BIT` is never set for any `*mut DynError` pointer. 15638325e1ecSAlex Crichton const _DYN_ERROR_HAS_GREATER_ALIGN_THAN_OOM: () = assert!(mem::align_of::<DynError>() > 1); 15648325e1ecSAlex Crichton 15658325e1ecSAlex Crichton /// If this bit is set in the inner pointer's address, then it is a bitpacked 15668325e1ecSAlex Crichton /// `OutOfMemory` rather than a pointer to a boxed dyn error. 15678325e1ecSAlex Crichton const OOM_BIT: usize = 0x1; 15688325e1ecSAlex Crichton new_oom_ptr(size: usize) -> NonNull<u8>15698325e1ecSAlex Crichton pub(crate) const fn new_oom_ptr(size: usize) -> NonNull<u8> { 15708325e1ecSAlex Crichton let size = if size > (isize::MAX as usize) { 15718325e1ecSAlex Crichton isize::MAX as usize 15728325e1ecSAlex Crichton } else { 15738325e1ecSAlex Crichton size 15748325e1ecSAlex Crichton }; 15758325e1ecSAlex Crichton let repr = (size << 1) | Self::OOM_BIT; 15768325e1ecSAlex Crichton let inner = core::ptr::without_provenance_mut(repr); 15778325e1ecSAlex Crichton NonNull::new(inner).unwrap() 15788325e1ecSAlex Crichton } 15798325e1ecSAlex Crichton new_oom(bitpacked: NonNull<u8>) -> Self15808325e1ecSAlex Crichton pub(crate) fn new_oom(bitpacked: NonNull<u8>) -> Self { 15818325e1ecSAlex Crichton assert!(Self::is_oom_ptr(bitpacked)); 15828325e1ecSAlex Crichton OomOrDynError { inner: bitpacked } 15838325e1ecSAlex Crichton } 15848325e1ecSAlex Crichton is_oom_ptr(ptr: NonNull<u8>) -> bool15858325e1ecSAlex Crichton fn is_oom_ptr(ptr: NonNull<u8>) -> bool { 15868325e1ecSAlex Crichton (ptr.addr().get() & Self::OOM_BIT) == Self::OOM_BIT 15878325e1ecSAlex Crichton } 15888325e1ecSAlex Crichton is_oom(&self) -> bool15898325e1ecSAlex Crichton fn is_oom(&self) -> bool { 15908325e1ecSAlex Crichton Self::is_oom_ptr(self.inner) 15918325e1ecSAlex Crichton } 15928325e1ecSAlex Crichton is_boxed_dyn_error(&self) -> bool15938325e1ecSAlex Crichton fn is_boxed_dyn_error(&self) -> bool { 15948325e1ecSAlex Crichton !self.is_oom() 15958325e1ecSAlex Crichton } 15968325e1ecSAlex Crichton oom_size(inner: NonNull<u8>) -> usize15978325e1ecSAlex Crichton pub(crate) fn oom_size(inner: NonNull<u8>) -> usize { 15988325e1ecSAlex Crichton debug_assert!(Self::is_oom_ptr(inner)); 15998325e1ecSAlex Crichton inner.addr().get() >> 1 16008325e1ecSAlex Crichton } 16018325e1ecSAlex Crichton 16028325e1ecSAlex Crichton /// # Safety 16038325e1ecSAlex Crichton /// 16048325e1ecSAlex Crichton /// `self.is_oom()` must be true. unchecked_oom(&self) -> &OutOfMemory16058325e1ecSAlex Crichton unsafe fn unchecked_oom(&self) -> &OutOfMemory { 16068325e1ecSAlex Crichton debug_assert!(self.is_oom()); 16078325e1ecSAlex Crichton // Safety: `self.is_oom()` and `OutOfMemory` has the same representation 16088325e1ecSAlex Crichton // as `Self`. 16098325e1ecSAlex Crichton unsafe { mem::transmute(self) } 16108325e1ecSAlex Crichton } 16118325e1ecSAlex Crichton 16128325e1ecSAlex Crichton /// # Safety 16138325e1ecSAlex Crichton /// 16148325e1ecSAlex Crichton /// `self.is_oom()` must be true. unchecked_oom_mut(&mut self) -> &mut OutOfMemory16158325e1ecSAlex Crichton unsafe fn unchecked_oom_mut(&mut self) -> &mut OutOfMemory { 16168325e1ecSAlex Crichton debug_assert!(self.is_oom()); 16178325e1ecSAlex Crichton // Safety: `self.is_oom()` and `OutOfMemory` has the same representation 16188325e1ecSAlex Crichton // as `Self`. 16198325e1ecSAlex Crichton unsafe { mem::transmute(self) } 16208325e1ecSAlex Crichton } 16218325e1ecSAlex Crichton 16228325e1ecSAlex Crichton /// # Safety 16238325e1ecSAlex Crichton /// 16248325e1ecSAlex Crichton /// `self.is_boxed_dyn_error()` must be true. unchecked_into_dyn_error(self) -> OwnedPtr<DynError>16258325e1ecSAlex Crichton unsafe fn unchecked_into_dyn_error(self) -> OwnedPtr<DynError> { 16268325e1ecSAlex Crichton debug_assert!(self.is_boxed_dyn_error()); 16278325e1ecSAlex Crichton let inner = self.inner.cast::<DynError>(); 16288325e1ecSAlex Crichton mem::forget(self); 16298325e1ecSAlex Crichton OwnedPtr::new(inner) 16308325e1ecSAlex Crichton } 16318325e1ecSAlex Crichton 16328325e1ecSAlex Crichton /// # Safety 16338325e1ecSAlex Crichton /// 16348325e1ecSAlex Crichton /// `self.is_boxed_dyn_error()` must be true. unchecked_dyn_error_ref(&self) -> SharedPtr<'_, DynError>16358325e1ecSAlex Crichton unsafe fn unchecked_dyn_error_ref(&self) -> SharedPtr<'_, DynError> { 16368325e1ecSAlex Crichton debug_assert!(self.is_boxed_dyn_error()); 16378325e1ecSAlex Crichton SharedPtr::new(self.inner.cast::<DynError>()) 16388325e1ecSAlex Crichton } 16398325e1ecSAlex Crichton 16408325e1ecSAlex Crichton /// # Safety 16418325e1ecSAlex Crichton /// 16428325e1ecSAlex Crichton /// `self.is_boxed_dyn_error()` must be true. unchecked_dyn_error_mut(&mut self) -> MutPtr<'_, DynError>16438325e1ecSAlex Crichton unsafe fn unchecked_dyn_error_mut(&mut self) -> MutPtr<'_, DynError> { 16448325e1ecSAlex Crichton debug_assert!(self.is_boxed_dyn_error()); 16458325e1ecSAlex Crichton MutPtr::new(self.inner.cast::<DynError>()) 16468325e1ecSAlex Crichton } 16478325e1ecSAlex Crichton unpack(&self) -> OomOrDynErrorRef<'_>16488325e1ecSAlex Crichton pub(crate) fn unpack(&self) -> OomOrDynErrorRef<'_> { 16498325e1ecSAlex Crichton if self.is_oom() { 16508325e1ecSAlex Crichton // Safety: is_oom() is true. 16518325e1ecSAlex Crichton OomOrDynErrorRef::Oom(unsafe { self.unchecked_oom() }) 16528325e1ecSAlex Crichton } else { 16538325e1ecSAlex Crichton debug_assert!(self.is_boxed_dyn_error()); 16548325e1ecSAlex Crichton // Safety: self.is_boxed_dyn_error() is true. 16558325e1ecSAlex Crichton OomOrDynErrorRef::DynError(unsafe { self.unchecked_dyn_error_ref() }) 16568325e1ecSAlex Crichton } 16578325e1ecSAlex Crichton } 16588325e1ecSAlex Crichton unpack_mut(&mut self) -> OomOrDynErrorMut<'_>16598325e1ecSAlex Crichton pub(crate) fn unpack_mut(&mut self) -> OomOrDynErrorMut<'_> { 16608325e1ecSAlex Crichton if self.is_oom() { 16618325e1ecSAlex Crichton // Safety: self.is_oom() is true 16628325e1ecSAlex Crichton OomOrDynErrorMut::Oom(unsafe { self.unchecked_oom_mut() }) 16638325e1ecSAlex Crichton } else { 16648325e1ecSAlex Crichton debug_assert!(self.is_boxed_dyn_error()); 16658325e1ecSAlex Crichton // Safety: self.is_boxed_dyn_error() is true. 16668325e1ecSAlex Crichton OomOrDynErrorMut::DynError(unsafe { self.unchecked_dyn_error_mut() }) 16678325e1ecSAlex Crichton } 16688325e1ecSAlex Crichton } 16698325e1ecSAlex Crichton into_boxed_dyn_core_error( self, ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory>16708325e1ecSAlex Crichton pub(crate) fn into_boxed_dyn_core_error( 16718325e1ecSAlex Crichton self, 16728325e1ecSAlex Crichton ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> { 16738325e1ecSAlex Crichton if self.is_oom() { 16748325e1ecSAlex Crichton let boxed = try_new_uninit_box::<OutOfMemory>()?; 16758325e1ecSAlex Crichton // Safety: `self.is_oom()` is true. 16768325e1ecSAlex Crichton let boxed = Box::write(boxed, unsafe { *self.unchecked_oom() }); 16778325e1ecSAlex Crichton Ok(boxed as _) 16788325e1ecSAlex Crichton } else { 16798325e1ecSAlex Crichton debug_assert!(self.is_boxed_dyn_error()); 16808325e1ecSAlex Crichton // Safety: this is a boxed dyn error. 16818325e1ecSAlex Crichton let ptr = unsafe { self.unchecked_into_dyn_error() }; 16828325e1ecSAlex Crichton // Safety: invariant of the type that the pointer is valid. 16838325e1ecSAlex Crichton let vtable = unsafe { ptr.as_ref().vtable }; 16848325e1ecSAlex Crichton // Safety: the pointer is valid and the vtable is associated with 16858325e1ecSAlex Crichton // this pointer's concrete error type. 16868325e1ecSAlex Crichton unsafe { (vtable.into_boxed_dyn_core_error)(ptr) } 16878325e1ecSAlex Crichton } 16888325e1ecSAlex Crichton } 16898325e1ecSAlex Crichton 16904fd25c07SAlex Crichton #[cfg(feature = "anyhow")] into_anyhow(self) -> anyhow::Error16914fd25c07SAlex Crichton pub(crate) fn into_anyhow(self) -> anyhow::Error { 16924fd25c07SAlex Crichton if self.is_oom() { 16934fd25c07SAlex Crichton // Safety: `self.is_oom()` is true. 16944fd25c07SAlex Crichton anyhow::Error::from(unsafe { *self.unchecked_oom() }) 16954fd25c07SAlex Crichton } else { 16964fd25c07SAlex Crichton debug_assert!(self.is_boxed_dyn_error()); 16974fd25c07SAlex Crichton // Safety: this is a boxed dyn error. 16984fd25c07SAlex Crichton let ptr = unsafe { self.unchecked_into_dyn_error() }; 16994fd25c07SAlex Crichton // Safety: invariant of the type that the pointer is valid. 17004fd25c07SAlex Crichton let vtable = unsafe { ptr.as_ref().vtable }; 17014fd25c07SAlex Crichton // Safety: the pointer is valid and the vtable is associated with 17024fd25c07SAlex Crichton // this pointer's concrete error type. 17034fd25c07SAlex Crichton unsafe { (vtable.into_anyhow)(ptr) } 17044fd25c07SAlex Crichton } 17054fd25c07SAlex Crichton } 17064fd25c07SAlex Crichton source(&self) -> Option<&Error>17075afb6030SNick Fitzgerald fn source(&self) -> Option<&Error> { 17085afb6030SNick Fitzgerald match self.unpack() { 17095afb6030SNick Fitzgerald OomOrDynErrorRef::DynError(e) => { 17105afb6030SNick Fitzgerald // Safety: invariant of this type. 17115afb6030SNick Fitzgerald let vtable = unsafe { e.as_ref().vtable }; 17125afb6030SNick Fitzgerald // Safety: using the vtable associated with this pointer's 17135afb6030SNick Fitzgerald // concrete type and the pointer is valid. 17145afb6030SNick Fitzgerald unsafe { (vtable.source)(e) } 17155afb6030SNick Fitzgerald } 17165afb6030SNick Fitzgerald OomOrDynErrorRef::Oom(_) => None, 17175afb6030SNick Fitzgerald } 17185afb6030SNick Fitzgerald } 17195afb6030SNick Fitzgerald source_mut(&mut self) -> Option<&mut Error>17205afb6030SNick Fitzgerald fn source_mut(&mut self) -> Option<&mut Error> { 17215afb6030SNick Fitzgerald match self.unpack_mut() { 17225afb6030SNick Fitzgerald OomOrDynErrorMut::DynError(e) => { 17235afb6030SNick Fitzgerald // Safety: invariant of this type. 17245afb6030SNick Fitzgerald let vtable = unsafe { e.as_ref().vtable }; 17255afb6030SNick Fitzgerald // Safety: using the vtable associated with this pointer's 17265afb6030SNick Fitzgerald // concrete type and the pointer is valid. 17275afb6030SNick Fitzgerald unsafe { (vtable.source_mut)(e.raw_copy()) } 17285afb6030SNick Fitzgerald } 17295afb6030SNick Fitzgerald OomOrDynErrorMut::Oom(_) => None, 17305afb6030SNick Fitzgerald } 17315afb6030SNick Fitzgerald } 17325afb6030SNick Fitzgerald is<E>(&self) -> bool where E: fmt::Display + fmt::Debug + Send + Sync + 'static,17335afb6030SNick Fitzgerald fn is<E>(&self) -> bool 17345afb6030SNick Fitzgerald where 17355afb6030SNick Fitzgerald E: fmt::Display + fmt::Debug + Send + Sync + 'static, 17365afb6030SNick Fitzgerald { 17375afb6030SNick Fitzgerald match self.unpack() { 17385afb6030SNick Fitzgerald OomOrDynErrorRef::DynError(e) => { 17395afb6030SNick Fitzgerald // Safety: invariant of this type. 17405afb6030SNick Fitzgerald let vtable = unsafe { e.as_ref().vtable }; 17415afb6030SNick Fitzgerald // Safety: using the vtable associated with this pointer's 17425afb6030SNick Fitzgerald // concrete type and the pointer is valid. 17435afb6030SNick Fitzgerald unsafe { (vtable.is)(e, TypeId::of::<E>()) } 17445afb6030SNick Fitzgerald } 17455afb6030SNick Fitzgerald OomOrDynErrorRef::Oom(_) => TypeId::of::<E>() == TypeId::of::<OutOfMemory>(), 17465afb6030SNick Fitzgerald } 17475afb6030SNick Fitzgerald } 17485afb6030SNick Fitzgerald downcast<E>(self) -> Result<E, Self> where E: fmt::Display + fmt::Debug + Send + Sync + 'static,17495afb6030SNick Fitzgerald pub(crate) fn downcast<E>(self) -> Result<E, Self> 17505afb6030SNick Fitzgerald where 17515afb6030SNick Fitzgerald E: fmt::Display + fmt::Debug + Send + Sync + 'static, 17525afb6030SNick Fitzgerald { 17535afb6030SNick Fitzgerald if !self.is::<E>() { 17545afb6030SNick Fitzgerald return Err(self); 17555afb6030SNick Fitzgerald } 17565afb6030SNick Fitzgerald 17575afb6030SNick Fitzgerald let mut ret = mem::MaybeUninit::<E>::uninit(); 17588325e1ecSAlex Crichton if self.is_oom() { 17595afb6030SNick Fitzgerald debug_assert_eq!(TypeId::of::<E>(), TypeId::of::<OutOfMemory>()); 17608325e1ecSAlex Crichton // Safety: this is an OOM error. 17615afb6030SNick Fitzgerald let oom = unsafe { *self.unchecked_oom() }; 17625afb6030SNick Fitzgerald let ret_ptr = NonNull::from(&mut ret).cast::<OutOfMemory>(); 17635afb6030SNick Fitzgerald // Safety: the pointer is valid for writing our OOM into because it 17645afb6030SNick Fitzgerald // is a valid pointer to space for an `E` and `E == OutOfMemory`. 17658325e1ecSAlex Crichton unsafe { 17665afb6030SNick Fitzgerald ret_ptr.write(oom); 17678325e1ecSAlex Crichton } 17688325e1ecSAlex Crichton } else { 17698325e1ecSAlex Crichton debug_assert!(self.is_boxed_dyn_error()); 17708325e1ecSAlex Crichton // Safety: this is a boxed dyn error. 17718325e1ecSAlex Crichton let ptr = unsafe { self.unchecked_into_dyn_error() }; 17728325e1ecSAlex Crichton // Safety: invariant of this type that the pointer is valid. 17738325e1ecSAlex Crichton let vtable = unsafe { ptr.as_ref().vtable }; 17745afb6030SNick Fitzgerald let ret_ptr = NonNull::from(&mut ret).cast::<u8>(); 17758325e1ecSAlex Crichton // Safety: the pointer is valid and the vtable is associated with 17768325e1ecSAlex Crichton // this pointer's concrete type. 17775afb6030SNick Fitzgerald unsafe { (vtable.move_into)(ptr, ret_ptr) } 17785afb6030SNick Fitzgerald } 17795afb6030SNick Fitzgerald 17805afb6030SNick Fitzgerald // Safety: `ret` was fully initialized in all control-flow paths leading 17815afb6030SNick Fitzgerald // here. 17825afb6030SNick Fitzgerald Ok(unsafe { ret.assume_init() }) 17835afb6030SNick Fitzgerald } 17845afb6030SNick Fitzgerald downcast_mut<E>(&mut self) -> Option<&mut E> where E: fmt::Display + fmt::Debug + Send + Sync + 'static,17855afb6030SNick Fitzgerald fn downcast_mut<E>(&mut self) -> Option<&mut E> 17865afb6030SNick Fitzgerald where 17875afb6030SNick Fitzgerald E: fmt::Display + fmt::Debug + Send + Sync + 'static, 17885afb6030SNick Fitzgerald { 17895afb6030SNick Fitzgerald if !self.is::<E>() { 17905afb6030SNick Fitzgerald return None; 17915afb6030SNick Fitzgerald } 17925afb6030SNick Fitzgerald 17935afb6030SNick Fitzgerald match self.unpack_mut() { 17945afb6030SNick Fitzgerald OomOrDynErrorMut::DynError(ptr) => { 17955afb6030SNick Fitzgerald let mut ptr = ptr.cast::<ConcreteError<E>>(); 17965afb6030SNick Fitzgerald // Safety: we own the pointer, it is valid for reading 17975afb6030SNick Fitzgerald // and writing, and we checked that it is an `E`. 17985afb6030SNick Fitzgerald let r = unsafe { ptr.as_mut() }; 17995afb6030SNick Fitzgerald Some(&mut r.error) 18005afb6030SNick Fitzgerald } 18015afb6030SNick Fitzgerald OomOrDynErrorMut::Oom(oom) => { 18025afb6030SNick Fitzgerald // Note: Even though we know that `E == OutOfMemory` 18035afb6030SNick Fitzgerald // here, we still have to do this dance to satisfy the 18045afb6030SNick Fitzgerald // type system. 18055afb6030SNick Fitzgerald debug_assert_eq!(TypeId::of::<E>(), TypeId::of::<OutOfMemory>()); 18065afb6030SNick Fitzgerald let ptr = NonNull::from(oom); 18075afb6030SNick Fitzgerald let mut ptr = ptr.cast::<E>(); 18085afb6030SNick Fitzgerald // Safety: the pointer points to `oom`, which is valid 18095afb6030SNick Fitzgerald // for creating an exclusive reference to. 18105afb6030SNick Fitzgerald Some(unsafe { ptr.as_mut() }) 18115afb6030SNick Fitzgerald } 18125afb6030SNick Fitzgerald } 18135afb6030SNick Fitzgerald } 18145afb6030SNick Fitzgerald display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result18155afb6030SNick Fitzgerald fn display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 18165afb6030SNick Fitzgerald match self.unpack() { 18175afb6030SNick Fitzgerald OomOrDynErrorRef::DynError(e) => { 18185afb6030SNick Fitzgerald // Safety: invariant of this type. 18195afb6030SNick Fitzgerald let vtable = unsafe { e.as_ref().vtable }; 18205afb6030SNick Fitzgerald // Safety: using the vtable associated with this pointer's 18215afb6030SNick Fitzgerald // concrete type and the pointer is valid. 18225afb6030SNick Fitzgerald unsafe { (vtable.display)(e, f) } 18235afb6030SNick Fitzgerald } 18245afb6030SNick Fitzgerald OomOrDynErrorRef::Oom(oom) => fmt::Display::fmt(oom, f), 18255afb6030SNick Fitzgerald } 18265afb6030SNick Fitzgerald } 18275afb6030SNick Fitzgerald debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result18285afb6030SNick Fitzgerald fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 18295afb6030SNick Fitzgerald match self.unpack() { 18305afb6030SNick Fitzgerald OomOrDynErrorRef::Oom(oom) => f.debug_tuple("Oom").field(oom).finish(), 18315afb6030SNick Fitzgerald OomOrDynErrorRef::DynError(error) => { 18325afb6030SNick Fitzgerald struct DebugError<'a>(SharedPtr<'a, DynError>); 18335afb6030SNick Fitzgerald impl fmt::Debug for DebugError<'_> { 18345afb6030SNick Fitzgerald fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 18355afb6030SNick Fitzgerald // Safety: invariant of `OomOrDynError` that the pointer 18365afb6030SNick Fitzgerald // is valid. 18375afb6030SNick Fitzgerald let vtable = unsafe { self.0.as_ref().vtable }; 18385afb6030SNick Fitzgerald // Safety: the pointer is valid and the vtable is 18395afb6030SNick Fitzgerald // associated with the pointer's concrete error type. 18405afb6030SNick Fitzgerald unsafe { (vtable.debug)(self.0, f) } 18415afb6030SNick Fitzgerald } 18425afb6030SNick Fitzgerald } 18435afb6030SNick Fitzgerald 18445afb6030SNick Fitzgerald let mut f = f.debug_struct("DynError"); 18455afb6030SNick Fitzgerald f.field("error", &DebugError(error)); 18465afb6030SNick Fitzgerald if let Some(source) = self.source() { 18475afb6030SNick Fitzgerald f.field("source", &source); 18485afb6030SNick Fitzgerald } 18495afb6030SNick Fitzgerald f.finish() 18505afb6030SNick Fitzgerald } 18515afb6030SNick Fitzgerald } 18525afb6030SNick Fitzgerald } 18535afb6030SNick Fitzgerald downcast_ref<E>(&self) -> Option<&E> where E: fmt::Display + fmt::Debug + Send + Sync + 'static,18545afb6030SNick Fitzgerald fn downcast_ref<E>(&self) -> Option<&E> 18555afb6030SNick Fitzgerald where 18565afb6030SNick Fitzgerald E: fmt::Display + fmt::Debug + Send + Sync + 'static, 18575afb6030SNick Fitzgerald { 18585afb6030SNick Fitzgerald if !self.is::<E>() { 18595afb6030SNick Fitzgerald return None; 18605afb6030SNick Fitzgerald } 18615afb6030SNick Fitzgerald 18625afb6030SNick Fitzgerald match self.unpack() { 18635afb6030SNick Fitzgerald OomOrDynErrorRef::DynError(ptr) => { 18645afb6030SNick Fitzgerald let ptr = ptr.cast::<ConcreteError<E>>(); 18655afb6030SNick Fitzgerald // Safety: we own the pointer, it is valid for reading, 18665afb6030SNick Fitzgerald // and we checked that it is an `E`. 18675afb6030SNick Fitzgerald let r = unsafe { ptr.as_ref() }; 18685afb6030SNick Fitzgerald Some(&r.error) 18695afb6030SNick Fitzgerald } 18705afb6030SNick Fitzgerald OomOrDynErrorRef::Oom(oom) => { 18715afb6030SNick Fitzgerald // Note: Even though we know that `E == OutOfMemory` 18725afb6030SNick Fitzgerald // here, we still have to do this dance to satisfy the 18735afb6030SNick Fitzgerald // type system. 18745afb6030SNick Fitzgerald debug_assert_eq!(TypeId::of::<E>(), TypeId::of::<OutOfMemory>()); 18755afb6030SNick Fitzgerald let ptr = NonNull::from(oom); 18765afb6030SNick Fitzgerald let ptr = ptr.cast::<E>(); 18775afb6030SNick Fitzgerald // Safety: the pointer points to `oom`, which is valid 18785afb6030SNick Fitzgerald // for creating a shared reference to. 18795afb6030SNick Fitzgerald Some(unsafe { ptr.as_ref() }) 18805afb6030SNick Fitzgerald } 18815afb6030SNick Fitzgerald } 18825afb6030SNick Fitzgerald } 18835afb6030SNick Fitzgerald as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static)18845afb6030SNick Fitzgerald pub(crate) fn as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) { 18855afb6030SNick Fitzgerald match self.unpack() { 18865afb6030SNick Fitzgerald OomOrDynErrorRef::DynError(e) => { 18875afb6030SNick Fitzgerald // Safety: invariant of this type. 18885afb6030SNick Fitzgerald let vtable = unsafe { e.as_ref().vtable }; 18895afb6030SNick Fitzgerald // Safety: using the vtable associated with this pointer's 18905afb6030SNick Fitzgerald // concrete type and the pointer is valid. 18915afb6030SNick Fitzgerald unsafe { (vtable.as_dyn_core_error)(e) } 18925afb6030SNick Fitzgerald } 18935afb6030SNick Fitzgerald OomOrDynErrorRef::Oom(oom) => oom as _, 18945afb6030SNick Fitzgerald } 18955afb6030SNick Fitzgerald } 18965afb6030SNick Fitzgerald 18975afb6030SNick Fitzgerald #[cfg(feature = "backtrace")] backtrace(&self) -> &Backtrace18985afb6030SNick Fitzgerald fn backtrace(&self) -> &Backtrace { 18995afb6030SNick Fitzgerald match self.unpack() { 19005afb6030SNick Fitzgerald OomOrDynErrorRef::DynError(e) => { 19015afb6030SNick Fitzgerald // Safety: invariant of this type. 19025afb6030SNick Fitzgerald let r = unsafe { e.as_ref() }; 19035afb6030SNick Fitzgerald r.backtrace 19045afb6030SNick Fitzgerald .as_ref() 19055afb6030SNick Fitzgerald .expect("the first error in the chain always has the backtrace") 19065afb6030SNick Fitzgerald } 19075afb6030SNick Fitzgerald 19085afb6030SNick Fitzgerald OomOrDynErrorRef::Oom(_) => { 19095afb6030SNick Fitzgerald static DISABLED: Backtrace = Backtrace::disabled(); 19105afb6030SNick Fitzgerald &DISABLED 19115afb6030SNick Fitzgerald } 19128325e1ecSAlex Crichton } 19138325e1ecSAlex Crichton } 19148325e1ecSAlex Crichton } 19158325e1ecSAlex Crichton 19168325e1ecSAlex Crichton /// An iterator over each error in an [`Error`]'s context chain. 19178325e1ecSAlex Crichton /// 19188325e1ecSAlex Crichton /// The iterator yields `&'a (dyn core::error::Error + 'static)` items. 19198325e1ecSAlex Crichton /// 19208325e1ecSAlex Crichton /// Iterates from the most recently added error context towards the root cause. 19218325e1ecSAlex Crichton /// 19228325e1ecSAlex Crichton /// Created by the [`Error::chain`] method. See that method's documentation for 19238325e1ecSAlex Crichton /// more details. 19248325e1ecSAlex Crichton pub struct Chain<'a> { 19258325e1ecSAlex Crichton state: ChainState<'a>, 19268325e1ecSAlex Crichton } 19278325e1ecSAlex Crichton 19288325e1ecSAlex Crichton enum ChainState<'a> { 19295afb6030SNick Fitzgerald Ours(&'a Error), 19308325e1ecSAlex Crichton Core(Option<&'a (dyn core::error::Error + 'static)>), 19318325e1ecSAlex Crichton } 19328325e1ecSAlex Crichton 19338325e1ecSAlex Crichton impl<'a> Chain<'a> { new(error: &'a Error) -> Self19345afb6030SNick Fitzgerald fn new(error: &'a Error) -> Self { 19358325e1ecSAlex Crichton Self { 19368325e1ecSAlex Crichton state: ChainState::Ours(error), 19378325e1ecSAlex Crichton } 19388325e1ecSAlex Crichton } 19398325e1ecSAlex Crichton } 19408325e1ecSAlex Crichton 19418325e1ecSAlex Crichton impl<'a> Iterator for Chain<'a> { 19428325e1ecSAlex Crichton type Item = &'a (dyn core::error::Error + 'static); 19438325e1ecSAlex Crichton 19448325e1ecSAlex Crichton #[inline] next(&mut self) -> Option<Self::Item>19458325e1ecSAlex Crichton fn next(&mut self) -> Option<Self::Item> { 19468325e1ecSAlex Crichton match &mut self.state { 19478325e1ecSAlex Crichton ChainState::Ours(e) => { 19485afb6030SNick Fitzgerald let core = e.inner.as_dyn_core_error(); 19495afb6030SNick Fitzgerald self.state = if let Some(e) = e.inner.source() { 19508325e1ecSAlex Crichton ChainState::Ours(e) 19518325e1ecSAlex Crichton } else { 19528325e1ecSAlex Crichton ChainState::Core(core.source()) 19538325e1ecSAlex Crichton }; 19548325e1ecSAlex Crichton Some(core) 19558325e1ecSAlex Crichton } 19568325e1ecSAlex Crichton ChainState::Core(error) => { 19578325e1ecSAlex Crichton let e = error.take()?; 19588325e1ecSAlex Crichton self.state = ChainState::Core(e.source()); 19598325e1ecSAlex Crichton Some(e) 19608325e1ecSAlex Crichton } 19618325e1ecSAlex Crichton } 19628325e1ecSAlex Crichton } 19638325e1ecSAlex Crichton } 19648325e1ecSAlex Crichton 19658325e1ecSAlex Crichton impl FusedIterator for Chain<'_> {} 19668325e1ecSAlex Crichton 19678325e1ecSAlex Crichton #[cfg(test)] 19688325e1ecSAlex Crichton mod tests { 19698325e1ecSAlex Crichton use super::*; 19708325e1ecSAlex Crichton 19718325e1ecSAlex Crichton #[derive(Debug)] 19728325e1ecSAlex Crichton struct TestError; 19738325e1ecSAlex Crichton 19748325e1ecSAlex Crichton impl fmt::Display for TestError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result19758325e1ecSAlex Crichton fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 19768325e1ecSAlex Crichton fmt::Debug::fmt(self, f) 19778325e1ecSAlex Crichton } 19788325e1ecSAlex Crichton } 19798325e1ecSAlex Crichton 19808325e1ecSAlex Crichton impl core::error::Error for TestError {} 19818325e1ecSAlex Crichton 19828325e1ecSAlex Crichton #[test] from_oom()19838325e1ecSAlex Crichton fn from_oom() { 19848325e1ecSAlex Crichton let mut error = Error::from(OutOfMemory::new(5)); 19858325e1ecSAlex Crichton assert!(error.is::<OutOfMemory>()); 19868325e1ecSAlex Crichton assert!(error.downcast_ref::<OutOfMemory>().is_some()); 19878325e1ecSAlex Crichton assert!(error.downcast_mut::<OutOfMemory>().is_some()); 19888325e1ecSAlex Crichton 19898325e1ecSAlex Crichton // NB: use this module's scope to check that the inner representation is 19908325e1ecSAlex Crichton // `OomOrDynError::Oom` and not a `Box<OutOfMemory> as Box<dyn 19918325e1ecSAlex Crichton // Error>`. This is why this test cannot be in `tests/tests.rs`. 19928325e1ecSAlex Crichton assert!(error.inner.is_oom()); 19938325e1ecSAlex Crichton } 19948325e1ecSAlex Crichton 19958325e1ecSAlex Crichton #[test] dyn_error_and_concrete_error_layouts_are_compatible()19968325e1ecSAlex Crichton fn dyn_error_and_concrete_error_layouts_are_compatible() { 19978325e1ecSAlex Crichton type Concrete = ConcreteError<TestError>; 19988325e1ecSAlex Crichton 19998325e1ecSAlex Crichton let dyn_size = mem::size_of::<DynError>(); 20008325e1ecSAlex Crichton let concrete_size = mem::size_of::<Concrete>(); 20018325e1ecSAlex Crichton assert!( 20028325e1ecSAlex Crichton dyn_size <= concrete_size, 20038325e1ecSAlex Crichton "assertion failed: {dyn_size} <= {concrete_size}" 20048325e1ecSAlex Crichton ); 20058325e1ecSAlex Crichton 20068325e1ecSAlex Crichton let dyn_align = mem::align_of::<DynError>(); 20078325e1ecSAlex Crichton let concrete_align = mem::align_of::<Concrete>(); 20088325e1ecSAlex Crichton assert!( 20098325e1ecSAlex Crichton dyn_align <= concrete_align, 20108325e1ecSAlex Crichton "assertion failed: {dyn_align} <= {concrete_align}" 20118325e1ecSAlex Crichton ); 20128325e1ecSAlex Crichton 20138325e1ecSAlex Crichton let dyn_offset = mem::offset_of!(DynError, vtable); 20148325e1ecSAlex Crichton let concrete_offset = mem::offset_of!(Concrete, vtable); 20158325e1ecSAlex Crichton assert_eq!(dyn_offset, concrete_offset); 20168325e1ecSAlex Crichton 20178325e1ecSAlex Crichton #[cfg(feature = "backtrace")] 20188325e1ecSAlex Crichton { 20198325e1ecSAlex Crichton let dyn_offset = mem::offset_of!(DynError, backtrace); 20208325e1ecSAlex Crichton let concrete_offset = mem::offset_of!(Concrete, backtrace); 20218325e1ecSAlex Crichton assert_eq!(dyn_offset, concrete_offset); 20228325e1ecSAlex Crichton } 20238325e1ecSAlex Crichton } 20248325e1ecSAlex Crichton } 2025