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