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