Skip to main content

wasmtime_internal_error/
error.rs

1use super::boxed::try_new_uninit_box;
2use super::context::ContextError;
3use super::ptr::{MutPtr, OwnedPtr, SharedPtr};
4use super::vtable::Vtable;
5use crate::{OutOfMemory, Result};
6use alloc::boxed::Box;
7use core::{
8    any::TypeId,
9    fmt::{self, Debug},
10    iter::FusedIterator,
11    mem,
12    ptr::NonNull,
13};
14#[cfg(feature = "backtrace")]
15use std::backtrace::{Backtrace, BacktraceStatus};
16
17/// Internal extension trait for errors.
18///
19/// # Safety
20///
21/// Safety relies on `ext_is` being implemented correctly. Implementations must
22/// not lie about whether they are or are not an instance of the given type id's
23/// associated type (or a newtype wrapper around that type). Violations will
24/// lead to unsafety.
25pub(crate) unsafe trait ErrorExt: Send + Sync + 'static {
26    /// Get this error as a shared reference to a `dyn core::error::Error` trait
27    /// object.
28    fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static);
29
30    /// Get this error as a boxed `dyn core::error::Error` trait object.
31    fn ext_into_boxed_dyn_core_error(
32        self,
33    ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory>;
34
35    /// Get a shared borrow of the next error in the chain.
36    fn ext_source(&self) -> Option<OomOrDynErrorRef<'_>>;
37
38    /// Get an exclusive borrow of the next error in the chain.
39    fn ext_source_mut(&mut self) -> Option<OomOrDynErrorMut<'_>>;
40
41    /// Take ownership of the next error in the chain.
42    fn ext_take_source(&mut self) -> Option<OomOrDynError>;
43
44    /// Is this error an instance of `T`, where `type_id == TypeId::of::<T>()`
45    /// or a newtype wrapper around that type?
46    ///
47    /// # Safety
48    ///
49    /// Implementations must return `true` only when they are actually a `T`, a
50    /// `#[repr(transparent)]` newtype wrapper around a `T`, or a `#[repr(C)]`
51    /// struct with a `T` as their first field. Safety relies on this invariant.
52    fn ext_is(&self, type_id: TypeId) -> bool;
53
54    /// Move the inner `T` error into the storage referenced by `dest`.
55    ///
56    /// # Safety
57    ///
58    /// Callers must ensure that `dest` is valid for writing a `T` to.
59    ///
60    /// Implementations must ensure that the memory block pointed to by `dest`
61    /// contains a valid, initialized `T` upon successful return.
62    unsafe fn ext_move(self, dest: NonNull<u8>);
63
64    /// Take the backtrace from this error, if any.
65    #[cfg(feature = "backtrace")]
66    fn take_backtrace(&mut self) -> Option<Backtrace>;
67}
68
69/// Morally a `dyn ErrorExt` trait object that holds its own vtable.
70///
71/// Must only ever be used via some kind of indirection (pointer, reference,
72/// `Box`, etc...) that is punning a `ConcreteError<?>` and never directly as an
73/// on-stack value, for example.
74///
75/// See the docs for `Vtable` for details about why we make our own trait
76/// objects.
77///
78/// XXX: Must have a compatible layout with `ConcreteError<E>`. See the
79/// assertions in `BoxedDynError::new` and the
80/// `dyn_error_and_concrete_error_layouts_are_compatible` test below.
81#[repr(C)]
82pub(crate) struct DynError {
83    // Safety: this vtable must always be associated with the `E` for the
84    // `ConcreteError<E>` that this `DynError` is punning.
85    pub(crate) vtable: &'static Vtable,
86    #[cfg(feature = "backtrace")]
87    pub(crate) backtrace: Option<Backtrace>,
88    // error: <?>
89}
90
91/// A `dyn ErrorExt` trait object that we know the concrete type of.
92///
93/// XXX: Must have a compatible layout with `DynError`. See the
94/// assertions in `BoxedDynError::new` and the
95/// `dyn_error_and_concrete_error_layouts_are_compatible` test below.
96#[repr(C)]
97pub(crate) struct ConcreteError<E> {
98    // Safety: this vtable must always be `E`'s vtable. This is ensured in
99    // `BoxDynError::new`.
100    pub(crate) vtable: &'static Vtable,
101    #[cfg(feature = "backtrace")]
102    pub(crate) backtrace: Option<Backtrace>,
103    pub(crate) error: E,
104}
105
106pub(crate) struct BoxedDynError {
107    inner: OwnedPtr<DynError>,
108}
109
110// Safety: `BoxedDynError::new` ensures that every concrete error type we make a
111// `BoxedDynError` from is `Send`.
112unsafe impl Send for BoxedDynError {}
113
114// Safety: `BoxedDynError::new` ensures that every concrete error type we make a
115// `BoxedDynError` from is `Sync`.
116unsafe impl Sync for BoxedDynError {}
117
118impl Drop for BoxedDynError {
119    fn drop(&mut self) {
120        let ptr = self.inner.raw_copy();
121        // Safety: We own the pointer and it is valid for reading/writing
122        // `DynError`s.
123        let inner = unsafe { ptr.as_ref() };
124        let vtable = inner.vtable;
125        // Safety: The vtable is for this pointer's concrete type and the
126        // pointer is valid to deallocate because we are passing ownership in.
127        unsafe {
128            (vtable.drop_and_deallocate)(ptr);
129        }
130    }
131}
132
133impl BoxedDynError {
134    #[inline]
135    fn new<E>(mut error: E) -> Result<Self, OutOfMemory>
136    where
137        // NB: This implies `Send + Sync`, which is necessary for safety.
138        E: ErrorExt,
139    {
140        #[cfg(not(feature = "backtrace"))]
141        let _ = &mut error;
142
143        // Note: do not use `Option::or_else` here to avoid an extra frame
144        // showing up in the backtrace, which would create extra noise for users
145        // to mentally filter out.
146        #[cfg(feature = "backtrace")]
147        let backtrace = match error.take_backtrace() {
148            Some(bt) => bt,
149            None => crate::backtrace::capture(),
150        };
151
152        let boxed = try_new_uninit_box()?;
153        let error = Box::write(
154            boxed,
155            ConcreteError {
156                vtable: Vtable::of::<E>(),
157                #[cfg(feature = "backtrace")]
158                backtrace: Some(backtrace),
159                error,
160            },
161        );
162
163        // We are going to pun the `ConcreteError<E>` pointer into a `DynError`
164        // pointer. Debug assert that their layouts are compatible first.
165        #[cfg(debug_assertions)]
166        {
167            let dyn_size = mem::size_of::<DynError>();
168            let concrete_size = mem::size_of::<ConcreteError<E>>();
169            assert!(
170                dyn_size <= concrete_size,
171                "assertion failed: {dyn_size} <= {concrete_size}"
172            );
173
174            let dyn_align = mem::align_of::<DynError>();
175            let concrete_align = mem::align_of::<ConcreteError<E>>();
176            assert!(
177                dyn_align <= concrete_align,
178                "assertion failed: {dyn_align} <= {concrete_align}"
179            );
180
181            let dyn_offset = mem::offset_of!(DynError, vtable);
182            let concrete_offset = mem::offset_of!(ConcreteError<E>, vtable);
183            assert_eq!(dyn_offset, concrete_offset);
184
185            #[cfg(feature = "backtrace")]
186            {
187                let dyn_offset = mem::offset_of!(DynError, backtrace);
188                let concrete_offset = mem::offset_of!(ConcreteError<E>, backtrace);
189                assert_eq!(dyn_offset, concrete_offset);
190            }
191        }
192
193        let ptr = Box::into_raw(error);
194        let ptr = ptr.cast::<DynError>();
195        // Safety: `Box::into_raw` always returns a non-null pointer.
196        let ptr = unsafe { NonNull::new_unchecked(ptr) };
197        let ptr = OwnedPtr::new(ptr);
198        // Safety: points to a valid `DynError`.
199        Ok(unsafe { Self::from_owned_ptr(ptr) })
200    }
201
202    fn into_owned_ptr(self) -> OwnedPtr<DynError> {
203        let ptr = self.inner.raw_copy();
204        mem::forget(self);
205        ptr
206    }
207
208    /// # Safety
209    ///
210    /// The given pointer must be a valid `DynError` pointer: punning a
211    /// `ConcreteError<?>` and is safe to drop and deallocate with its
212    /// `DynError::vtable` methods.
213    unsafe fn from_owned_ptr(inner: OwnedPtr<DynError>) -> Self {
214        BoxedDynError { inner }
215    }
216}
217
218/// Wasmtime's universal error type.
219///
220/// 99% API-compatible with `anyhow::Error` but additionally allows recovery
221/// from memory exhaustion (see the [`OutOfMemory`] error).
222///
223/// `Error` is similar to `Box<dyn core::error::Error + Send + Sync + 'static>`
224/// but fits in one word instead of two. Additionally, `Result<(), Error>` also
225/// fits in a single word.
226///
227/// When the `"backtrace"` cargo feature is enabled, `Error` contains a
228/// backtrace.
229///
230/// # Creating an `Error`
231///
232/// Because `Error` implements `From<E>` for all types `E` that implement
233/// `core::error::Error + Send + Sync + 'static`, you don't usually need to
234/// explicitly construct an `Error`. When you use `?`-style error propagation,
235/// it will automatically get constructed from the root cause error for you.
236///
237/// Most often when creating an `Error`, you just want to early-exit from the
238/// function, returning `Err(...)`. The [`ensure!`][crate::ensure] macro
239/// early-returns an error when a condition is not met (similar to how `assert!`
240/// panics when a condition is not met) and the [`bail!`][crate::bail] macro
241/// early-returns an error unconditionally.
242///
243/// ```
244/// # use wasmtime_internal_error as wasmtime;
245/// use wasmtime::{bail, ensure, Result};
246///
247/// fn my_fallible_function(x: u32) -> Result<()> {
248///     // This `ensure!` macro invocation is equivalent to
249///     //
250///     //     if x % 2 != 0 {
251///     //         return Err(...);
252///     //     }
253///     ensure!(x % 2 == 0, "{x} is not even!");
254///
255///     // This `bail!` macro invocation is equivalent to
256///     //
257///     //     return Err(...);
258///     bail!("oops, another error! {x}")
259/// }
260/// ```
261///
262/// If you do not want to early-return, just to create the `Error`, then the
263/// [`anyhow!`][crate::anyhow] macro is preferred:
264///
265/// ```
266/// # use wasmtime_internal_error as wasmtime;
267/// use wasmtime::{anyhow, Error};
268///
269/// let x = 42;
270/// let my_error: Error = anyhow!("whoops! {x}");
271/// ```
272///
273/// If, however, you happen to require a constructor function instead of a
274/// macro, you can use either [`Error::new`] or [`Error::msg`]:
275///
276/// ```
277/// # use wasmtime_internal_error as wasmtime;
278/// use wasmtime::Error;
279///
280/// let messages = ["yikes", "uh oh", "ouch"];
281/// let errors = messages
282///     .into_iter()
283///     .map(Error::msg)
284///     .collect::<Vec<_>>();
285/// ```
286///
287/// # Printing an `Error`
288///
289/// Different format strings will print an `Error` differently:
290///
291/// * `{}`: Prints the `Display` of just the first error, without any of the
292///   other errors in the chain or the root cause.
293///
294/// * `{:#}`: Prints the `Display` of the first error, then (if there are more
295///   errors in the chain) a colon, then the display of the second error in the
296///   chain, etc...
297///
298/// * `{:?}`: Prints the `Display` of the first error, then (if there are more
299///   errors in the chain) a newline-separated list of the rest of the errors in
300///   the chain, and finally (if the `"backtrace"` cargo feature is enabled, the
301///   `RUST_BACKTRACE` environment variable is set and non-zero, and the
302///   platform is supported by Rust's standard library's `Backtrace` type) the
303///   captured backtrace is printed.
304///
305///   This is the default formatting used when `fn main() ->
306///   wasmtime::Result<()>` returns an error.
307///
308/// * `{:#?}`: Prints an internal, debugging representation of the `Error`. We
309///   make no guarantees about its stability.
310///
311/// Here is an example showing the different formats for the same error:
312///
313/// ```
314/// # fn _foo() {
315/// #![cfg(all(feature = "backtrace", not(miri)))]
316/// # let _ = unsafe { std::env::set_var("RUST_BACKTRACE", "1") };
317/// # use wasmtime_internal_error as wasmtime;
318/// use wasmtime::{bail, Context as _, Result};
319///
320/// fn uno() -> Result<()> {
321///     bail!("ouch")
322/// }
323///
324/// fn dos() -> Result<()> {
325///     uno().context("whoops")
326/// }
327///
328/// fn tres() -> Result<()> {
329///     dos().context("uh oh")
330/// }
331///
332/// let error = tres().unwrap_err();
333///
334/// println!("{error}");
335/// // Prints:
336/// //
337/// //     uh oh
338///
339/// println!("{error:#}");
340/// // Prints:
341/// //
342/// //     uh oh: whoops: ouch
343///
344/// println!("{error:?}");
345/// // Prints
346/// //
347/// //     uh oh
348/// //
349/// //     Caused by:
350/// //         0: whoops
351/// //         1: ouch
352/// //
353/// //     Stack backtrace:
354/// //       <...>
355/// //        7: example::uno
356/// //        8: example::dos
357/// //        9: example::tres
358/// //       10: example::main
359/// //       <...>
360///
361/// println!("{error:#?}");
362/// // Prints
363/// //
364/// //     Error {
365/// //         <...>
366/// //     }
367/// # }
368/// ```
369///
370/// # Converting a `wasmtime::Error` into an `anyhow::Error`
371///
372/// When the `"anyhow"` feature is enabled, there is a `From<wasmtime::Error>
373/// for anyhow::Error` implementation. You can always call that implementation
374/// explicitly if needed, but `?`-propagation allows the conversion to happen
375/// seamlessly from functions that return a `Result<T, wasmtime::Error>` to
376/// those that return a `Result<U, anyhow::Error>`.
377///
378/// ```
379/// # fn _foo() {
380/// #![cfg(feature = "anyhow")]
381/// # use wasmtime_internal_error as wasmtime;
382///
383/// fn foo() -> Result<(), wasmtime::Error> {
384///     wasmtime::bail!("decontamination failure")
385/// }
386///
387/// fn bar() -> Result<(), anyhow::Error> {
388///     foo()?; // `?` is auto-converting here!
389///     Ok(())
390/// }
391///
392/// let error = bar().unwrap_err();
393/// assert_eq!(error.to_string(), "decontamination failure");
394/// # }
395/// ```
396///
397/// # Converting an `anyhow::Error` into a `wasmtime::Error`
398///
399/// When the `"anyhow"` feature is enabled, there is an `Error::from_anyhow`
400/// constructor that you may use to convert an `anyhow::Error` into a
401/// `wasmtime::Error`. (Unfortunately trait coherence does not allow us a
402/// `From<anyhow::Error> for wasmtime::Error` implementation.) This will
403/// most-often be used in combination with `Result::map_err`:
404///
405/// ```
406/// # fn _foo() {
407/// #![cfg(feature = "anyhow")]
408/// # use wasmtime_internal_error as wasmtime;
409///
410/// fn baz() -> Result<(), anyhow::Error> {
411///     anyhow::bail!("oops I ate worms")
412/// }
413///
414/// fn qux() -> Result<(), wasmtime::Error> {
415///     baz().map_err(wasmtime::Error::from_anyhow)?;
416///     Ok(())
417/// }
418///
419/// let error = qux().unwrap_err();
420/// assert_eq!(error.to_string(), "oops I ate worms");
421/// # }
422/// ```
423#[repr(transparent)]
424pub struct Error {
425    pub(crate) inner: OomOrDynError,
426}
427
428/// For performance, it is important that `Error` and `Result<()>` fit in a
429/// single word so that they can be passed in registers by rustc/llvm, rather
430/// than on the stack, when used as a function's return type.
431const _ERROR_IS_ONE_WORD_LARGE: () = assert!(mem::size_of::<Error>() == mem::size_of::<usize>());
432const _RESULT_OF_UNIT_IS_ONE_WORD_LARGE: () =
433    assert!(mem::size_of::<Result<()>>() == mem::size_of::<usize>());
434
435impl fmt::Debug for Error {
436    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
437        if f.alternate() {
438            return f
439                .debug_struct("Error")
440                .field("inner", &self.inner.unpack())
441                .finish();
442        }
443
444        let inner = self.inner.unpack();
445        inner.display(f)?;
446
447        if let Some(source) = inner.source() {
448            f.write_str("\n\nCaused by:\n")?;
449            for (i, e) in Chain::new(source).enumerate() {
450                writeln!(f, "\t{i}: {e}")?;
451            }
452        }
453
454        #[cfg(feature = "backtrace")]
455        {
456            let backtrace = inner.backtrace();
457            if let BacktraceStatus::Captured = backtrace.status() {
458                f.write_str("\nStack backtrace:\n")?;
459                fmt::Display::fmt(backtrace, f)?;
460            }
461        }
462
463        Ok(())
464    }
465}
466
467impl fmt::Display for Error {
468    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
469        let inner = self.inner.unpack();
470        inner.display(f)?;
471
472        if f.alternate() {
473            if let Some(e) = inner.source() {
474                for e in Chain::new(e) {
475                    write!(f, ": {e}")?;
476                }
477            }
478        }
479
480        Ok(())
481    }
482}
483
484impl<E> From<E> for Error
485where
486    E: core::error::Error + Send + Sync + 'static,
487{
488    fn from(error: E) -> Self {
489        Self::new(error)
490    }
491}
492
493impl From<Error> for Box<dyn core::error::Error + Send + Sync + 'static> {
494    #[inline]
495    fn from(error: Error) -> Self {
496        error.into_boxed_dyn_error()
497    }
498}
499
500impl From<Error> for Box<dyn core::error::Error + Send + 'static> {
501    #[inline]
502    fn from(error: Error) -> Self {
503        error.into_boxed_dyn_error()
504    }
505}
506
507impl From<Error> for Box<dyn core::error::Error + 'static> {
508    #[inline]
509    fn from(error: Error) -> Self {
510        error.into_boxed_dyn_error()
511    }
512}
513
514/// Convert a [`Error`] into an [`anyhow::Error`].
515///
516/// # Example
517///
518/// ```
519/// # use wasmtime_internal_error as wasmtime;
520/// let wasmtime_error = wasmtime::Error::msg("whoops");
521/// let anyhow_error = anyhow::Error::from(wasmtime_error);
522/// ```
523//
524// Unfortunately, we can't also implement `From<anyhow::Error> for Error`
525// because of trait coherence. From Rust's trait system's point of view,
526// `anyhow` could theoretically add an `core::error::Error for anyhow::Error`
527// implementation, which would make our desired `From<anyhow::Error>`
528// implementation conflict with our existing `From<E: core::error::Error>`
529// implementation. They cannot in fact add that implementation, however, because
530// they already have a `From<E: core::error::Error> for anyhow::Error`
531// implementation and so adding `core::error::Error for anyhow::Error` would
532// cause that impl to conflict with `From<T> for T` (which is the same reason we
533// cannot implement `core::error::Error for Error`). Nonetheless, our hands are
534// tied here.
535#[cfg(feature = "anyhow")]
536impl From<Error> for anyhow::Error {
537    #[inline]
538    fn from(e: Error) -> Self {
539        anyhow::Error::from_boxed(e.into_boxed_dyn_error())
540    }
541}
542
543impl core::ops::Deref for Error {
544    type Target = dyn core::error::Error + Send + Sync + 'static;
545
546    fn deref(&self) -> &Self::Target {
547        self.as_ref()
548    }
549}
550
551impl AsRef<dyn core::error::Error> for Error {
552    #[inline]
553    fn as_ref(&self) -> &(dyn core::error::Error + 'static) {
554        self.inner.unpack().as_dyn_core_error()
555    }
556}
557
558impl AsRef<dyn core::error::Error + Send + Sync> for Error {
559    #[inline]
560    fn as_ref(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
561        self.inner.unpack().as_dyn_core_error()
562    }
563}
564
565impl Error {
566    /// Construct a new `Error` from a type that implements
567    /// `core::error::Error`.
568    ///
569    /// Calling [`error.is::<E>()`][Error::is] will return `true` for the new
570    /// error (unless there was a memory allocation failure).
571    ///
572    /// This boxes the inner error, but if that box allocation fails, then this
573    /// function returns an `Error` where
574    /// [`error.is::<OutOfMemory>()`][crate::OutOfMemory] is true.
575    ///
576    /// # Example
577    ///
578    /// ```
579    /// # use wasmtime_internal_error as wasmtime;
580    /// use wasmtime::Error;
581    ///
582    /// let error = Error::new(std::fmt::Error);
583    /// ```
584    pub fn new<E>(error: E) -> Self
585    where
586        E: core::error::Error + Send + Sync + 'static,
587    {
588        if TypeId::of::<E>() == TypeId::of::<OutOfMemory>() {
589            return Error {
590                inner: OutOfMemory::new().into(),
591            };
592        }
593
594        Self::from_error_ext(ForeignError(error))
595    }
596
597    /// Construct a new `Error` from any type that implements `Debug` and
598    /// `Display`.
599    ///
600    /// Calling [`error.is::<M>()`][Error::is] will return `true` for the new
601    /// error (unless there was a memory allocation failure).
602    ///
603    /// This boxes the inner `M` type, but if that box allocation fails, then
604    /// this function returns an `Error` where
605    /// [`error.is::<OutOfMemory>()`][crate::OutOfMemory] is true.
606    ///
607    /// # Example
608    ///
609    /// ```
610    /// # use wasmtime_internal_error as wasmtime;
611    /// use wasmtime::Error;
612    ///
613    /// let error = Error::msg("hello");
614    /// ```
615    pub fn msg<M>(message: M) -> Self
616    where
617        M: fmt::Debug + fmt::Display + Send + Sync + 'static,
618    {
619        Self::from_error_ext(MessageError(message))
620    }
621
622    /// Create an `Error` from a `Box<dyn core::error::Error>`.
623    ///
624    /// This is useful when converting errors from other universal-error
625    /// libraries into this crate's `Error` type. Prefer [`Error::from_anyhow`]
626    /// for converting `anyhow::Error`s into `Error`s, as that preserves
627    /// `error.is::<anyhow::Error>()`.
628    ///
629    /// Calling [`error.is::<Box<dyn core::error::Error + Send + Sync +
630    /// 'static>>()`][Error::is] will return `true` for the new error (unless
631    /// there was a memory allocation failure).
632    ///
633    /// This reboxes the inner error, but if that box allocation fails, then
634    /// this function returns an `Error` where
635    /// [`error.is::<OutOfMemory>()`][crate::OutOfMemory] is true.
636    ///
637    /// # Example
638    ///
639    /// ```
640    /// # fn _foo() {
641    /// #![cfg(all(feature = "std", feature = "anyhow"))]
642    /// # use wasmtime_internal_error as wasmtime;
643    /// use std::error::Error;
644    ///
645    /// let anyhow_error = anyhow::Error::msg("whoops");
646    /// let boxed_error: Box<dyn Error + Send + Sync + 'static> = anyhow_error.into_boxed_dyn_error();
647    /// let wasmtime_error = wasmtime::Error::from_boxed(boxed_error);
648    /// # }
649    /// ```
650    pub fn from_boxed(error: Box<dyn core::error::Error + Send + Sync + 'static>) -> Self {
651        Self::from_error_ext(BoxedError(error))
652    }
653
654    /// Convert an `anyhow::Error` into an `Error`.
655    ///
656    /// Calling [`error.is::<anyhow::Error>()`][Error::is] will return `true`
657    /// for the new error (unless there was a memory allocation failure).
658    ///
659    /// This reboxes the `anyhow::Error`, but if that box allocation fails, then
660    /// this function returns an `Error` where
661    /// [`error.is::<OutOfMemory>()`][crate::OutOfMemory] is true.
662    ///
663    /// # Example
664    ///
665    /// ```
666    /// # fn _foo() {
667    /// #![cfg(all(feature = "std", feature = "anyhow"))]
668    /// # use wasmtime_internal_error as wasmtime;
669    /// let anyhow_error = anyhow::Error::msg("failed to flim the flam");
670    /// let wasmtime_error = wasmtime::Error::from_anyhow(anyhow_error);
671    /// assert_eq!(
672    ///     wasmtime_error.to_string(),
673    ///     "failed to flim the flam",
674    /// );
675    /// # }
676    /// ```
677    #[cfg(feature = "anyhow")]
678    #[inline]
679    pub fn from_anyhow(error: anyhow::Error) -> Self {
680        Self::from_error_ext(AnyhowError(error))
681    }
682
683    /// Add additional context to this error.
684    ///
685    /// The new context will show up first in the error chain, and the original
686    /// error will come next.
687    ///
688    /// This is similar to the [`Context::context`] trait method, but because it
689    /// is a method directly on [`Error`], there is no need for lazily-computing
690    /// the error context (like `with_context` does).
691    ///
692    /// Calling [`error.is::<C>()`][Error::is] will return `true` for the new
693    /// error (unless there was a memory allocation failure) in addition to any
694    /// other types `T` for which it was already the case that
695    /// `error.is::<T>()`.
696    ///
697    /// This boxes the inner `C` type, but if that box allocation fails, then
698    /// this function returns an `Error` where
699    /// [`error.is::<OutOfMemory>()`][crate::OutOfMemory] is true.
700    ///
701    /// # Example
702    ///
703    /// ```
704    /// # use wasmtime_internal_error as wasmtime;
705    /// use wasmtime::Error;
706    ///
707    /// let error = Error::msg("root cause");
708    /// let error = error.context("failed to bonkinate");
709    /// let error = error.context("cannot frob the blobbins");
710    ///
711    /// assert!(
712    ///     format!("{error:?}").contains(
713    ///         r#"
714    /// cannot frob the blobbins
715    ///
716    /// Caused by:
717    /// 	0: failed to bonkinate
718    /// 	1: root cause
719    ///         "#.trim(),
720    ///     ),
721    /// );
722    /// ```
723    pub fn context<C>(self, context: C) -> Self
724    where
725        C: fmt::Display + Send + Sync + 'static,
726    {
727        if self.inner.is_oom() {
728            self
729        } else {
730            Self::from_error_ext(ContextError {
731                context,
732                error: Some(self),
733            })
734        }
735    }
736
737    #[inline]
738    pub(crate) fn from_error_ext(error: impl ErrorExt) -> Self {
739        match BoxedDynError::new(error) {
740            Ok(boxed) => Error {
741                inner: boxed.into(),
742            },
743            Err(oom) => out_of_line_slow_path!(Error { inner: oom.into() }),
744        }
745    }
746
747    /// Get this error's backtrace.
748    ///
749    /// Backtraces will be automatically captured on initial `Error` creation
750    /// when all of the following conditions are met:
751    ///
752    /// * This crate's `"backtrace"` cargo feature is enabled
753    /// * Rust's `std::backtrace::Backtrace` supports the platform
754    /// * The `RUST_BACKTRACE` or `RUST_LIB_BACKTRACE` environment variables
755    ///   are set and non-zero
756    ///
757    /// See [the `std::backtrace::Backtrace`
758    /// documentation](https://doc.rust-lang.org/stable/std/backtrace/struct.Backtrace.html)
759    /// for more details on backtraces.
760    ///
761    /// Note that `std::backtrace::Backtrace` does not provide a
762    /// fallible-capture mechanism that returns an error, rather than aborting
763    /// the process, when it encounters memory exhaustion. If you require
764    /// out-of-memory error handling, do not enable this crate's `"backtrace"`
765    /// cargo feature.
766    ///
767    /// # Example
768    ///
769    /// ```
770    /// # fn _foo() {
771    /// #![cfg(feature = "backtrace")]
772    /// # use wasmtime_internal_error as wasmtime;
773    /// use std::backtrace::BacktraceStatus;
774    /// use wasmtime::Error;
775    ///
776    /// let error = Error::msg("whoops");
777    ///
778    /// let backtrace = error.backtrace();
779    /// if let BacktraceStatus::Captured = backtrace.status() {
780    ///     println!("error backtrace is:\n{backtrace}");
781    /// }
782    /// # }
783    /// ```
784    #[inline]
785    #[cfg(feature = "backtrace")]
786    pub fn backtrace(&self) -> &Backtrace {
787        self.inner.unpack().backtrace()
788    }
789
790    /// Iterate over this error's context chain.
791    ///
792    /// The iterator yields `&(dyn core::error::Error + 'static)` items.
793    ///
794    /// Iterates from the most recently added error context towards the root
795    /// cause.
796    ///
797    /// # Example
798    ///
799    /// ```
800    /// # use wasmtime_internal_error as wasmtime;
801    /// use wasmtime::Error;
802    ///
803    /// let error = Error::msg("root cause");
804    /// let error = error.context("failed to reticulate splines");
805    /// let error = error.context("aborting launch");
806    ///
807    /// let messages: Vec<_> = error.chain().map(|e| e.to_string()).collect();
808    /// assert_eq!(
809    ///     messages,
810    ///     ["aborting launch", "failed to reticulate splines", "root cause"],
811    /// );
812    /// ```
813    #[inline]
814    pub fn chain(&self) -> Chain<'_> {
815        Chain::new(self.inner.unpack())
816    }
817
818    /// Get the last error in the context chain.
819    ///
820    /// # Example
821    ///
822    /// ```
823    /// # use wasmtime_internal_error as wasmtime;
824    /// use wasmtime::Error;
825    ///
826    /// let error = Error::msg("ghosts");
827    /// let error = error.context("failed to reticulate splines");
828    /// let error = error.context("aborting launch");
829    ///
830    /// assert_eq!(
831    ///     error.root_cause().to_string(),
832    ///     "ghosts",
833    /// );
834    /// ```
835    #[inline]
836    pub fn root_cause(&self) -> &(dyn core::error::Error + 'static) {
837        self.chain().last().expect("chain is always non-empty")
838    }
839
840    /// Is this an `E` error?
841    ///
842    /// Returns true if any error in the context chain is an `E`.
843    ///
844    /// # Example
845    ///
846    /// ```
847    /// # use wasmtime_internal_error as wasmtime;
848    /// use wasmtime::{Error, OutOfMemory};
849    ///
850    /// let oom = Error::from(OutOfMemory::new());
851    /// assert!(oom.is::<OutOfMemory>());
852    /// assert!(!oom.is::<std::num::TryFromIntError>());
853    ///
854    /// // Here is an example with additional error context.
855    /// let error = Error::from(u8::try_from(u32::MAX).unwrap_err());
856    /// let error = error.context(format!("cannot convert {} into a u8", u32::MAX));
857    /// assert!(
858    ///     error.is::<std::num::TryFromIntError>(),
859    ///     "root cause is an int conversion failure",
860    /// );
861    /// assert!(
862    ///     error.is::<String>(),
863    ///     "additional context is a `String`",
864    /// );
865    /// assert!(
866    ///     !error.is::<OutOfMemory>(),
867    ///     "no error in the chain is an out-of-memory error",
868    /// );
869    /// ```
870    pub fn is<E>(&self) -> bool
871    where
872        E: fmt::Display + fmt::Debug + Send + Sync + 'static,
873    {
874        let mut error = Some(self.inner.unpack());
875        while let Some(e) = error {
876            if e.is::<E>() {
877                return true;
878            } else {
879                error = e.source();
880            }
881        }
882        false
883    }
884
885    /// Downcast this error into an `E`, taking ownership.
886    ///
887    /// If this error is an `E`, then `Ok(E)` is returned. Otherwise,
888    /// `Err(self)` is returned.
889    ///
890    /// If there are multiple instances of `E` in this error's chain, then the
891    /// first (as encountered by [`Error::chain`]'s iteration order) is
892    /// returned.
893    ///
894    /// # Example
895    ///
896    /// ```
897    /// # use wasmtime_internal_error as wasmtime;
898    /// use wasmtime::{Error, OutOfMemory};
899    ///
900    /// let error = Error::msg("whoops");
901    ///
902    /// // `error` is not an `OutOfMemory`.
903    /// let downcasted = error.downcast::<OutOfMemory>();
904    /// assert!(downcasted.is_err());
905    ///
906    /// // Get the original `error` back.
907    /// let error = downcasted.unwrap_err();
908    ///
909    /// // `error` is an `&str`.
910    /// let downcasted = error.downcast::<&str>();
911    /// assert!(downcasted.is_ok());
912    /// assert_eq!(downcasted.unwrap(), "whoops");
913    ///
914    /// // If there are multiple `E`s in the chain, the first in the chain is
915    /// // returned.
916    /// let error = Error::msg("root cause");
917    /// let error = error.context("failed to recombobulate");
918    /// assert_eq!(
919    ///     error.downcast::<&str>().unwrap(),
920    ///     "failed to recombobulate",
921    /// );
922    /// ```
923    pub fn downcast<E>(self) -> Result<E, Self>
924    where
925        E: fmt::Display + fmt::Debug + Send + Sync + 'static,
926    {
927        if !self.is::<E>() {
928            return Err(self);
929        }
930
931        let mut value = mem::MaybeUninit::<E>::uninit();
932
933        // Safety: this error is an `E` and the given pointer is valid to write
934        // an `E` to.
935        unsafe {
936            self.inner
937                .downcast(TypeId::of::<E>(), NonNull::from(&mut value).cast::<u8>());
938        }
939
940        // Safety: `OomOrDynError::downcast` guarantees that the given pointer's
941        // data is initialized upon successful return.
942        Ok(unsafe { value.assume_init() })
943    }
944
945    /// Downcast this error into a shared `&E` borrow.
946    ///
947    /// If this error is an `E`, then `Some(&E)` is returned. Otherwise, `None`
948    /// is returned.
949    ///
950    /// If there are multiple instances of `E` in this error's chain, then the
951    /// first (as encountered by [`Error::chain`]'s iteration order) is
952    /// returned.
953    ///
954    /// # Example
955    ///
956    /// ```
957    /// # use wasmtime_internal_error as wasmtime;
958    /// use wasmtime::{Error, OutOfMemory};
959    ///
960    /// let error = Error::msg("whoops");
961    ///
962    /// // `error` is not an `OutOfMemory`.
963    /// assert!(error.downcast_ref::<OutOfMemory>().is_none());
964    ///
965    /// // `error` is an `&str`.
966    /// assert!(error.downcast_ref::<&str>().is_some());
967    /// assert_eq!(*error.downcast_ref::<&str>().unwrap(), "whoops");
968    ///
969    /// // If there are multiple `E`s in the chain, the first in the chain is
970    /// // returned.
971    /// let error = Error::msg("root cause");
972    /// let error = error.context("failed to recombobulate");
973    /// assert_eq!(
974    ///     *error.downcast_ref::<&str>().unwrap(),
975    ///     "failed to recombobulate",
976    /// );
977    /// ```
978    pub fn downcast_ref<E>(&self) -> Option<&E>
979    where
980        E: fmt::Display + fmt::Debug + Send + Sync + 'static,
981    {
982        let mut error = Some(self.inner.unpack());
983        while let Some(e) = error {
984            if e.is::<E>() {
985                return Some(match e {
986                    OomOrDynErrorRef::DynError(ptr) => {
987                        let ptr = ptr.cast::<ConcreteError<E>>();
988                        // Safety: we own the pointer, it is valid for reading,
989                        // and we checked that it is an `E`.
990                        let r = unsafe { ptr.as_ref() };
991                        &r.error
992                    }
993                    OomOrDynErrorRef::Oom(oom) => {
994                        // Note: Even though we know that `E == OutOfMemory`
995                        // here, we still have to do this dance to satisfy the
996                        // type system.
997                        debug_assert_eq!(TypeId::of::<E>(), TypeId::of::<OutOfMemory>());
998                        let ptr = NonNull::from(oom);
999                        let ptr = ptr.cast::<E>();
1000                        // Safety: the pointer points to `oom`, which is valid
1001                        // for creating a shared reference to.
1002                        unsafe { ptr.as_ref() }
1003                    }
1004                });
1005            } else {
1006                error = e.source();
1007            }
1008        }
1009        None
1010    }
1011
1012    /// Downcast this error into an exclusive `&mut E` borrow.
1013    ///
1014    /// If this error is an `E`, then `Some(&mut E)` is returned. Otherwise,
1015    /// `None` is returned.
1016    ///
1017    /// If there are multiple instances of `E` in this error's chain, then the
1018    /// first (as encountered by [`Error::chain`]'s iteration order) is
1019    /// returned.
1020    ///
1021    /// # Example
1022    ///
1023    /// ```
1024    /// # use wasmtime_internal_error as wasmtime;
1025    /// use wasmtime::{Error, OutOfMemory};
1026    ///
1027    /// let mut error = Error::msg("whoops");
1028    ///
1029    /// // `error` is not an `OutOfMemory`.
1030    /// assert!(error.downcast_mut::<OutOfMemory>().is_none());
1031    ///
1032    /// // `error` is an `&str`.
1033    /// assert!(error.downcast_mut::<&str>().is_some());
1034    /// assert_eq!(*error.downcast_mut::<&str>().unwrap(), "whoops");
1035    /// *error.downcast_mut::<&str>().unwrap() = "yikes";
1036    /// assert_eq!(*error.downcast_mut::<&str>().unwrap(), "yikes");
1037    ///
1038    /// // If there are multiple `E`s in the chain, the first in the chain is
1039    /// // returned.
1040    /// let error = Error::msg("root cause");
1041    /// let mut error = error.context("failed to recombobulate");
1042    /// assert_eq!(
1043    ///     *error.downcast_mut::<&str>().unwrap(),
1044    ///     "failed to recombobulate",
1045    /// );
1046    /// ```
1047    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
1048    where
1049        E: fmt::Display + fmt::Debug + Send + Sync + 'static,
1050    {
1051        let mut error = Some(self.inner.unpack_mut());
1052        while let Some(mut e) = error.take() {
1053            if e.as_ref().is::<E>() {
1054                return Some(match e {
1055                    OomOrDynErrorMut::DynError(ptr) => {
1056                        let mut ptr = ptr.cast::<ConcreteError<E>>();
1057                        // Safety: we own the pointer, it is valid for reading
1058                        // and writing, and we checked that it is an `E`.
1059                        let r = unsafe { ptr.as_mut() };
1060                        &mut r.error
1061                    }
1062                    OomOrDynErrorMut::Oom(oom) => {
1063                        // Note: Even though we know that `E == OutOfMemory`
1064                        // here, we still have to do this dance to satisfy the
1065                        // type system.
1066                        debug_assert_eq!(TypeId::of::<E>(), TypeId::of::<OutOfMemory>());
1067                        let ptr = NonNull::from(oom);
1068                        let mut ptr = ptr.cast::<E>();
1069                        // Safety: the pointer points to `oom`, which is valid
1070                        // for creating an exclusive reference to.
1071                        unsafe { ptr.as_mut() }
1072                    }
1073                });
1074            } else {
1075                error = e.source_mut();
1076            }
1077        }
1078        None
1079    }
1080
1081    /// Convert this error into a `Box<dyn core::error::Error>`.
1082    ///
1083    /// This is useful for integrating this crate's `Error`s into other
1084    /// universal-error libraries.
1085    ///
1086    /// This functionality is also available via a `From<Error> for Box<dyn
1087    /// core::error::Error + Send + Sync + 'static>>` implementation.
1088    ///
1089    /// # Example
1090    ///
1091    /// ```
1092    /// # fn _foo() {
1093    /// #![cfg(feature = "std")]
1094    /// use std::fmt;
1095    ///
1096    /// /// A stub representing some other error library.
1097    /// #[derive(Debug)]
1098    /// pub struct OtherError {
1099    ///     inner: Box<dyn std::error::Error + Send + Sync + 'static>,
1100    /// }
1101    ///
1102    /// impl fmt::Display for OtherError {
1103    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1104    ///         fmt::Display::fmt(&self.inner, f)
1105    ///     }
1106    /// }
1107    ///
1108    /// impl std::error::Error for OtherError {
1109    ///     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1110    ///         self.inner.source()
1111    ///     }
1112    /// }
1113    ///
1114    /// impl OtherError {
1115    ///     /// Create an `OtherError` from another error.
1116    ///     pub fn new<E>(error: E) -> Self
1117    ///     where
1118    ///         E: std::error::Error + Send + Sync + 'static,
1119    ///     {
1120    ///         OtherError { inner: Box::new(error) }
1121    ///     }
1122    ///
1123    ///     /// Create an `OtherError` from another, already-boxed error.
1124    ///     pub fn from_boxed(error: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self {
1125    ///         OtherError { inner: error }
1126    ///     }
1127    /// }
1128    ///
1129    /// # use wasmtime_internal_error as wasmtime;
1130    /// use wasmtime::Error;
1131    ///
1132    /// // Create an `Error`.
1133    /// let error = Error::msg("whoopsies");
1134    ///
1135    /// // Convert it into an `OtherError`.
1136    /// let error = OtherError::from_boxed(error.into_boxed_dyn_error());
1137    /// # }
1138    /// ```
1139    #[inline]
1140    pub fn into_boxed_dyn_error(self) -> Box<dyn core::error::Error + Send + Sync + 'static> {
1141        self.inner.into_boxed_dyn_core_error()
1142    }
1143}
1144
1145/// `ErrorExt` wrapper for foreign `core::error::Error` implementations.
1146///
1147/// For `Error::new`'s use only.
1148///
1149/// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is`
1150/// implementation and the casts that are performed using that method's return
1151/// value.
1152#[repr(transparent)]
1153struct ForeignError<E>(E);
1154
1155// Safety: `ext_is` is correct, `ext_move` always writes to `dest`.
1156unsafe impl<E> ErrorExt for ForeignError<E>
1157where
1158    E: core::error::Error + Send + Sync + 'static,
1159{
1160    fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
1161        &self.0
1162    }
1163
1164    fn ext_into_boxed_dyn_core_error(
1165        self,
1166    ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> {
1167        let boxed = try_new_uninit_box()?;
1168        Ok(Box::write(boxed, self.0) as _)
1169    }
1170
1171    fn ext_source(&self) -> Option<OomOrDynErrorRef<'_>> {
1172        None
1173    }
1174
1175    fn ext_source_mut(&mut self) -> Option<OomOrDynErrorMut<'_>> {
1176        None
1177    }
1178
1179    fn ext_take_source(&mut self) -> Option<OomOrDynError> {
1180        None
1181    }
1182
1183    unsafe fn ext_move(self, dest: NonNull<u8>) {
1184        // Safety: implied by this trait method's safety contract.
1185        unsafe {
1186            dest.cast::<E>().write(self.0);
1187        }
1188    }
1189
1190    fn ext_is(&self, type_id: TypeId) -> bool {
1191        // NB: need to check type id of `E`, not `Self` aka
1192        // `ForeignError<E>`.
1193        type_id == TypeId::of::<E>()
1194    }
1195
1196    #[cfg(feature = "backtrace")]
1197    fn take_backtrace(&mut self) -> Option<Backtrace> {
1198        None
1199    }
1200}
1201
1202/// `ErrorExt` wrapper for types given to `Error::msg`.
1203///
1204/// For `Error::msg`'s use only.
1205///
1206/// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is`
1207/// implementation and the casts that are performed using that method's return
1208/// value.
1209#[repr(transparent)]
1210struct MessageError<M>(M);
1211
1212impl<M> fmt::Debug for MessageError<M>
1213where
1214    M: fmt::Debug,
1215{
1216    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1217        self.0.fmt(f)
1218    }
1219}
1220
1221impl<M> fmt::Display for MessageError<M>
1222where
1223    M: fmt::Display,
1224{
1225    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1226        self.0.fmt(f)
1227    }
1228}
1229
1230impl<M> core::error::Error for MessageError<M> where M: fmt::Debug + fmt::Display {}
1231
1232// Safety: `ext_is` is implemented correctly and `ext_move` always
1233// writes to its pointer.
1234unsafe impl<M> ErrorExt for MessageError<M>
1235where
1236    M: fmt::Debug + fmt::Display + Send + Sync + 'static,
1237{
1238    fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
1239        self
1240    }
1241
1242    fn ext_into_boxed_dyn_core_error(
1243        self,
1244    ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> {
1245        let boxed = try_new_uninit_box()?;
1246        Ok(Box::write(boxed, self) as _)
1247    }
1248
1249    fn ext_source(&self) -> Option<OomOrDynErrorRef<'_>> {
1250        None
1251    }
1252
1253    fn ext_source_mut(&mut self) -> Option<OomOrDynErrorMut<'_>> {
1254        None
1255    }
1256
1257    fn ext_take_source(&mut self) -> Option<OomOrDynError> {
1258        None
1259    }
1260
1261    fn ext_is(&self, type_id: TypeId) -> bool {
1262        // NB: need to check type id of `M`, not `Self` aka
1263        // `MessageError<M>`.
1264        type_id == TypeId::of::<M>()
1265    }
1266
1267    unsafe fn ext_move(self, dest: NonNull<u8>) {
1268        // Safety: implied by this trait method's contract.
1269        unsafe {
1270            dest.cast::<M>().write(self.0);
1271        }
1272    }
1273
1274    #[cfg(feature = "backtrace")]
1275    fn take_backtrace(&mut self) -> Option<Backtrace> {
1276        None
1277    }
1278}
1279
1280/// `ErrorExt` wrapper for `Box<dyn core::error::Error>`.
1281///
1282/// For `Error::from_boxed`'s use only.
1283///
1284/// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is`
1285/// implementation and the casts that are performed using that method's return
1286/// value.
1287#[repr(transparent)]
1288struct BoxedError(Box<dyn core::error::Error + Send + Sync + 'static>);
1289
1290// Safety: `ext_is` is implemented correctly and `ext_move` always
1291// writes to its pointer.
1292unsafe impl ErrorExt for BoxedError {
1293    fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
1294        &*self.0
1295    }
1296
1297    fn ext_into_boxed_dyn_core_error(
1298        self,
1299    ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> {
1300        Ok(self.0)
1301    }
1302
1303    fn ext_source(&self) -> Option<OomOrDynErrorRef<'_>> {
1304        None
1305    }
1306
1307    fn ext_source_mut(&mut self) -> Option<OomOrDynErrorMut<'_>> {
1308        None
1309    }
1310
1311    fn ext_take_source(&mut self) -> Option<OomOrDynError> {
1312        None
1313    }
1314
1315    fn ext_is(&self, type_id: TypeId) -> bool {
1316        // NB: need to check type id of `BoxDynSendSyncError`, not
1317        // `BoxedError`.
1318        type_id == TypeId::of::<Box<dyn core::error::Error + Send + Sync + 'static>>()
1319    }
1320
1321    unsafe fn ext_move(self, dest: NonNull<u8>) {
1322        // Safety: implied by this trait method's contract.
1323        unsafe {
1324            dest.cast::<Box<dyn core::error::Error + Send + Sync + 'static>>()
1325                .write(self.0);
1326        }
1327    }
1328
1329    #[cfg(feature = "backtrace")]
1330    fn take_backtrace(&mut self) -> Option<Backtrace> {
1331        None
1332    }
1333}
1334
1335/// `ErrorExt` wrapper for `anyhow::Error`.
1336///
1337/// For `Error::from_anyhow`'s use only.
1338///
1339/// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is`
1340/// implementation and the casts that are performed using that method's return
1341/// value.
1342#[repr(transparent)]
1343#[cfg(feature = "anyhow")]
1344struct AnyhowError(anyhow::Error);
1345
1346// Safety: `ext_is` is implemented correctly and `ext_move` always
1347// writes to its pointer.
1348#[cfg(feature = "anyhow")]
1349unsafe impl ErrorExt for AnyhowError {
1350    fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
1351        self.0.as_ref()
1352    }
1353
1354    fn ext_into_boxed_dyn_core_error(
1355        self,
1356    ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> {
1357        Ok(self.0.into_boxed_dyn_error())
1358    }
1359
1360    fn ext_source(&self) -> Option<OomOrDynErrorRef<'_>> {
1361        None
1362    }
1363
1364    fn ext_source_mut(&mut self) -> Option<OomOrDynErrorMut<'_>> {
1365        None
1366    }
1367
1368    fn ext_take_source(&mut self) -> Option<OomOrDynError> {
1369        None
1370    }
1371
1372    fn ext_is(&self, type_id: TypeId) -> bool {
1373        // NB: need to check type id of `BoxDynSendSyncError`, not
1374        // `AnyhowError`.
1375        type_id == TypeId::of::<anyhow::Error>()
1376    }
1377
1378    unsafe fn ext_move(self, dest: NonNull<u8>) {
1379        // Safety: implied by this trait method's contract.
1380        unsafe {
1381            dest.cast::<anyhow::Error>().write(self.0);
1382        }
1383    }
1384
1385    #[cfg(feature = "backtrace")]
1386    fn take_backtrace(&mut self) -> Option<Backtrace> {
1387        None
1388    }
1389}
1390
1391pub(crate) enum OomOrDynErrorRef<'a> {
1392    // Safety: this must always be a valid pointer to read a `DynError` from for
1393    // the `'a` lifetime.
1394    DynError(SharedPtr<'a, DynError>),
1395
1396    Oom(&'a OutOfMemory),
1397}
1398
1399impl<'a> Debug for OomOrDynErrorRef<'a> {
1400    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1401        self.debug(f)
1402    }
1403}
1404
1405impl<'a> OomOrDynErrorRef<'a> {
1406    fn display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1407        match self {
1408            OomOrDynErrorRef::DynError(e) => {
1409                // Safety: invariant of this type.
1410                let vtable = unsafe { e.as_ref().vtable };
1411                // Safety: using the vtable associated with this pointer's
1412                // concrete type and the pointer is valid.
1413                unsafe { (vtable.display)(*e, f) }
1414            }
1415            OomOrDynErrorRef::Oom(oom) => fmt::Display::fmt(oom, f),
1416        }
1417    }
1418
1419    fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1420        match *self {
1421            OomOrDynErrorRef::Oom(oom) => f.debug_tuple("Oom").field(oom).finish(),
1422            OomOrDynErrorRef::DynError(error) => {
1423                struct DebugError<'a>(SharedPtr<'a, DynError>);
1424                impl fmt::Debug for DebugError<'_> {
1425                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1426                        // Safety: invariant of `OomOrDynError` that the pointer
1427                        // is valid.
1428                        let vtable = unsafe { self.0.as_ref().vtable };
1429                        // Safety: the pointer is valid and the vtable is
1430                        // associated with the pointer's concrete error type.
1431                        unsafe { (vtable.debug)(self.0, f) }
1432                    }
1433                }
1434
1435                let mut f = f.debug_struct("DynError");
1436                f.field("error", &DebugError(error));
1437                if let Some(source) = self.source() {
1438                    f.field("source", &source);
1439                }
1440                f.finish()
1441            }
1442        }
1443    }
1444
1445    fn source(&self) -> Option<OomOrDynErrorRef<'a>> {
1446        match self {
1447            OomOrDynErrorRef::DynError(e) => {
1448                // Safety: invariant of this type.
1449                let vtable = unsafe { e.as_ref().vtable };
1450                // Safety: using the vtable associated with this pointer's
1451                // concrete type and the pointer is valid.
1452                unsafe { (vtable.source)(*e) }
1453            }
1454            OomOrDynErrorRef::Oom(_) => None,
1455        }
1456    }
1457
1458    fn is<E>(&self) -> bool
1459    where
1460        E: fmt::Display + fmt::Debug + Send + Sync + 'static,
1461    {
1462        match self {
1463            OomOrDynErrorRef::DynError(e) => {
1464                // Safety: invariant of this type.
1465                let vtable = unsafe { e.as_ref().vtable };
1466                // Safety: using the vtable associated with this pointer's
1467                // concrete type and the pointer is valid.
1468                unsafe { (vtable.is)(*e, TypeId::of::<E>()) }
1469            }
1470            OomOrDynErrorRef::Oom(_) => TypeId::of::<E>() == TypeId::of::<OutOfMemory>(),
1471        }
1472    }
1473
1474    pub(crate) fn as_dyn_core_error(&self) -> &'a (dyn core::error::Error + Send + Sync + 'static) {
1475        match *self {
1476            OomOrDynErrorRef::DynError(e) => {
1477                // Safety: invariant of this type.
1478                let vtable = unsafe { e.as_ref().vtable };
1479                // Safety: using the vtable associated with this pointer's
1480                // concrete type and the pointer is valid.
1481                unsafe { (vtable.as_dyn_core_error)(e) }
1482            }
1483            OomOrDynErrorRef::Oom(oom) => oom as _,
1484        }
1485    }
1486
1487    #[cfg(feature = "backtrace")]
1488    fn backtrace(&self) -> &'a Backtrace {
1489        match self {
1490            OomOrDynErrorRef::DynError(e) => {
1491                // Safety: invariant of this type.
1492                let r = unsafe { e.as_ref() };
1493                r.backtrace
1494                    .as_ref()
1495                    .expect("the first error in the chain always has the backtrace")
1496            }
1497
1498            OomOrDynErrorRef::Oom(_) => {
1499                static DISABLED: Backtrace = Backtrace::disabled();
1500                &DISABLED
1501            }
1502        }
1503    }
1504}
1505
1506pub(crate) enum OomOrDynErrorMut<'a> {
1507    // Safety: this must always be a valid pointer to read and write a
1508    // `DynError` from for the `'a` lifetime.
1509    DynError(MutPtr<'a, DynError>),
1510
1511    Oom(&'a mut OutOfMemory),
1512}
1513
1514impl<'a> OomOrDynErrorMut<'a> {
1515    fn as_ref(&self) -> OomOrDynErrorRef<'_> {
1516        match self {
1517            OomOrDynErrorMut::DynError(e) => OomOrDynErrorRef::DynError(e.as_shared_ptr()),
1518            OomOrDynErrorMut::Oom(oom) => OomOrDynErrorRef::Oom(oom),
1519        }
1520    }
1521
1522    fn source_mut(&mut self) -> Option<OomOrDynErrorMut<'a>> {
1523        match self {
1524            OomOrDynErrorMut::DynError(e) => {
1525                // Safety: invariant of this type.
1526                let vtable = unsafe { e.as_ref().vtable };
1527                // Safety: using the vtable associated with this pointer's
1528                // concrete type and the pointer is valid.
1529                unsafe { (vtable.source_mut)(e.raw_copy()) }
1530            }
1531            OomOrDynErrorMut::Oom(_) => None,
1532        }
1533    }
1534}
1535
1536/// Bit packed version of `enum { BoxedDynError, OutOfMemory }` that relies on
1537/// implicit pointer tagging and `OutOfMemory` being zero-sized.
1538#[repr(transparent)]
1539pub(crate) struct OomOrDynError {
1540    // Safety: this must always be the casted-to-`u8` version of either (a)
1541    // `0x1`, or (b) a valid, owned `DynError` pointer. (Note that these cases
1542    // cannot overlap because `DynError`'s alignment is greater than `0x1`.)
1543    inner: NonNull<u8>,
1544}
1545
1546// Safety: `OomOrDynError` is either an `OutOfMemory` or a `BoxedDynError` and
1547// both are `Send`.
1548unsafe impl Send for OomOrDynError {}
1549
1550// Safety: `OomOrDynError` is either an `OutOfMemory` or a `BoxedDynError` and
1551// both are `Sync`.
1552unsafe impl Sync for OomOrDynError {}
1553
1554const _OOM_OR_DYN_ERROR_SEND_SYNC_SAFETY: () = {
1555    const fn assert_send_sync<T: Send + Sync>() {}
1556    assert_send_sync::<OutOfMemory>();
1557    assert_send_sync::<BoxedDynError>();
1558};
1559
1560impl Drop for OomOrDynError {
1561    fn drop(&mut self) {
1562        if self.is_boxed_dyn_error() {
1563            let inner = self.inner.cast::<DynError>();
1564            let inner = OwnedPtr::new(inner);
1565            // Safety: the pointer is a valid `DynError` pointer.
1566            let _ = unsafe { BoxedDynError::from_owned_ptr(inner) };
1567        } else {
1568            debug_assert!(self.is_oom());
1569        }
1570    }
1571}
1572
1573impl From<BoxedDynError> for OomOrDynError {
1574    fn from(boxed: BoxedDynError) -> Self {
1575        let inner = boxed.into_owned_ptr().into_non_null().cast::<u8>();
1576        debug_assert_ne!(inner, Self::OOM.inner);
1577        OomOrDynError { inner }
1578    }
1579}
1580
1581impl OomOrDynError {
1582    const _SIZE: () = assert!(mem::size_of::<OomOrDynError>() == mem::size_of::<usize>());
1583
1584    // Our pointer tagging relies on this property.
1585    const _DYN_ERROR_HAS_GREATER_ALIGN_THAN_OOM: () = assert!(mem::align_of::<DynError>() > 1);
1586
1587    const OOM_REPR: NonNull<u8> = unsafe {
1588        // Safety: `0x1` is not null.
1589        NonNull::<u8>::new_unchecked(0x1 as *mut u8)
1590    };
1591
1592    pub(crate) const OOM: Self = OomOrDynError {
1593        inner: Self::OOM_REPR,
1594    };
1595
1596    fn is_oom(&self) -> bool {
1597        self.inner == Self::OOM_REPR
1598    }
1599
1600    fn is_boxed_dyn_error(&self) -> bool {
1601        !self.is_oom()
1602    }
1603
1604    /// # Safety
1605    ///
1606    /// `self.is_oom()` must be true.
1607    unsafe fn unchecked_oom(&self) -> &OutOfMemory {
1608        debug_assert!(self.is_oom());
1609        let dangling = NonNull::<OutOfMemory>::dangling();
1610        debug_assert_eq!(mem::size_of::<OutOfMemory>(), 0);
1611        // Safety: it is always valid to turn `T`'s dangling pointer into an
1612        // `&T` reference for unit types.
1613        unsafe { dangling.as_ref() }
1614    }
1615
1616    /// # Safety
1617    ///
1618    /// `self.is_oom()` must be true.
1619    unsafe fn unchecked_oom_mut(&mut self) -> &mut OutOfMemory {
1620        debug_assert!(self.is_oom());
1621        let mut dangling = NonNull::<OutOfMemory>::dangling();
1622        debug_assert_eq!(mem::size_of::<OutOfMemory>(), 0);
1623        // Safety: it is always valid to turn `T`'s dangling pointer into an
1624        // `&mut T` reference for unit types.
1625        unsafe { dangling.as_mut() }
1626    }
1627
1628    /// # Safety
1629    ///
1630    /// `self.is_boxed_dyn_error()` must be true.
1631    unsafe fn unchecked_into_dyn_error(self) -> OwnedPtr<DynError> {
1632        debug_assert!(self.is_boxed_dyn_error());
1633        let inner = self.inner.cast::<DynError>();
1634        mem::forget(self);
1635        OwnedPtr::new(inner)
1636    }
1637
1638    /// # Safety
1639    ///
1640    /// `self.is_boxed_dyn_error()` must be true.
1641    unsafe fn unchecked_dyn_error_ref(&self) -> SharedPtr<'_, DynError> {
1642        debug_assert!(self.is_boxed_dyn_error());
1643        SharedPtr::new(self.inner.cast::<DynError>())
1644    }
1645
1646    /// # Safety
1647    ///
1648    /// `self.is_boxed_dyn_error()` must be true.
1649    unsafe fn unchecked_dyn_error_mut(&mut self) -> MutPtr<'_, DynError> {
1650        debug_assert!(self.is_boxed_dyn_error());
1651        MutPtr::new(self.inner.cast::<DynError>())
1652    }
1653
1654    pub(crate) fn unpack(&self) -> OomOrDynErrorRef<'_> {
1655        if self.is_oom() {
1656            // Safety: is_oom() is true.
1657            OomOrDynErrorRef::Oom(unsafe { self.unchecked_oom() })
1658        } else {
1659            debug_assert!(self.is_boxed_dyn_error());
1660            // Safety: self.is_boxed_dyn_error() is true.
1661            OomOrDynErrorRef::DynError(unsafe { self.unchecked_dyn_error_ref() })
1662        }
1663    }
1664
1665    pub(crate) fn unpack_mut(&mut self) -> OomOrDynErrorMut<'_> {
1666        if self.is_oom() {
1667            // Safety: self.is_oom() is true
1668            OomOrDynErrorMut::Oom(unsafe { self.unchecked_oom_mut() })
1669        } else {
1670            debug_assert!(self.is_boxed_dyn_error());
1671            // Safety: self.is_boxed_dyn_error() is true.
1672            OomOrDynErrorMut::DynError(unsafe { self.unchecked_dyn_error_mut() })
1673        }
1674    }
1675
1676    pub(crate) fn into_boxed_dyn_core_error(
1677        self,
1678    ) -> Box<dyn core::error::Error + Send + Sync + 'static> {
1679        let box_dyn_error_of_oom = || {
1680            // NB: `Box::new` will never actually allocate for zero-sized types
1681            // like `OutOfMemory`.
1682            Box::new(OutOfMemory::new()) as _
1683        };
1684
1685        if self.is_oom() {
1686            box_dyn_error_of_oom()
1687        } else {
1688            debug_assert!(self.is_boxed_dyn_error());
1689            // Safety: this is a boxed dyn error.
1690            let ptr = unsafe { self.unchecked_into_dyn_error() };
1691            // Safety: invariant of the type that the pointer is valid.
1692            let vtable = unsafe { ptr.as_ref().vtable };
1693            // Safety: the pointer is valid and the vtable is associated with
1694            // this pointer's concrete error type.
1695            match unsafe { (vtable.into_boxed_dyn_core_error)(ptr) } {
1696                Ok(e) => e,
1697                Err(_oom) => box_dyn_error_of_oom(),
1698            }
1699        }
1700    }
1701
1702    /// Given that this is known to be an instance of the type associated with
1703    /// the given `TypeId`, do an owning-downcast to that type, writing the
1704    /// result through the given `ret_ptr`, and deallocating `self` along the
1705    /// way.
1706    ///
1707    /// The `ret_ptr`'s storage will contain an initialized instance of the
1708    /// associated type upon this method's successful return.
1709    ///
1710    /// # Safety
1711    ///
1712    /// This error (or another in its chain) must be of the type associated with
1713    /// `TypeId`.
1714    ///
1715    /// The given `ret_ptr` must point to a valid-but-uninitialized storage
1716    /// location for an instance of the type associated with the given `TypeId`.
1717    pub(crate) unsafe fn downcast(self, type_id: TypeId, ret_ptr: NonNull<u8>) {
1718        if self.is_oom() {
1719            debug_assert_eq!(type_id, TypeId::of::<OutOfMemory>());
1720            // Safety: this is an OOM error.
1721            let oom = unsafe { self.unchecked_oom() };
1722            // Safety: implied by this method's safety contract.
1723            unsafe {
1724                ret_ptr.cast::<OutOfMemory>().write(*oom);
1725            }
1726        } else {
1727            debug_assert!(self.is_boxed_dyn_error());
1728            // Safety: this is a boxed dyn error.
1729            let ptr = unsafe { self.unchecked_into_dyn_error() };
1730            // Safety: invariant of this type that the pointer is valid.
1731            let vtable = unsafe { ptr.as_ref().vtable };
1732            // Safety: the pointer is valid and the vtable is associated with
1733            // this pointer's concrete type.
1734            unsafe { (vtable.downcast)(ptr, type_id, ret_ptr) }
1735        }
1736    }
1737}
1738
1739/// An iterator over each error in an [`Error`]'s context chain.
1740///
1741/// The iterator yields `&'a (dyn core::error::Error + 'static)` items.
1742///
1743/// Iterates from the most recently added error context towards the root cause.
1744///
1745/// Created by the [`Error::chain`] method. See that method's documentation for
1746/// more details.
1747pub struct Chain<'a> {
1748    state: ChainState<'a>,
1749}
1750
1751enum ChainState<'a> {
1752    Ours(OomOrDynErrorRef<'a>),
1753    Core(Option<&'a (dyn core::error::Error + 'static)>),
1754}
1755
1756impl<'a> Chain<'a> {
1757    fn new(error: OomOrDynErrorRef<'a>) -> Self {
1758        Self {
1759            state: ChainState::Ours(error),
1760        }
1761    }
1762}
1763
1764impl<'a> Iterator for Chain<'a> {
1765    type Item = &'a (dyn core::error::Error + 'static);
1766
1767    #[inline]
1768    fn next(&mut self) -> Option<Self::Item> {
1769        match &mut self.state {
1770            ChainState::Ours(e) => {
1771                let core = e.as_dyn_core_error();
1772                self.state = if let Some(e) = e.source() {
1773                    ChainState::Ours(e)
1774                } else {
1775                    ChainState::Core(core.source())
1776                };
1777                Some(core)
1778            }
1779            ChainState::Core(error) => {
1780                let e = error.take()?;
1781                self.state = ChainState::Core(e.source());
1782                Some(e)
1783            }
1784        }
1785    }
1786}
1787
1788impl FusedIterator for Chain<'_> {}
1789
1790#[cfg(test)]
1791mod tests {
1792    use super::*;
1793
1794    #[derive(Debug)]
1795    struct TestError;
1796
1797    impl fmt::Display for TestError {
1798        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1799            fmt::Debug::fmt(self, f)
1800        }
1801    }
1802
1803    impl core::error::Error for TestError {}
1804
1805    #[test]
1806    fn from_oom() {
1807        let mut error = Error::from(OutOfMemory::new());
1808        assert!(error.is::<OutOfMemory>());
1809        assert!(error.downcast_ref::<OutOfMemory>().is_some());
1810        assert!(error.downcast_mut::<OutOfMemory>().is_some());
1811
1812        // NB: use this module's scope to check that the inner representation is
1813        // `OomOrDynError::Oom` and not a `Box<OutOfMemory> as Box<dyn
1814        // Error>`. This is why this test cannot be in `tests/tests.rs`.
1815        assert!(error.inner.is_oom());
1816    }
1817
1818    #[test]
1819    fn dyn_error_and_concrete_error_layouts_are_compatible() {
1820        type Concrete = ConcreteError<TestError>;
1821
1822        let dyn_size = mem::size_of::<DynError>();
1823        let concrete_size = mem::size_of::<Concrete>();
1824        assert!(
1825            dyn_size <= concrete_size,
1826            "assertion failed: {dyn_size} <= {concrete_size}"
1827        );
1828
1829        let dyn_align = mem::align_of::<DynError>();
1830        let concrete_align = mem::align_of::<Concrete>();
1831        assert!(
1832            dyn_align <= concrete_align,
1833            "assertion failed: {dyn_align} <= {concrete_align}"
1834        );
1835
1836        let dyn_offset = mem::offset_of!(DynError, vtable);
1837        let concrete_offset = mem::offset_of!(Concrete, vtable);
1838        assert_eq!(dyn_offset, concrete_offset);
1839
1840        #[cfg(feature = "backtrace")]
1841        {
1842            let dyn_offset = mem::offset_of!(DynError, backtrace);
1843            let concrete_offset = mem::offset_of!(Concrete, backtrace);
1844            assert_eq!(dyn_offset, concrete_offset);
1845        }
1846    }
1847}