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