xref: /wasmtime-44.0.1/crates/core/src/error/error.rs (revision ab78bd82)
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