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