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