Skip to main content

wasmtime_internal_core/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::error::{OutOfMemory, Result};
6use core::{
7    any::TypeId,
8    fmt::{self, Debug},
9    iter::FusedIterator,
10    mem,
11    ptr::NonNull,
12};
13#[cfg(feature = "backtrace")]
14use std::backtrace::{Backtrace, BacktraceStatus};
15use std_alloc::boxed::Box;
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::error::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_core::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/// [`format_err!`](crate::format_err) macro is preferred:
264///
265/// ```
266/// # use wasmtime_internal_core::error as wasmtime;
267/// use wasmtime::{format_err, Error};
268///
269/// let x = 42;
270/// let my_error: Error = format_err!("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_core::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_core as wasmtime;
318/// use wasmtime::error::{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_core::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_core::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            let multiple_causes = source.source().is_some();
450            for (i, e) in Chain::new(source).enumerate() {
451                if multiple_causes {
452                    write!(f, "{i: >5}: ")?;
453                } else {
454                    write!(f, "    ")?;
455                }
456                writeln!(f, "{e}")?;
457            }
458        }
459
460        #[cfg(feature = "backtrace")]
461        {
462            let backtrace = inner.backtrace();
463            if let BacktraceStatus::Captured = backtrace.status() {
464                f.write_str("\nStack backtrace:\n")?;
465                fmt::Display::fmt(backtrace, f)?;
466            }
467        }
468
469        Ok(())
470    }
471}
472
473impl fmt::Display for Error {
474    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
475        let inner = self.inner.unpack();
476        inner.display(f)?;
477
478        if f.alternate() {
479            if let Some(e) = inner.source() {
480                for e in Chain::new(e) {
481                    write!(f, ": {e}")?;
482                }
483            }
484        }
485
486        Ok(())
487    }
488}
489
490impl<E> From<E> for Error
491where
492    E: core::error::Error + Send + Sync + 'static,
493{
494    fn from(error: E) -> Self {
495        Self::new(error)
496    }
497}
498
499impl From<Error> for Box<dyn core::error::Error + Send + Sync + 'static> {
500    #[inline]
501    fn from(error: Error) -> Self {
502        error.into_boxed_dyn_error()
503    }
504}
505
506impl From<Error> for Box<dyn core::error::Error + Send + 'static> {
507    #[inline]
508    fn from(error: Error) -> Self {
509        error.into_boxed_dyn_error()
510    }
511}
512
513impl From<Error> for Box<dyn core::error::Error + 'static> {
514    #[inline]
515    fn from(error: Error) -> Self {
516        error.into_boxed_dyn_error()
517    }
518}
519
520/// Convert a [`wasmtime::Error`](Error) into an [`anyhow::Error`].
521///
522/// # Example
523///
524/// ```
525/// # use wasmtime_internal_core::error as wasmtime;
526/// let wasmtime_error = wasmtime::Error::msg("whoops");
527/// let anyhow_error = anyhow::Error::from(wasmtime_error);
528/// ```
529//
530// Unfortunately, we can't also implement `From<anyhow::Error> for Error`
531// because of trait coherence. From Rust's trait system's point of view,
532// `anyhow` could theoretically add an `core::error::Error for anyhow::Error`
533// implementation, which would make our desired `From<anyhow::Error>`
534// implementation conflict with our existing `From<E: core::error::Error>`
535// implementation. They cannot in fact add that implementation, however, because
536// they already have a `From<E: core::error::Error> for anyhow::Error`
537// implementation and so adding `core::error::Error for anyhow::Error` would
538// cause that impl to conflict with `From<T> for T` (which is the same reason we
539// cannot implement `core::error::Error for Error`). Nonetheless, our hands are
540// tied here.
541#[cfg(feature = "anyhow")]
542impl From<Error> for anyhow::Error {
543    #[inline]
544    fn from(e: Error) -> Self {
545        anyhow::Error::from_boxed(e.into_boxed_dyn_error())
546    }
547}
548
549impl core::ops::Deref for Error {
550    type Target = dyn core::error::Error + Send + Sync + 'static;
551
552    fn deref(&self) -> &Self::Target {
553        self.as_ref()
554    }
555}
556
557impl AsRef<dyn core::error::Error> for Error {
558    #[inline]
559    fn as_ref(&self) -> &(dyn core::error::Error + 'static) {
560        self.inner.unpack().as_dyn_core_error()
561    }
562}
563
564impl AsRef<dyn core::error::Error + Send + Sync> for Error {
565    #[inline]
566    fn as_ref(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
567        self.inner.unpack().as_dyn_core_error()
568    }
569}
570
571impl Error {
572    /// Construct a new `Error` from a type that implements
573    /// `core::error::Error`.
574    ///
575    /// Calling [`error.is::<E>()`](Error::is) will return `true` for the new
576    /// error (unless there was a memory allocation failure).
577    ///
578    /// This boxes the inner error, but if that box allocation fails, then this
579    /// function returns an `Error` where
580    /// [`error.is::<OutOfMemory>()`](OutOfMemory) is true.
581    ///
582    /// # Example
583    ///
584    /// ```
585    /// # use wasmtime_internal_core::error as wasmtime;
586    /// use wasmtime::Error;
587    ///
588    /// let error = Error::new(std::fmt::Error);
589    /// ```
590    pub fn new<E>(error: E) -> Self
591    where
592        E: core::error::Error + Send + Sync + 'static,
593    {
594        if TypeId::of::<E>() == TypeId::of::<OutOfMemory>() {
595            // Although we know that `E == OutOfMemory` in this block, the
596            // compiler doesn't understand that, and we have to do this litle
597            // dance.
598            union ToOom<T> {
599                oom: OutOfMemory,
600                error: mem::ManuallyDrop<T>,
601            }
602            let error = mem::ManuallyDrop::new(error);
603            // Safety: `E == OutOfMemory`.
604            let oom = unsafe { (ToOom { error }).oom };
605            return Error { inner: oom.into() };
606        }
607
608        Self::from_error_ext(ForeignError(error))
609    }
610
611    /// Construct a new `Error` from any type that implements `Debug` and
612    /// `Display`.
613    ///
614    /// Calling [`error.is::<M>()`](Error::is) will return `true` for the new
615    /// error (unless there was a memory allocation failure).
616    ///
617    /// This boxes the inner `M` type, but if that box allocation fails, then
618    /// this function returns an `Error` where
619    /// [`error.is::<OutOfMemory>()`](OutOfMemory) is true.
620    ///
621    /// # Example
622    ///
623    /// ```
624    /// # use wasmtime_internal_core::error as wasmtime;
625    /// use wasmtime::Error;
626    ///
627    /// let error = Error::msg("hello");
628    /// ```
629    pub fn msg<M>(message: M) -> Self
630    where
631        M: fmt::Debug + fmt::Display + Send + Sync + 'static,
632    {
633        Self::from_error_ext(MessageError(message))
634    }
635
636    /// Create an `Error` from a `Box<dyn core::error::Error>`.
637    ///
638    /// This is useful when converting errors from other universal-error
639    /// libraries into this crate's `Error` type. Prefer [`Error::from_anyhow`]
640    /// for converting `anyhow::Error`s into `Error`s, as that preserves
641    /// `error.is::<anyhow::Error>()`.
642    ///
643    /// Calling [`error.is::<Box<dyn core::error::Error + Send + Sync +
644    /// 'static>>()`](Error::is) will return `true` for the new error (unless
645    /// there was a memory allocation failure).
646    ///
647    /// This reboxes the inner error, but if that box allocation fails, then
648    /// this function returns an `Error` where
649    /// [`error.is::<OutOfMemory>()`](OutOfMemory) is true.
650    ///
651    /// # Example
652    ///
653    /// ```
654    /// # fn _foo() {
655    /// #![cfg(all(feature = "std", feature = "anyhow"))]
656    /// # use wasmtime_internal_core::error as wasmtime;
657    /// use std::error::Error;
658    ///
659    /// // You happen to have a boxed error trait object.
660    /// let orig_error = std::fs::read("XXX: some file that doesn't exist").unwrap_err();
661    /// let boxed_error: Box<dyn Error + Send + Sync + 'static> = Box::new(orig_error) as _;
662    ///
663    /// // You can turn it into a `wasmtime::Error` via `from_boxed`.
664    /// let wasmtime_error = wasmtime::Error::from_boxed(boxed_error);
665    /// # }
666    /// ```
667    pub fn from_boxed(error: Box<dyn core::error::Error + Send + Sync + 'static>) -> Self {
668        Self::from_error_ext(BoxedError(error))
669    }
670
671    /// Convert an `anyhow::Error` into an `Error`.
672    ///
673    /// Calling [`error.is::<anyhow::Error>()`](Error::is) will return `true`
674    /// for the new error (unless there was a memory allocation failure).
675    ///
676    /// This reboxes the `anyhow::Error`, but if that box allocation fails, then
677    /// this function returns an `Error` where
678    /// [`error.is::<OutOfMemory>()`](OutOfMemory) is true.
679    ///
680    /// # Example
681    ///
682    /// ```
683    /// # fn _foo() {
684    /// #![cfg(all(feature = "std", feature = "anyhow"))]
685    /// # use wasmtime_internal_core::error as wasmtime;
686    /// let anyhow_error = anyhow::Error::msg("failed to flim the flam");
687    /// let wasmtime_error = wasmtime::Error::from_anyhow(anyhow_error);
688    /// assert_eq!(
689    ///     wasmtime_error.to_string(),
690    ///     "failed to flim the flam",
691    /// );
692    /// # }
693    /// ```
694    #[cfg(feature = "anyhow")]
695    #[inline]
696    pub fn from_anyhow(error: anyhow::Error) -> Self {
697        Self::from_error_ext(AnyhowError(error))
698    }
699
700    /// Add additional context to this error.
701    ///
702    /// The new context will show up first in the error chain, and the original
703    /// error will come next.
704    ///
705    /// This is similar to the [`Context::context`] trait method, but because it
706    /// is a method directly on [`Error`], there is no need for lazily-computing
707    /// the error context (like `with_context` does).
708    ///
709    /// Calling [`error.is::<C>()`](Error::is) will return `true` for the new
710    /// error (unless there was a memory allocation failure) in addition to any
711    /// other types `T` for which it was already the case that
712    /// `error.is::<T>()`.
713    ///
714    /// This boxes the inner `C` type, but if that box allocation fails, then
715    /// this function returns an `Error` where
716    /// [`error.is::<OutOfMemory>()`](OutOfMemory) is true.
717    ///
718    /// [`Context::context`]: crate::error::Context::context
719    ///
720    /// # Example
721    ///
722    /// ```
723    /// # use wasmtime_internal_core::error as wasmtime;
724    /// use wasmtime::Error;
725    ///
726    /// let error = Error::msg("root cause");
727    /// let error = error.context("failed to bonkinate");
728    /// let error = error.context("cannot frob the blobbins");
729    ///
730    /// assert!(
731    ///     format!("{error:?}").contains(
732    ///         r#"
733    /// cannot frob the blobbins
734    ///
735    /// Caused by:
736    ///     0: failed to bonkinate
737    ///     1: root cause
738    ///         "#.trim(),
739    ///     ),
740    /// );
741    /// ```
742    pub fn context<C>(self, context: C) -> Self
743    where
744        C: fmt::Display + Send + Sync + 'static,
745    {
746        if self.inner.is_oom() {
747            self
748        } else {
749            Self::from_error_ext(ContextError {
750                context,
751                error: Some(self),
752            })
753        }
754    }
755
756    #[inline]
757    pub(crate) fn from_error_ext(error: impl ErrorExt) -> Self {
758        match BoxedDynError::new(error) {
759            Ok(boxed) => Error {
760                inner: boxed.into(),
761            },
762            Err(oom) => Error { inner: oom.into() },
763        }
764    }
765
766    /// Get this error's backtrace.
767    ///
768    /// Backtraces will be automatically captured on initial `Error` creation
769    /// when all of the following conditions are met:
770    ///
771    /// * This crate's `"backtrace"` cargo feature is enabled
772    /// * Rust's `std::backtrace::Backtrace` supports the platform
773    /// * The `RUST_BACKTRACE` or `RUST_LIB_BACKTRACE` environment variables
774    ///   are set and non-zero
775    ///
776    /// See [the `std::backtrace::Backtrace`
777    /// documentation](https://doc.rust-lang.org/stable/std/backtrace/struct.Backtrace.html)
778    /// for more details on backtraces.
779    ///
780    /// Note that `std::backtrace::Backtrace` does not provide a
781    /// fallible-capture mechanism that returns an error, rather than aborting
782    /// the process, when it encounters memory exhaustion. If you require
783    /// out-of-memory error handling, do not enable this crate's `"backtrace"`
784    /// cargo feature.
785    ///
786    /// # Example
787    ///
788    /// ```
789    /// # fn _foo() {
790    /// #![cfg(feature = "backtrace")]
791    /// # use wasmtime_internal_core::error as wasmtime;
792    /// use std::backtrace::BacktraceStatus;
793    /// use wasmtime::Error;
794    ///
795    /// let error = Error::msg("whoops");
796    ///
797    /// let backtrace = error.backtrace();
798    /// if let BacktraceStatus::Captured = backtrace.status() {
799    ///     println!("error backtrace is:\n{backtrace}");
800    /// }
801    /// # }
802    /// ```
803    #[inline]
804    #[cfg(feature = "backtrace")]
805    pub fn backtrace(&self) -> &Backtrace {
806        self.inner.unpack().backtrace()
807    }
808
809    /// Iterate over this error's context chain.
810    ///
811    /// The iterator yields `&(dyn core::error::Error + 'static)` items.
812    ///
813    /// Iterates from the most recently added error context towards the root
814    /// cause.
815    ///
816    /// # Example
817    ///
818    /// ```
819    /// # use wasmtime_internal_core::error as wasmtime;
820    /// use wasmtime::Error;
821    ///
822    /// let error = Error::msg("root cause");
823    /// let error = error.context("failed to reticulate splines");
824    /// let error = error.context("aborting launch");
825    ///
826    /// let messages: Vec<_> = error.chain().map(|e| e.to_string()).collect();
827    /// assert_eq!(
828    ///     messages,
829    ///     ["aborting launch", "failed to reticulate splines", "root cause"],
830    /// );
831    /// ```
832    #[inline]
833    pub fn chain(&self) -> Chain<'_> {
834        Chain::new(self.inner.unpack())
835    }
836
837    /// Get the last error in the context chain.
838    ///
839    /// # Example
840    ///
841    /// ```
842    /// # use wasmtime_internal_core::error as wasmtime;
843    /// use wasmtime::Error;
844    ///
845    /// let error = Error::msg("ghosts");
846    /// let error = error.context("failed to reticulate splines");
847    /// let error = error.context("aborting launch");
848    ///
849    /// assert_eq!(
850    ///     error.root_cause().to_string(),
851    ///     "ghosts",
852    /// );
853    /// ```
854    #[inline]
855    pub fn root_cause(&self) -> &(dyn core::error::Error + 'static) {
856        self.chain().last().expect("chain is always non-empty")
857    }
858
859    /// Is this an `E` error?
860    ///
861    /// Returns true if any error in the context chain is an `E`.
862    ///
863    /// # Example
864    ///
865    /// ```
866    /// # use wasmtime_internal_core as wasmtime;
867    /// use wasmtime::error::{Error, OutOfMemory};
868    ///
869    /// let oom = Error::from(OutOfMemory::new(1234));
870    /// assert!(oom.is::<OutOfMemory>());
871    /// assert!(!oom.is::<std::num::TryFromIntError>());
872    ///
873    /// // Here is an example with additional error context.
874    /// let error = Error::from(u8::try_from(u32::MAX).unwrap_err());
875    /// let error = error.context(format!("cannot convert {} into a u8", u32::MAX));
876    /// assert!(
877    ///     error.is::<std::num::TryFromIntError>(),
878    ///     "root cause is an int conversion failure",
879    /// );
880    /// assert!(
881    ///     error.is::<String>(),
882    ///     "additional context is a `String`",
883    /// );
884    /// assert!(
885    ///     !error.is::<OutOfMemory>(),
886    ///     "no error in the chain is an out-of-memory error",
887    /// );
888    /// ```
889    pub fn is<E>(&self) -> bool
890    where
891        E: fmt::Display + fmt::Debug + Send + Sync + 'static,
892    {
893        let mut error = Some(self.inner.unpack());
894        while let Some(e) = error {
895            if e.is::<E>() {
896                return true;
897            } else {
898                error = e.source();
899            }
900        }
901        false
902    }
903
904    /// Downcast this error into an `E`, taking ownership.
905    ///
906    /// If this error is an `E`, then `Ok(E)` is returned. Otherwise,
907    /// `Err(self)` is returned.
908    ///
909    /// If there are multiple instances of `E` in this error's chain, then the
910    /// first (as encountered by [`Error::chain`]'s iteration order) is
911    /// returned.
912    ///
913    /// # Example
914    ///
915    /// ```
916    /// # use wasmtime_internal_core as wasmtime;
917    /// use wasmtime::error::{Error, OutOfMemory};
918    ///
919    /// let error = Error::msg("whoops");
920    ///
921    /// // `error` is not an `OutOfMemory`.
922    /// let downcasted = error.downcast::<OutOfMemory>();
923    /// assert!(downcasted.is_err());
924    ///
925    /// // Get the original `error` back.
926    /// let error = downcasted.unwrap_err();
927    ///
928    /// // `error` is an `&str`.
929    /// let downcasted = error.downcast::<&str>();
930    /// assert!(downcasted.is_ok());
931    /// assert_eq!(downcasted.unwrap(), "whoops");
932    ///
933    /// // If there are multiple `E`s in the chain, the first in the chain is
934    /// // returned.
935    /// let error = Error::msg("root cause");
936    /// let error = error.context("failed to recombobulate");
937    /// assert_eq!(
938    ///     error.downcast::<&str>().unwrap(),
939    ///     "failed to recombobulate",
940    /// );
941    /// ```
942    pub fn downcast<E>(self) -> Result<E, Self>
943    where
944        E: fmt::Display + fmt::Debug + Send + Sync + 'static,
945    {
946        if !self.is::<E>() {
947            return Err(self);
948        }
949
950        let mut value = mem::MaybeUninit::<E>::uninit();
951
952        // Safety: this error is an `E` and the given pointer is valid to write
953        // an `E` to.
954        unsafe {
955            self.inner
956                .downcast(TypeId::of::<E>(), NonNull::from(&mut value).cast::<u8>());
957        }
958
959        // Safety: `OomOrDynError::downcast` guarantees that the given pointer's
960        // data is initialized upon successful return.
961        Ok(unsafe { value.assume_init() })
962    }
963
964    /// Downcast this error into a shared `&E` borrow.
965    ///
966    /// If this error is an `E`, then `Some(&E)` is returned. Otherwise, `None`
967    /// is returned.
968    ///
969    /// If there are multiple instances of `E` in this error's chain, then the
970    /// first (as encountered by [`Error::chain`]'s iteration order) is
971    /// returned.
972    ///
973    /// # Example
974    ///
975    /// ```
976    /// # use wasmtime_internal_core as wasmtime;
977    /// use wasmtime::error::{Error, OutOfMemory};
978    ///
979    /// let error = Error::msg("whoops");
980    ///
981    /// // `error` is not an `OutOfMemory`.
982    /// assert!(error.downcast_ref::<OutOfMemory>().is_none());
983    ///
984    /// // `error` is an `&str`.
985    /// assert!(error.downcast_ref::<&str>().is_some());
986    /// assert_eq!(*error.downcast_ref::<&str>().unwrap(), "whoops");
987    ///
988    /// // If there are multiple `E`s in the chain, the first in the chain is
989    /// // returned.
990    /// let error = Error::msg("root cause");
991    /// let error = error.context("failed to recombobulate");
992    /// assert_eq!(
993    ///     *error.downcast_ref::<&str>().unwrap(),
994    ///     "failed to recombobulate",
995    /// );
996    /// ```
997    pub fn downcast_ref<E>(&self) -> Option<&E>
998    where
999        E: fmt::Display + fmt::Debug + Send + Sync + 'static,
1000    {
1001        let mut error = Some(self.inner.unpack());
1002        while let Some(e) = error {
1003            if e.is::<E>() {
1004                return Some(match e {
1005                    OomOrDynErrorRef::DynError(ptr) => {
1006                        let ptr = ptr.cast::<ConcreteError<E>>();
1007                        // Safety: we own the pointer, it is valid for reading,
1008                        // and we checked that it is an `E`.
1009                        let r = unsafe { ptr.as_ref() };
1010                        &r.error
1011                    }
1012                    OomOrDynErrorRef::Oom(oom) => {
1013                        // Note: Even though we know that `E == OutOfMemory`
1014                        // here, we still have to do this dance to satisfy the
1015                        // type system.
1016                        debug_assert_eq!(TypeId::of::<E>(), TypeId::of::<OutOfMemory>());
1017                        let ptr = NonNull::from(oom);
1018                        let ptr = ptr.cast::<E>();
1019                        // Safety: the pointer points to `oom`, which is valid
1020                        // for creating a shared reference to.
1021                        unsafe { ptr.as_ref() }
1022                    }
1023                });
1024            } else {
1025                error = e.source();
1026            }
1027        }
1028        None
1029    }
1030
1031    /// Downcast this error into an exclusive `&mut E` borrow.
1032    ///
1033    /// If this error is an `E`, then `Some(&mut E)` is returned. Otherwise,
1034    /// `None` is returned.
1035    ///
1036    /// If there are multiple instances of `E` in this error's chain, then the
1037    /// first (as encountered by [`Error::chain`]'s iteration order) is
1038    /// returned.
1039    ///
1040    /// # Example
1041    ///
1042    /// ```
1043    /// # use wasmtime_internal_core as wasmtime;
1044    /// use wasmtime::error::{Error, OutOfMemory};
1045    ///
1046    /// let mut error = Error::msg("whoops");
1047    ///
1048    /// // `error` is not an `OutOfMemory`.
1049    /// assert!(error.downcast_mut::<OutOfMemory>().is_none());
1050    ///
1051    /// // `error` is an `&str`.
1052    /// assert!(error.downcast_mut::<&str>().is_some());
1053    /// assert_eq!(*error.downcast_mut::<&str>().unwrap(), "whoops");
1054    /// *error.downcast_mut::<&str>().unwrap() = "yikes";
1055    /// assert_eq!(*error.downcast_mut::<&str>().unwrap(), "yikes");
1056    ///
1057    /// // If there are multiple `E`s in the chain, the first in the chain is
1058    /// // returned.
1059    /// let error = Error::msg("root cause");
1060    /// let mut error = error.context("failed to recombobulate");
1061    /// assert_eq!(
1062    ///     *error.downcast_mut::<&str>().unwrap(),
1063    ///     "failed to recombobulate",
1064    /// );
1065    /// ```
1066    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
1067    where
1068        E: fmt::Display + fmt::Debug + Send + Sync + 'static,
1069    {
1070        let mut error = Some(self.inner.unpack_mut());
1071        while let Some(mut e) = error.take() {
1072            if e.as_ref().is::<E>() {
1073                return Some(match e {
1074                    OomOrDynErrorMut::DynError(ptr) => {
1075                        let mut ptr = ptr.cast::<ConcreteError<E>>();
1076                        // Safety: we own the pointer, it is valid for reading
1077                        // and writing, and we checked that it is an `E`.
1078                        let r = unsafe { ptr.as_mut() };
1079                        &mut r.error
1080                    }
1081                    OomOrDynErrorMut::Oom(oom) => {
1082                        // Note: Even though we know that `E == OutOfMemory`
1083                        // here, we still have to do this dance to satisfy the
1084                        // type system.
1085                        debug_assert_eq!(TypeId::of::<E>(), TypeId::of::<OutOfMemory>());
1086                        let ptr = NonNull::from(oom);
1087                        let mut ptr = ptr.cast::<E>();
1088                        // Safety: the pointer points to `oom`, which is valid
1089                        // for creating an exclusive reference to.
1090                        unsafe { ptr.as_mut() }
1091                    }
1092                });
1093            } else {
1094                error = e.source_mut();
1095            }
1096        }
1097        None
1098    }
1099
1100    /// Convert this error into a `Box<dyn core::error::Error>`.
1101    ///
1102    /// This is useful for integrating this crate's `Error`s into other
1103    /// universal-error libraries.
1104    ///
1105    /// This functionality is also available via a `From<Error> for Box<dyn
1106    /// core::error::Error + Send + Sync + 'static>>` implementation.
1107    ///
1108    /// # Example
1109    ///
1110    /// ```
1111    /// # fn _foo() {
1112    /// #![cfg(feature = "std")]
1113    /// use std::fmt;
1114    ///
1115    /// /// A stub representing some other error library.
1116    /// #[derive(Debug)]
1117    /// pub struct OtherError {
1118    ///     inner: Box<dyn std::error::Error + Send + Sync + 'static>,
1119    /// }
1120    ///
1121    /// impl fmt::Display for OtherError {
1122    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1123    ///         fmt::Display::fmt(&self.inner, f)
1124    ///     }
1125    /// }
1126    ///
1127    /// impl std::error::Error for OtherError {
1128    ///     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1129    ///         self.inner.source()
1130    ///     }
1131    /// }
1132    ///
1133    /// impl OtherError {
1134    ///     /// Create an `OtherError` from another error.
1135    ///     pub fn new<E>(error: E) -> Self
1136    ///     where
1137    ///         E: std::error::Error + Send + Sync + 'static,
1138    ///     {
1139    ///         OtherError { inner: Box::new(error) }
1140    ///     }
1141    ///
1142    ///     /// Create an `OtherError` from another, already-boxed error.
1143    ///     pub fn from_boxed(error: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self {
1144    ///         OtherError { inner: error }
1145    ///     }
1146    /// }
1147    ///
1148    /// # use wasmtime_internal_core::error as wasmtime;
1149    /// use wasmtime::Error;
1150    ///
1151    /// // Create an `Error`.
1152    /// let error = Error::msg("whoopsies");
1153    ///
1154    /// // Convert it into an `OtherError`.
1155    /// let error = OtherError::from_boxed(error.into_boxed_dyn_error());
1156    /// # }
1157    /// ```
1158    #[inline]
1159    pub fn into_boxed_dyn_error(self) -> Box<dyn core::error::Error + Send + Sync + 'static> {
1160        /// A specialized OOM error that is zero-sized, so that it can always be
1161        /// boxed without allocation, and we can keep this method infallible (to
1162        /// match `anyhow`'s API).
1163        #[derive(Debug)]
1164        struct IntoBoxedDynCoreErrorFailure;
1165
1166        impl core::fmt::Display for IntoBoxedDynCoreErrorFailure {
1167            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1168                write!(
1169                    f,
1170                    "failed to box error into `Box<dyn core::error::Error>` \
1171                     (allocation of {} bytes failed)",
1172                    mem::size_of::<Error>()
1173                )
1174            }
1175        }
1176
1177        impl core::error::Error for IntoBoxedDynCoreErrorFailure {}
1178
1179        match self.inner.into_boxed_dyn_core_error() {
1180            Ok(boxed) => boxed,
1181            Err(_oom) => {
1182                // NB: `Box::new` will never actually allocate for zero-sized types.
1183                Box::new(IntoBoxedDynCoreErrorFailure) as _
1184            }
1185        }
1186    }
1187}
1188
1189/// `ErrorExt` wrapper for foreign `core::error::Error` implementations.
1190///
1191/// For `Error::new`'s use only.
1192///
1193/// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is`
1194/// implementation and the casts that are performed using that method's return
1195/// value.
1196#[repr(transparent)]
1197struct ForeignError<E>(E);
1198
1199// Safety: `ext_is` is correct, `ext_move` always writes to `dest`.
1200unsafe impl<E> ErrorExt for ForeignError<E>
1201where
1202    E: core::error::Error + Send + Sync + 'static,
1203{
1204    fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
1205        &self.0
1206    }
1207
1208    fn ext_into_boxed_dyn_core_error(
1209        self,
1210    ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> {
1211        let boxed = try_new_uninit_box()?;
1212        Ok(Box::write(boxed, self.0) as _)
1213    }
1214
1215    fn ext_source(&self) -> Option<OomOrDynErrorRef<'_>> {
1216        None
1217    }
1218
1219    fn ext_source_mut(&mut self) -> Option<OomOrDynErrorMut<'_>> {
1220        None
1221    }
1222
1223    fn ext_take_source(&mut self) -> Option<OomOrDynError> {
1224        None
1225    }
1226
1227    unsafe fn ext_move(self, dest: NonNull<u8>) {
1228        // Safety: implied by this trait method's safety contract.
1229        unsafe {
1230            dest.cast::<E>().write(self.0);
1231        }
1232    }
1233
1234    fn ext_is(&self, type_id: TypeId) -> bool {
1235        // NB: need to check type id of `E`, not `Self` aka
1236        // `ForeignError<E>`.
1237        type_id == TypeId::of::<E>()
1238    }
1239
1240    #[cfg(feature = "backtrace")]
1241    fn take_backtrace(&mut self) -> Option<Backtrace> {
1242        None
1243    }
1244}
1245
1246/// `ErrorExt` wrapper for types given to `Error::msg`.
1247///
1248/// For `Error::msg`'s use only.
1249///
1250/// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is`
1251/// implementation and the casts that are performed using that method's return
1252/// value.
1253#[repr(transparent)]
1254struct MessageError<M>(M);
1255
1256impl<M> fmt::Debug for MessageError<M>
1257where
1258    M: fmt::Debug,
1259{
1260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1261        self.0.fmt(f)
1262    }
1263}
1264
1265impl<M> fmt::Display for MessageError<M>
1266where
1267    M: fmt::Display,
1268{
1269    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1270        self.0.fmt(f)
1271    }
1272}
1273
1274impl<M> core::error::Error for MessageError<M> where M: fmt::Debug + fmt::Display {}
1275
1276// Safety: `ext_is` is implemented correctly and `ext_move` always
1277// writes to its pointer.
1278unsafe impl<M> ErrorExt for MessageError<M>
1279where
1280    M: fmt::Debug + fmt::Display + Send + Sync + 'static,
1281{
1282    fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
1283        self
1284    }
1285
1286    fn ext_into_boxed_dyn_core_error(
1287        self,
1288    ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> {
1289        let boxed = try_new_uninit_box()?;
1290        Ok(Box::write(boxed, self) as _)
1291    }
1292
1293    fn ext_source(&self) -> Option<OomOrDynErrorRef<'_>> {
1294        None
1295    }
1296
1297    fn ext_source_mut(&mut self) -> Option<OomOrDynErrorMut<'_>> {
1298        None
1299    }
1300
1301    fn ext_take_source(&mut self) -> Option<OomOrDynError> {
1302        None
1303    }
1304
1305    fn ext_is(&self, type_id: TypeId) -> bool {
1306        // NB: need to check type id of `M`, not `Self` aka
1307        // `MessageError<M>`.
1308        type_id == TypeId::of::<M>()
1309    }
1310
1311    unsafe fn ext_move(self, dest: NonNull<u8>) {
1312        // Safety: implied by this trait method's contract.
1313        unsafe {
1314            dest.cast::<M>().write(self.0);
1315        }
1316    }
1317
1318    #[cfg(feature = "backtrace")]
1319    fn take_backtrace(&mut self) -> Option<Backtrace> {
1320        None
1321    }
1322}
1323
1324/// `ErrorExt` wrapper for `Box<dyn core::error::Error>`.
1325///
1326/// For `Error::from_boxed`'s use only.
1327///
1328/// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is`
1329/// implementation and the casts that are performed using that method's return
1330/// value.
1331#[repr(transparent)]
1332struct BoxedError(Box<dyn core::error::Error + Send + Sync + 'static>);
1333
1334// Safety: `ext_is` is implemented correctly and `ext_move` always
1335// writes to its pointer.
1336unsafe impl ErrorExt for BoxedError {
1337    fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
1338        &*self.0
1339    }
1340
1341    fn ext_into_boxed_dyn_core_error(
1342        self,
1343    ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> {
1344        Ok(self.0)
1345    }
1346
1347    fn ext_source(&self) -> Option<OomOrDynErrorRef<'_>> {
1348        None
1349    }
1350
1351    fn ext_source_mut(&mut self) -> Option<OomOrDynErrorMut<'_>> {
1352        None
1353    }
1354
1355    fn ext_take_source(&mut self) -> Option<OomOrDynError> {
1356        None
1357    }
1358
1359    fn ext_is(&self, type_id: TypeId) -> bool {
1360        // NB: need to check type id of `BoxDynSendSyncError`, not
1361        // `BoxedError`.
1362        type_id == TypeId::of::<Box<dyn core::error::Error + Send + Sync + 'static>>()
1363    }
1364
1365    unsafe fn ext_move(self, dest: NonNull<u8>) {
1366        // Safety: implied by this trait method's contract.
1367        unsafe {
1368            dest.cast::<Box<dyn core::error::Error + Send + Sync + 'static>>()
1369                .write(self.0);
1370        }
1371    }
1372
1373    #[cfg(feature = "backtrace")]
1374    fn take_backtrace(&mut self) -> Option<Backtrace> {
1375        None
1376    }
1377}
1378
1379/// `ErrorExt` wrapper for `anyhow::Error`.
1380///
1381/// For `Error::from_anyhow`'s use only.
1382///
1383/// NB: The `repr(transparent)` is required for safety of the `ErrorExt::ext_is`
1384/// implementation and the casts that are performed using that method's return
1385/// value.
1386#[repr(transparent)]
1387#[cfg(feature = "anyhow")]
1388struct AnyhowError(anyhow::Error);
1389
1390// Safety: `ext_is` is implemented correctly and `ext_move` always
1391// writes to its pointer.
1392#[cfg(feature = "anyhow")]
1393unsafe impl ErrorExt for AnyhowError {
1394    fn ext_as_dyn_core_error(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
1395        self.0.as_ref()
1396    }
1397
1398    fn ext_into_boxed_dyn_core_error(
1399        self,
1400    ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> {
1401        Ok(self.0.into_boxed_dyn_error())
1402    }
1403
1404    fn ext_source(&self) -> Option<OomOrDynErrorRef<'_>> {
1405        None
1406    }
1407
1408    fn ext_source_mut(&mut self) -> Option<OomOrDynErrorMut<'_>> {
1409        None
1410    }
1411
1412    fn ext_take_source(&mut self) -> Option<OomOrDynError> {
1413        None
1414    }
1415
1416    fn ext_is(&self, type_id: TypeId) -> bool {
1417        // NB: need to check type id of `BoxDynSendSyncError`, not
1418        // `AnyhowError`.
1419        type_id == TypeId::of::<anyhow::Error>()
1420    }
1421
1422    unsafe fn ext_move(self, dest: NonNull<u8>) {
1423        // Safety: implied by this trait method's contract.
1424        unsafe {
1425            dest.cast::<anyhow::Error>().write(self.0);
1426        }
1427    }
1428
1429    #[cfg(feature = "backtrace")]
1430    fn take_backtrace(&mut self) -> Option<Backtrace> {
1431        None
1432    }
1433}
1434
1435pub(crate) enum OomOrDynErrorRef<'a> {
1436    // Safety: this must always be a valid pointer to read a `DynError` from for
1437    // the `'a` lifetime.
1438    DynError(SharedPtr<'a, DynError>),
1439
1440    Oom(&'a OutOfMemory),
1441}
1442
1443impl<'a> Debug for OomOrDynErrorRef<'a> {
1444    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1445        self.debug(f)
1446    }
1447}
1448
1449impl<'a> OomOrDynErrorRef<'a> {
1450    fn display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1451        match self {
1452            OomOrDynErrorRef::DynError(e) => {
1453                // Safety: invariant of this type.
1454                let vtable = unsafe { e.as_ref().vtable };
1455                // Safety: using the vtable associated with this pointer's
1456                // concrete type and the pointer is valid.
1457                unsafe { (vtable.display)(*e, f) }
1458            }
1459            OomOrDynErrorRef::Oom(oom) => fmt::Display::fmt(oom, f),
1460        }
1461    }
1462
1463    fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1464        match *self {
1465            OomOrDynErrorRef::Oom(oom) => f.debug_tuple("Oom").field(oom).finish(),
1466            OomOrDynErrorRef::DynError(error) => {
1467                struct DebugError<'a>(SharedPtr<'a, DynError>);
1468                impl fmt::Debug for DebugError<'_> {
1469                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1470                        // Safety: invariant of `OomOrDynError` that the pointer
1471                        // is valid.
1472                        let vtable = unsafe { self.0.as_ref().vtable };
1473                        // Safety: the pointer is valid and the vtable is
1474                        // associated with the pointer's concrete error type.
1475                        unsafe { (vtable.debug)(self.0, f) }
1476                    }
1477                }
1478
1479                let mut f = f.debug_struct("DynError");
1480                f.field("error", &DebugError(error));
1481                if let Some(source) = self.source() {
1482                    f.field("source", &source);
1483                }
1484                f.finish()
1485            }
1486        }
1487    }
1488
1489    fn source(&self) -> Option<OomOrDynErrorRef<'a>> {
1490        match self {
1491            OomOrDynErrorRef::DynError(e) => {
1492                // Safety: invariant of this type.
1493                let vtable = unsafe { e.as_ref().vtable };
1494                // Safety: using the vtable associated with this pointer's
1495                // concrete type and the pointer is valid.
1496                unsafe { (vtable.source)(*e) }
1497            }
1498            OomOrDynErrorRef::Oom(_) => None,
1499        }
1500    }
1501
1502    fn is<E>(&self) -> bool
1503    where
1504        E: fmt::Display + fmt::Debug + Send + Sync + 'static,
1505    {
1506        match self {
1507            OomOrDynErrorRef::DynError(e) => {
1508                // Safety: invariant of this type.
1509                let vtable = unsafe { e.as_ref().vtable };
1510                // Safety: using the vtable associated with this pointer's
1511                // concrete type and the pointer is valid.
1512                unsafe { (vtable.is)(*e, TypeId::of::<E>()) }
1513            }
1514            OomOrDynErrorRef::Oom(_) => TypeId::of::<E>() == TypeId::of::<OutOfMemory>(),
1515        }
1516    }
1517
1518    pub(crate) fn as_dyn_core_error(&self) -> &'a (dyn core::error::Error + Send + Sync + 'static) {
1519        match *self {
1520            OomOrDynErrorRef::DynError(e) => {
1521                // Safety: invariant of this type.
1522                let vtable = unsafe { e.as_ref().vtable };
1523                // Safety: using the vtable associated with this pointer's
1524                // concrete type and the pointer is valid.
1525                unsafe { (vtable.as_dyn_core_error)(e) }
1526            }
1527            OomOrDynErrorRef::Oom(oom) => oom as _,
1528        }
1529    }
1530
1531    #[cfg(feature = "backtrace")]
1532    fn backtrace(&self) -> &'a Backtrace {
1533        match self {
1534            OomOrDynErrorRef::DynError(e) => {
1535                // Safety: invariant of this type.
1536                let r = unsafe { e.as_ref() };
1537                r.backtrace
1538                    .as_ref()
1539                    .expect("the first error in the chain always has the backtrace")
1540            }
1541
1542            OomOrDynErrorRef::Oom(_) => {
1543                static DISABLED: Backtrace = Backtrace::disabled();
1544                &DISABLED
1545            }
1546        }
1547    }
1548}
1549
1550pub(crate) enum OomOrDynErrorMut<'a> {
1551    // Safety: this must always be a valid pointer to read and write a
1552    // `DynError` from for the `'a` lifetime.
1553    DynError(MutPtr<'a, DynError>),
1554
1555    Oom(&'a mut OutOfMemory),
1556}
1557
1558impl<'a> OomOrDynErrorMut<'a> {
1559    fn as_ref(&self) -> OomOrDynErrorRef<'_> {
1560        match self {
1561            OomOrDynErrorMut::DynError(e) => OomOrDynErrorRef::DynError(e.as_shared_ptr()),
1562            OomOrDynErrorMut::Oom(oom) => OomOrDynErrorRef::Oom(oom),
1563        }
1564    }
1565
1566    fn source_mut(&mut self) -> Option<OomOrDynErrorMut<'a>> {
1567        match self {
1568            OomOrDynErrorMut::DynError(e) => {
1569                // Safety: invariant of this type.
1570                let vtable = unsafe { e.as_ref().vtable };
1571                // Safety: using the vtable associated with this pointer's
1572                // concrete type and the pointer is valid.
1573                unsafe { (vtable.source_mut)(e.raw_copy()) }
1574            }
1575            OomOrDynErrorMut::Oom(_) => None,
1576        }
1577    }
1578}
1579
1580/// Bit packed version of `enum { BoxedDynError, OutOfMemory }` that relies on
1581/// implicit pointer tagging and `OutOfMemory` being zero-sized.
1582#[repr(transparent)]
1583pub(crate) struct OomOrDynError {
1584    // Safety: this must always be the casted-to-`u8` version of either (a)
1585    // `0x1`, or (b) a valid, owned `DynError` pointer. (Note that these cases
1586    // cannot overlap because `DynError`'s alignment is greater than `0x1`.)
1587    inner: NonNull<u8>,
1588}
1589
1590// Safety: `OomOrDynError` is either an `OutOfMemory` or a `BoxedDynError` and
1591// both are `Send`.
1592unsafe impl Send for OomOrDynError {}
1593
1594// Safety: `OomOrDynError` is either an `OutOfMemory` or a `BoxedDynError` and
1595// both are `Sync`.
1596unsafe impl Sync for OomOrDynError {}
1597
1598const _OOM_OR_DYN_ERROR_SEND_SYNC_SAFETY: () = {
1599    const fn assert_send_sync<T: Send + Sync>() {}
1600    assert_send_sync::<OutOfMemory>();
1601    assert_send_sync::<BoxedDynError>();
1602};
1603
1604impl Drop for OomOrDynError {
1605    fn drop(&mut self) {
1606        if self.is_boxed_dyn_error() {
1607            let inner = self.inner.cast::<DynError>();
1608            let inner = OwnedPtr::new(inner);
1609            // Safety: the pointer is a valid `DynError` pointer.
1610            let _ = unsafe { BoxedDynError::from_owned_ptr(inner) };
1611        } else {
1612            debug_assert!(self.is_oom());
1613        }
1614    }
1615}
1616
1617impl From<BoxedDynError> for OomOrDynError {
1618    fn from(boxed: BoxedDynError) -> Self {
1619        let inner = boxed.into_owned_ptr().into_non_null().cast::<u8>();
1620        debug_assert!(!Self::is_oom_ptr(inner));
1621        OomOrDynError { inner }
1622    }
1623}
1624
1625impl OomOrDynError {
1626    const _SIZE: () = assert!(mem::size_of::<OomOrDynError>() == mem::size_of::<usize>());
1627
1628    /// Our pointer tagging relies on this property, which implies that
1629    /// `Self::OOM_BIT` is never set for any `*mut DynError` pointer.
1630    const _DYN_ERROR_HAS_GREATER_ALIGN_THAN_OOM: () = assert!(mem::align_of::<DynError>() > 1);
1631
1632    /// If this bit is set in the inner pointer's address, then it is a bitpacked
1633    /// `OutOfMemory` rather than a pointer to a boxed dyn error.
1634    const OOM_BIT: usize = 0x1;
1635
1636    pub(crate) const fn new_oom_ptr(size: usize) -> NonNull<u8> {
1637        let size = if size > (isize::MAX as usize) {
1638            isize::MAX as usize
1639        } else {
1640            size
1641        };
1642        let repr = (size << 1) | Self::OOM_BIT;
1643        let inner = core::ptr::without_provenance_mut(repr);
1644        NonNull::new(inner).unwrap()
1645    }
1646
1647    pub(crate) fn new_oom(bitpacked: NonNull<u8>) -> Self {
1648        assert!(Self::is_oom_ptr(bitpacked));
1649        OomOrDynError { inner: bitpacked }
1650    }
1651
1652    fn is_oom_ptr(ptr: NonNull<u8>) -> bool {
1653        (ptr.addr().get() & Self::OOM_BIT) == Self::OOM_BIT
1654    }
1655
1656    fn is_oom(&self) -> bool {
1657        Self::is_oom_ptr(self.inner)
1658    }
1659
1660    fn is_boxed_dyn_error(&self) -> bool {
1661        !self.is_oom()
1662    }
1663
1664    pub(crate) fn oom_size(inner: NonNull<u8>) -> usize {
1665        debug_assert!(Self::is_oom_ptr(inner));
1666        inner.addr().get() >> 1
1667    }
1668
1669    /// # Safety
1670    ///
1671    /// `self.is_oom()` must be true.
1672    unsafe fn unchecked_oom(&self) -> &OutOfMemory {
1673        debug_assert!(self.is_oom());
1674        // Safety: `self.is_oom()` and `OutOfMemory` has the same representation
1675        // as `Self`.
1676        unsafe { mem::transmute(self) }
1677    }
1678
1679    /// # Safety
1680    ///
1681    /// `self.is_oom()` must be true.
1682    unsafe fn unchecked_oom_mut(&mut self) -> &mut OutOfMemory {
1683        debug_assert!(self.is_oom());
1684        // Safety: `self.is_oom()` and `OutOfMemory` has the same representation
1685        // as `Self`.
1686        unsafe { mem::transmute(self) }
1687    }
1688
1689    /// # Safety
1690    ///
1691    /// `self.is_boxed_dyn_error()` must be true.
1692    unsafe fn unchecked_into_dyn_error(self) -> OwnedPtr<DynError> {
1693        debug_assert!(self.is_boxed_dyn_error());
1694        let inner = self.inner.cast::<DynError>();
1695        mem::forget(self);
1696        OwnedPtr::new(inner)
1697    }
1698
1699    /// # Safety
1700    ///
1701    /// `self.is_boxed_dyn_error()` must be true.
1702    unsafe fn unchecked_dyn_error_ref(&self) -> SharedPtr<'_, DynError> {
1703        debug_assert!(self.is_boxed_dyn_error());
1704        SharedPtr::new(self.inner.cast::<DynError>())
1705    }
1706
1707    /// # Safety
1708    ///
1709    /// `self.is_boxed_dyn_error()` must be true.
1710    unsafe fn unchecked_dyn_error_mut(&mut self) -> MutPtr<'_, DynError> {
1711        debug_assert!(self.is_boxed_dyn_error());
1712        MutPtr::new(self.inner.cast::<DynError>())
1713    }
1714
1715    pub(crate) fn unpack(&self) -> OomOrDynErrorRef<'_> {
1716        if self.is_oom() {
1717            // Safety: is_oom() is true.
1718            OomOrDynErrorRef::Oom(unsafe { self.unchecked_oom() })
1719        } else {
1720            debug_assert!(self.is_boxed_dyn_error());
1721            // Safety: self.is_boxed_dyn_error() is true.
1722            OomOrDynErrorRef::DynError(unsafe { self.unchecked_dyn_error_ref() })
1723        }
1724    }
1725
1726    pub(crate) fn unpack_mut(&mut self) -> OomOrDynErrorMut<'_> {
1727        if self.is_oom() {
1728            // Safety: self.is_oom() is true
1729            OomOrDynErrorMut::Oom(unsafe { self.unchecked_oom_mut() })
1730        } else {
1731            debug_assert!(self.is_boxed_dyn_error());
1732            // Safety: self.is_boxed_dyn_error() is true.
1733            OomOrDynErrorMut::DynError(unsafe { self.unchecked_dyn_error_mut() })
1734        }
1735    }
1736
1737    pub(crate) fn into_boxed_dyn_core_error(
1738        self,
1739    ) -> Result<Box<dyn core::error::Error + Send + Sync + 'static>, OutOfMemory> {
1740        if self.is_oom() {
1741            let boxed = try_new_uninit_box::<OutOfMemory>()?;
1742            // Safety: `self.is_oom()` is true.
1743            let boxed = Box::write(boxed, unsafe { *self.unchecked_oom() });
1744            Ok(boxed as _)
1745        } else {
1746            debug_assert!(self.is_boxed_dyn_error());
1747            // Safety: this is a boxed dyn error.
1748            let ptr = unsafe { self.unchecked_into_dyn_error() };
1749            // Safety: invariant of the type that the pointer is valid.
1750            let vtable = unsafe { ptr.as_ref().vtable };
1751            // Safety: the pointer is valid and the vtable is associated with
1752            // this pointer's concrete error type.
1753            unsafe { (vtable.into_boxed_dyn_core_error)(ptr) }
1754        }
1755    }
1756
1757    /// Given that this is known to be an instance of the type associated with
1758    /// the given `TypeId`, do an owning-downcast to that type, writing the
1759    /// result through the given `ret_ptr`, and deallocating `self` along the
1760    /// way.
1761    ///
1762    /// The `ret_ptr`'s storage will contain an initialized instance of the
1763    /// associated type upon this method's successful return.
1764    ///
1765    /// # Safety
1766    ///
1767    /// This error (or another in its chain) must be of the type associated with
1768    /// `TypeId`.
1769    ///
1770    /// The given `ret_ptr` must point to a valid-but-uninitialized storage
1771    /// location for an instance of the type associated with the given `TypeId`.
1772    pub(crate) unsafe fn downcast(self, type_id: TypeId, ret_ptr: NonNull<u8>) {
1773        if self.is_oom() {
1774            debug_assert_eq!(type_id, TypeId::of::<OutOfMemory>());
1775            // Safety: this is an OOM error.
1776            let oom = unsafe { self.unchecked_oom() };
1777            // Safety: implied by this method's safety contract.
1778            unsafe {
1779                ret_ptr.cast::<OutOfMemory>().write(*oom);
1780            }
1781        } else {
1782            debug_assert!(self.is_boxed_dyn_error());
1783            // Safety: this is a boxed dyn error.
1784            let ptr = unsafe { self.unchecked_into_dyn_error() };
1785            // Safety: invariant of this type that the pointer is valid.
1786            let vtable = unsafe { ptr.as_ref().vtable };
1787            // Safety: the pointer is valid and the vtable is associated with
1788            // this pointer's concrete type.
1789            unsafe { (vtable.downcast)(ptr, type_id, ret_ptr) }
1790        }
1791    }
1792}
1793
1794/// An iterator over each error in an [`Error`]'s context chain.
1795///
1796/// The iterator yields `&'a (dyn core::error::Error + 'static)` items.
1797///
1798/// Iterates from the most recently added error context towards the root cause.
1799///
1800/// Created by the [`Error::chain`] method. See that method's documentation for
1801/// more details.
1802pub struct Chain<'a> {
1803    state: ChainState<'a>,
1804}
1805
1806enum ChainState<'a> {
1807    Ours(OomOrDynErrorRef<'a>),
1808    Core(Option<&'a (dyn core::error::Error + 'static)>),
1809}
1810
1811impl<'a> Chain<'a> {
1812    fn new(error: OomOrDynErrorRef<'a>) -> Self {
1813        Self {
1814            state: ChainState::Ours(error),
1815        }
1816    }
1817}
1818
1819impl<'a> Iterator for Chain<'a> {
1820    type Item = &'a (dyn core::error::Error + 'static);
1821
1822    #[inline]
1823    fn next(&mut self) -> Option<Self::Item> {
1824        match &mut self.state {
1825            ChainState::Ours(e) => {
1826                let core = e.as_dyn_core_error();
1827                self.state = if let Some(e) = e.source() {
1828                    ChainState::Ours(e)
1829                } else {
1830                    ChainState::Core(core.source())
1831                };
1832                Some(core)
1833            }
1834            ChainState::Core(error) => {
1835                let e = error.take()?;
1836                self.state = ChainState::Core(e.source());
1837                Some(e)
1838            }
1839        }
1840    }
1841}
1842
1843impl FusedIterator for Chain<'_> {}
1844
1845#[cfg(test)]
1846mod tests {
1847    use super::*;
1848
1849    #[derive(Debug)]
1850    struct TestError;
1851
1852    impl fmt::Display for TestError {
1853        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1854            fmt::Debug::fmt(self, f)
1855        }
1856    }
1857
1858    impl core::error::Error for TestError {}
1859
1860    #[test]
1861    fn from_oom() {
1862        let mut error = Error::from(OutOfMemory::new(5));
1863        assert!(error.is::<OutOfMemory>());
1864        assert!(error.downcast_ref::<OutOfMemory>().is_some());
1865        assert!(error.downcast_mut::<OutOfMemory>().is_some());
1866
1867        // NB: use this module's scope to check that the inner representation is
1868        // `OomOrDynError::Oom` and not a `Box<OutOfMemory> as Box<dyn
1869        // Error>`. This is why this test cannot be in `tests/tests.rs`.
1870        assert!(error.inner.is_oom());
1871    }
1872
1873    #[test]
1874    fn dyn_error_and_concrete_error_layouts_are_compatible() {
1875        type Concrete = ConcreteError<TestError>;
1876
1877        let dyn_size = mem::size_of::<DynError>();
1878        let concrete_size = mem::size_of::<Concrete>();
1879        assert!(
1880            dyn_size <= concrete_size,
1881            "assertion failed: {dyn_size} <= {concrete_size}"
1882        );
1883
1884        let dyn_align = mem::align_of::<DynError>();
1885        let concrete_align = mem::align_of::<Concrete>();
1886        assert!(
1887            dyn_align <= concrete_align,
1888            "assertion failed: {dyn_align} <= {concrete_align}"
1889        );
1890
1891        let dyn_offset = mem::offset_of!(DynError, vtable);
1892        let concrete_offset = mem::offset_of!(Concrete, vtable);
1893        assert_eq!(dyn_offset, concrete_offset);
1894
1895        #[cfg(feature = "backtrace")]
1896        {
1897            let dyn_offset = mem::offset_of!(DynError, backtrace);
1898            let concrete_offset = mem::offset_of!(Concrete, backtrace);
1899            assert_eq!(dyn_offset, concrete_offset);
1900        }
1901    }
1902}