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