eyre/error.rs
1use crate::chain::Chain;
2use crate::ptr::{MutPtr, OwnedPtr, RefPtr};
3use crate::EyreHandler;
4use crate::{Report, StdError};
5use core::any::TypeId;
6use core::fmt::{self, Debug, Display};
7use core::mem::{self, ManuallyDrop};
8use core::ptr::{self, NonNull};
9
10use core::ops::{Deref, DerefMut};
11
12impl Report {
13 /// Create a new error object from any error type.
14 ///
15 /// The error type must be threadsafe and `'static`, so that the `Report`
16 /// will be as well.
17 ///
18 /// If the error type does not provide a backtrace, a backtrace will be
19 /// created here to ensure that a backtrace exists.
20 #[cfg_attr(track_caller, track_caller)]
21 pub fn new<E>(error: E) -> Self
22 where
23 E: StdError + Send + Sync + 'static,
24 {
25 Report::from_std(error)
26 }
27
28 /// Create a new error object from a printable error message.
29 ///
30 /// If the argument implements std::error::Error, prefer `Report::new`
31 /// instead which preserves the underlying error's cause chain and
32 /// backtrace. If the argument may or may not implement std::error::Error
33 /// now or in the future, use `eyre!(err)` which handles either way
34 /// correctly.
35 ///
36 /// `Report::msg("...")` is equivalent to `eyre!("...")` but occasionally
37 /// convenient in places where a function is preferable over a macro, such
38 /// as iterator or stream combinators:
39 ///
40 /// ```
41 /// # mod ffi {
42 /// # pub struct Input;
43 /// # pub struct Output;
44 /// # pub async fn do_some_work(_: Input) -> Result<Output, &'static str> {
45 /// # unimplemented!()
46 /// # }
47 /// # }
48 /// #
49 /// # use ffi::{Input, Output};
50 /// #
51 /// use eyre::{Report, Result};
52 /// use futures::stream::{Stream, StreamExt, TryStreamExt};
53 ///
54 /// async fn demo<S>(stream: S) -> Result<Vec<Output>>
55 /// where
56 /// S: Stream<Item = Input>,
57 /// {
58 /// stream
59 /// .then(ffi::do_some_work) // returns Result<Output, &str>
60 /// .map_err(Report::msg)
61 /// .try_collect()
62 /// .await
63 /// }
64 /// ```
65 #[cfg_attr(track_caller, track_caller)]
66 pub fn msg<M>(message: M) -> Self
67 where
68 M: Display + Debug + Send + Sync + 'static,
69 {
70 Report::from_adhoc(message)
71 }
72
73 #[cfg_attr(track_caller, track_caller)]
74 /// Creates a new error from an implementor of [`std::error::Error`]
75 pub(crate) fn from_std<E>(error: E) -> Self
76 where
77 E: StdError + Send + Sync + 'static,
78 {
79 let vtable = &ErrorVTable {
80 object_drop: object_drop::<E>,
81 object_ref: object_ref::<E>,
82 object_mut: object_mut::<E>,
83 object_boxed: object_boxed::<E>,
84 object_downcast: object_downcast::<E>,
85 object_downcast_mut: object_downcast_mut::<E>,
86 object_drop_rest: object_drop_front::<E>,
87 };
88
89 // Safety: passing vtable that operates on the right type E.
90 let handler = Some(crate::capture_handler(&error));
91
92 unsafe { Report::construct(error, vtable, handler) }
93 }
94
95 #[cfg_attr(track_caller, track_caller)]
96 pub(crate) fn from_adhoc<M>(message: M) -> Self
97 where
98 M: Display + Debug + Send + Sync + 'static,
99 {
100 use crate::wrapper::MessageError;
101 let error: MessageError<M> = MessageError(message);
102 let vtable = &ErrorVTable {
103 object_drop: object_drop::<MessageError<M>>,
104 object_ref: object_ref::<MessageError<M>>,
105 object_mut: object_mut::<MessageError<M>>,
106 object_boxed: object_boxed::<MessageError<M>>,
107 object_downcast: object_downcast::<M>,
108 object_downcast_mut: object_downcast_mut::<M>,
109 object_drop_rest: object_drop_front::<M>,
110 };
111
112 // Safety: MessageError is repr(transparent) so it is okay for the
113 // vtable to allow casting the MessageError<M> to M.
114 let handler = Some(crate::capture_handler(&error));
115
116 unsafe { Report::construct(error, vtable, handler) }
117 }
118
119 #[cfg_attr(track_caller, track_caller)]
120 pub(crate) fn from_display<M>(message: M) -> Self
121 where
122 M: Display + Send + Sync + 'static,
123 {
124 use crate::wrapper::{DisplayError, NoneError};
125 let error: DisplayError<M> = DisplayError(message);
126 let vtable = &ErrorVTable {
127 object_drop: object_drop::<DisplayError<M>>,
128 object_ref: object_ref::<DisplayError<M>>,
129 object_mut: object_mut::<DisplayError<M>>,
130 object_boxed: object_boxed::<DisplayError<M>>,
131 object_downcast: object_downcast::<M>,
132 object_downcast_mut: object_downcast_mut::<M>,
133 object_drop_rest: object_drop_front::<M>,
134 };
135
136 // Safety: DisplayError is repr(transparent) so it is okay for the
137 // vtable to allow casting the DisplayError<M> to M.
138 let handler = Some(crate::capture_handler(&NoneError));
139
140 unsafe { Report::construct(error, vtable, handler) }
141 }
142
143 #[cfg_attr(track_caller, track_caller)]
144 pub(crate) fn from_msg<D, E>(msg: D, error: E) -> Self
145 where
146 D: Display + Send + Sync + 'static,
147 E: StdError + Send + Sync + 'static,
148 {
149 let error: ContextError<D, E> = ContextError { msg, error };
150
151 let vtable = &ErrorVTable {
152 object_drop: object_drop::<ContextError<D, E>>,
153 object_ref: object_ref::<ContextError<D, E>>,
154 object_mut: object_mut::<ContextError<D, E>>,
155 object_boxed: object_boxed::<ContextError<D, E>>,
156 object_downcast: context_downcast::<D, E>,
157 object_downcast_mut: context_downcast_mut::<D, E>,
158 object_drop_rest: context_drop_rest::<D, E>,
159 };
160
161 // Safety: passing vtable that operates on the right type.
162 let handler = Some(crate::capture_handler(&error));
163
164 unsafe { Report::construct(error, vtable, handler) }
165 }
166
167 #[cfg_attr(track_caller, track_caller)]
168 pub(crate) fn from_boxed(error: Box<dyn StdError + Send + Sync>) -> Self {
169 use crate::wrapper::BoxedError;
170 let error = BoxedError(error);
171 let handler = Some(crate::capture_handler(&error));
172
173 let vtable = &ErrorVTable {
174 object_drop: object_drop::<BoxedError>,
175 object_ref: object_ref::<BoxedError>,
176 object_mut: object_mut::<BoxedError>,
177 object_boxed: object_boxed::<BoxedError>,
178 object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>>,
179 object_downcast_mut: object_downcast_mut::<Box<dyn StdError + Send + Sync>>,
180 object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>>,
181 };
182
183 // Safety: BoxedError is repr(transparent) so it is okay for the vtable
184 // to allow casting to Box<dyn StdError + Send + Sync>.
185 unsafe { Report::construct(error, vtable, handler) }
186 }
187
188 // Takes backtrace as argument rather than capturing it here so that the
189 // user sees one fewer layer of wrapping noise in the backtrace.
190 //
191 // Unsafe because the given vtable must have sensible behavior on the error
192 // value of type E.
193 unsafe fn construct<E>(
194 error: E,
195 vtable: &'static ErrorVTable,
196 handler: Option<Box<dyn EyreHandler>>,
197 ) -> Self
198 where
199 E: StdError + Send + Sync + 'static,
200 {
201 let inner = ErrorImpl {
202 header: ErrorHeader { vtable, handler },
203 _object: error,
204 };
205
206 // Construct a new owned allocation through a raw pointer
207 //
208 // This does not keep the allocation around as a `Box` which would invalidate an
209 // references when moved
210 let ptr = OwnedPtr::<ErrorImpl<E>>::new(inner);
211
212 // Safety: the type
213 let ptr = ptr.cast::<ErrorImpl<()>>();
214 Report { inner: ptr }
215 }
216
217 /// Create a new error from an error message to wrap the existing error.
218 ///
219 /// For attaching a higher level error message to a `Result` as it is propagated, the
220 /// [`WrapErr`][crate::WrapErr] extension trait may be more convenient than this function.
221 ///
222 /// The primary reason to use `error.wrap_err(...)` instead of `result.wrap_err(...)` via the
223 /// `WrapErr` trait would be if the message needs to depend on some data held by the underlying
224 /// error:
225 ///
226 /// ```
227 /// # use std::fmt::{self, Debug, Display};
228 /// #
229 /// # type T = ();
230 /// #
231 /// # impl std::error::Error for ParseError {}
232 /// # impl Debug for ParseError {
233 /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
234 /// # unimplemented!()
235 /// # }
236 /// # }
237 /// # impl Display for ParseError {
238 /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
239 /// # unimplemented!()
240 /// # }
241 /// # }
242 /// #
243 /// use eyre::Result;
244 /// use std::fs::File;
245 /// use std::path::Path;
246 ///
247 /// struct ParseError {
248 /// line: usize,
249 /// column: usize,
250 /// }
251 ///
252 /// fn parse_impl(file: File) -> Result<T, ParseError> {
253 /// # const IGNORE: &str = stringify! {
254 /// ...
255 /// # };
256 /// # unimplemented!()
257 /// }
258 ///
259 /// pub fn parse(path: impl AsRef<Path>) -> Result<T> {
260 /// let file = File::open(&path)?;
261 /// parse_impl(file).map_err(|error| {
262 /// let message = format!(
263 /// "only the first {} lines of {} are valid",
264 /// error.line, path.as_ref().display(),
265 /// );
266 /// eyre::Report::new(error).wrap_err(message)
267 /// })
268 /// }
269 /// ```
270 pub fn wrap_err<D>(mut self, msg: D) -> Self
271 where
272 D: Display + Send + Sync + 'static,
273 {
274 // Safety: this access a `ErrorImpl<unknown>` as a valid reference to a `ErrorImpl<()>`
275 //
276 // As the generic is at the end of the struct and the struct is `repr(C)` this reference
277 // will be within bounds of the original pointer, and the field will have the same offset
278 let handler = header_mut(self.inner.as_mut()).handler.take();
279 let error: ContextError<D, Report> = ContextError { msg, error: self };
280
281 let vtable = &ErrorVTable {
282 object_drop: object_drop::<ContextError<D, Report>>,
283 object_ref: object_ref::<ContextError<D, Report>>,
284 object_mut: object_mut::<ContextError<D, Report>>,
285 object_boxed: object_boxed::<ContextError<D, Report>>,
286 object_downcast: context_chain_downcast::<D>,
287 object_downcast_mut: context_chain_downcast_mut::<D>,
288 object_drop_rest: context_chain_drop_rest::<D>,
289 };
290
291 // Safety: passing vtable that operates on the right type.
292 unsafe { Report::construct(error, vtable, handler) }
293 }
294
295 /// Access the vtable for the current error object.
296 fn vtable(&self) -> &'static ErrorVTable {
297 header(self.inner.as_ref()).vtable
298 }
299
300 /// An iterator of the chain of source errors contained by this Report.
301 ///
302 /// This iterator will visit every error in the cause chain of this error
303 /// object, beginning with the error that this error object was created
304 /// from.
305 ///
306 /// # Example
307 ///
308 /// ```
309 /// use eyre::Report;
310 /// use std::io;
311 ///
312 /// pub fn underlying_io_error_kind(error: &Report) -> Option<io::ErrorKind> {
313 /// for cause in error.chain() {
314 /// if let Some(io_error) = cause.downcast_ref::<io::Error>() {
315 /// return Some(io_error.kind());
316 /// }
317 /// }
318 /// None
319 /// }
320 /// ```
321 pub fn chain(&self) -> Chain<'_> {
322 ErrorImpl::chain(self.inner.as_ref())
323 }
324
325 /// The lowest level cause of this error — this error's cause's
326 /// cause's cause etc.
327 ///
328 /// The root cause is the last error in the iterator produced by
329 /// [`chain()`][Report::chain].
330 pub fn root_cause(&self) -> &(dyn StdError + 'static) {
331 let mut chain = self.chain();
332 let mut root_cause = chain.next().unwrap();
333 for cause in chain {
334 root_cause = cause;
335 }
336 root_cause
337 }
338
339 /// Returns true if `E` is the type held by this error object.
340 ///
341 /// For errors constructed from messages, this method returns true if `E` matches the type of
342 /// the message `D` **or** the type of the error on which the message has been attached. For
343 /// details about the interaction between message and downcasting, [see here].
344 ///
345 /// [see here]: trait.WrapErr.html#effect-on-downcasting
346 pub fn is<E>(&self) -> bool
347 where
348 E: Display + Debug + Send + Sync + 'static,
349 {
350 self.downcast_ref::<E>().is_some()
351 }
352
353 /// Attempt to downcast the error object to a concrete type.
354 pub fn downcast<E>(self) -> Result<E, Self>
355 where
356 E: Display + Debug + Send + Sync + 'static,
357 {
358 let target = TypeId::of::<E>();
359 unsafe {
360 // Use vtable to find NonNull<()> which points to a value of type E
361 // somewhere inside the data structure.
362 let addr = match (self.vtable().object_downcast)(self.inner.as_ref(), target) {
363 Some(addr) => addr,
364 None => return Err(self),
365 };
366
367 // Prepare to read E out of the data structure. We'll drop the rest
368 // of the data structure separately so that E is not dropped.
369 let outer = ManuallyDrop::new(self);
370
371 // Read E from where the vtable found it.
372 let error = ptr::read(addr.cast::<E>().as_ptr());
373
374 // Read Box<ErrorImpl<()>> from self. Can't move it out because
375 // Report has a Drop impl which we want to not run.
376 let inner = ptr::read(&outer.inner);
377
378 // Drop rest of the data structure outside of E.
379 (outer.vtable().object_drop_rest)(inner, target);
380
381 Ok(error)
382 }
383 }
384
385 /// Downcast this error object by reference.
386 ///
387 /// # Example
388 ///
389 /// ```
390 /// # use eyre::{Report, eyre};
391 /// # use std::fmt::{self, Display};
392 /// # use std::task::Poll;
393 /// #
394 /// # #[derive(Debug)]
395 /// # enum DataStoreError {
396 /// # Censored(()),
397 /// # }
398 /// #
399 /// # impl Display for DataStoreError {
400 /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
401 /// # unimplemented!()
402 /// # }
403 /// # }
404 /// #
405 /// # impl std::error::Error for DataStoreError {}
406 /// #
407 /// # const REDACTED_CONTENT: () = ();
408 /// #
409 /// # #[cfg(not(feature = "auto-install"))]
410 /// # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
411 /// #
412 /// # let error: Report = eyre!("...");
413 /// # let root_cause = &error;
414 /// #
415 /// # let ret =
416 /// // If the error was caused by redaction, then return a tombstone instead
417 /// // of the content.
418 /// match root_cause.downcast_ref::<DataStoreError>() {
419 /// Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
420 /// None => Err(error),
421 /// }
422 /// # ;
423 /// ```
424 pub fn downcast_ref<E>(&self) -> Option<&E>
425 where
426 E: Display + Debug + Send + Sync + 'static,
427 {
428 let target = TypeId::of::<E>();
429 unsafe {
430 // Use vtable to find NonNull<()> which points to a value of type E
431 // somewhere inside the data structure.
432 let addr = (self.vtable().object_downcast)(self.inner.as_ref(), target)?;
433 Some(addr.cast::<E>().as_ref())
434 }
435 }
436
437 /// Downcast this error object by mutable reference.
438 pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
439 where
440 E: Display + Debug + Send + Sync + 'static,
441 {
442 let target = TypeId::of::<E>();
443 unsafe {
444 // Use vtable to find NonNull<()> which points to a value of type E
445 // somewhere inside the data structure.
446 let addr = (self.vtable().object_downcast_mut)(self.inner.as_mut(), target)?;
447 Some(addr.cast::<E>().as_mut())
448 }
449 }
450
451 /// Get a reference to the Handler for this Report.
452 pub fn handler(&self) -> &dyn EyreHandler {
453 header(self.inner.as_ref())
454 .handler
455 .as_ref()
456 .unwrap()
457 .as_ref()
458 }
459
460 /// Get a mutable reference to the Handler for this Report.
461 pub fn handler_mut(&mut self) -> &mut dyn EyreHandler {
462 header_mut(self.inner.as_mut())
463 .handler
464 .as_mut()
465 .unwrap()
466 .as_mut()
467 }
468
469 /// Get a reference to the Handler for this Report.
470 #[doc(hidden)]
471 pub fn context(&self) -> &dyn EyreHandler {
472 header(self.inner.as_ref())
473 .handler
474 .as_ref()
475 .unwrap()
476 .as_ref()
477 }
478
479 /// Get a mutable reference to the Handler for this Report.
480 #[doc(hidden)]
481 pub fn context_mut(&mut self) -> &mut dyn EyreHandler {
482 header_mut(self.inner.as_mut())
483 .handler
484 .as_mut()
485 .unwrap()
486 .as_mut()
487 }
488}
489
490impl<E> From<E> for Report
491where
492 E: StdError + Send + Sync + 'static,
493{
494 #[cfg_attr(track_caller, track_caller)]
495 fn from(error: E) -> Self {
496 Report::from_std(error)
497 }
498}
499
500impl Deref for Report {
501 type Target = dyn StdError + Send + Sync + 'static;
502
503 fn deref(&self) -> &Self::Target {
504 ErrorImpl::error(self.inner.as_ref())
505 }
506}
507
508impl DerefMut for Report {
509 fn deref_mut(&mut self) -> &mut Self::Target {
510 ErrorImpl::error_mut(self.inner.as_mut())
511 }
512}
513
514impl Display for Report {
515 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
516 ErrorImpl::display(self.inner.as_ref(), formatter)
517 }
518}
519
520impl Debug for Report {
521 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
522 ErrorImpl::debug(self.inner.as_ref(), formatter)
523 }
524}
525
526impl Drop for Report {
527 fn drop(&mut self) {
528 unsafe {
529 // Read Box<ErrorImpl<()>> from self.
530 (self.vtable().object_drop)(self.inner);
531 }
532 }
533}
534
535struct ErrorVTable {
536 object_drop: unsafe fn(OwnedPtr<ErrorImpl<()>>),
537 object_ref: unsafe fn(RefPtr<'_, ErrorImpl<()>>) -> &(dyn StdError + Send + Sync + 'static),
538 object_mut: unsafe fn(MutPtr<'_, ErrorImpl<()>>) -> &mut (dyn StdError + Send + Sync + 'static),
539 #[allow(clippy::type_complexity)]
540 object_boxed: unsafe fn(OwnedPtr<ErrorImpl<()>>) -> Box<dyn StdError + Send + Sync + 'static>,
541 object_downcast: unsafe fn(RefPtr<'_, ErrorImpl<()>>, TypeId) -> Option<NonNull<()>>,
542 object_downcast_mut: unsafe fn(MutPtr<'_, ErrorImpl<()>>, TypeId) -> Option<NonNull<()>>,
543 object_drop_rest: unsafe fn(OwnedPtr<ErrorImpl<()>>, TypeId),
544}
545
546/// # Safety
547///
548/// Requires layout of *e to match ErrorImpl<E>.
549unsafe fn object_drop<E>(e: OwnedPtr<ErrorImpl<()>>) {
550 // Cast to a context type and drop the Box allocation.
551 let unerased = unsafe { e.cast::<ErrorImpl<E>>().into_box() };
552 drop(unerased);
553}
554
555/// # Safety
556///
557/// Requires layout of *e to match ErrorImpl<E>.
558unsafe fn object_drop_front<E>(e: OwnedPtr<ErrorImpl<()>>, target: TypeId) {
559 // Drop the fields of ErrorImpl other than E as well as the Box allocation,
560 // without dropping E itself. This is used by downcast after doing a
561 // ptr::read to take ownership of the E.
562 let _ = target;
563 // Note: This must not use `mem::transmute` because it tries to reborrow the `Unique`
564 // contained in `Box`, which must not be done. In practice this probably won't make any
565 // difference by now, but technically it's unsound.
566 // see: https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.m
567 let unerased = unsafe { e.cast::<ErrorImpl<E>>().into_box() };
568
569 mem::forget(unerased._object)
570}
571
572/// # Safety
573///
574/// Requires layout of *e to match ErrorImpl<E>.
575unsafe fn object_ref<E>(e: RefPtr<'_, ErrorImpl<()>>) -> &(dyn StdError + Send + Sync + 'static)
576where
577 E: StdError + Send + Sync + 'static,
578{
579 // Attach E's native StdError vtable onto a pointer to self._object.
580 &unsafe { e.cast::<ErrorImpl<E>>().as_ref() }._object
581}
582
583/// # Safety
584///
585/// Requires layout of *e to match ErrorImpl<E>.
586unsafe fn object_mut<E>(e: MutPtr<'_, ErrorImpl<()>>) -> &mut (dyn StdError + Send + Sync + 'static)
587where
588 E: StdError + Send + Sync + 'static,
589{
590 // Attach E's native StdError vtable onto a pointer to self._object.
591 &mut unsafe { e.cast::<ErrorImpl<E>>().into_mut() }._object
592}
593
594/// # Safety
595///
596/// Requires layout of *e to match ErrorImpl<E>.
597unsafe fn object_boxed<E>(e: OwnedPtr<ErrorImpl<()>>) -> Box<dyn StdError + Send + Sync + 'static>
598where
599 E: StdError + Send + Sync + 'static,
600{
601 // Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below.
602 unsafe { e.cast::<ErrorImpl<E>>().into_box() }
603}
604
605/// # Safety
606///
607/// Requires layout of *e to match ErrorImpl<E>. Ensures that returned pointee's layout
608/// matches `target`.
609unsafe fn object_downcast<E>(e: RefPtr<'_, ErrorImpl<()>>, target: TypeId) -> Option<NonNull<()>>
610where
611 E: 'static,
612{
613 if TypeId::of::<E>() == target {
614 // Caller is looking for an E pointer and e is ErrorImpl<E>, take a
615 // pointer to its E field.
616 let unerased = unsafe { e.cast::<ErrorImpl<E>>().as_ref() };
617 Some(NonNull::from(&(unerased._object)).cast::<()>())
618 } else {
619 None
620 }
621}
622
623/// # Safety
624///
625/// Requires layout of *e to match ErrorImpl<E>. Ensures that returned pointee's layout
626/// matches `target`.
627unsafe fn object_downcast_mut<E>(
628 e: MutPtr<'_, ErrorImpl<()>>,
629 target: TypeId,
630) -> Option<NonNull<()>>
631where
632 E: 'static,
633{
634 if TypeId::of::<E>() == target {
635 // Caller is looking for an E pointer and e is ErrorImpl<E>, take a
636 // pointer to its E field.
637 let unerased = unsafe { e.cast::<ErrorImpl<E>>().into_mut() };
638 Some(NonNull::from(&mut (unerased._object)).cast::<()>())
639 } else {
640 None
641 }
642}
643
644/// # Safety
645///
646/// Requires layout of *e to match ErrorImpl<ContextError<D, E>>. Ensures that returned
647/// pointee's layout matches `target`.
648unsafe fn context_downcast<D, E>(
649 e: RefPtr<'_, ErrorImpl<()>>,
650 target: TypeId,
651) -> Option<NonNull<()>>
652where
653 D: 'static,
654 E: 'static,
655{
656 let unerased = e.cast::<ErrorImpl<ContextError<D, E>>>();
657 if TypeId::of::<D>() == target {
658 // Safety: Layout of `*unerased` matches `ErrorImpl<ContextError<D, E>>`.
659 let addr = unsafe { ptr::addr_of!((*unerased.ptr.as_ptr())._object.msg) };
660 // Safety: `addr` is not null, layout matches `D`.
661 Some(unsafe { NonNull::new_unchecked(addr.cast_mut()).cast::<()>() })
662 } else if TypeId::of::<E>() == target {
663 // Safety: Layout of `*unerased` matches `ErrorImpl<ContextError<D, E>>`.
664 let addr = unsafe { ptr::addr_of!((*unerased.ptr.as_ptr())._object.error) };
665 // Safety: `addr` is not null, layout matches `E`.
666 Some(unsafe { NonNull::new_unchecked(addr.cast_mut()).cast::<()>() })
667 } else {
668 None
669 }
670}
671
672/// # Safety
673///
674/// Requires layout of *e to match ErrorImpl<ContextError<D, E>>. Ensures that returned
675/// pointee's layout matches `target`.
676unsafe fn context_downcast_mut<D, E>(
677 e: MutPtr<'_, ErrorImpl<()>>,
678 target: TypeId,
679) -> Option<NonNull<()>>
680where
681 D: 'static,
682 E: 'static,
683{
684 let unerased = e.cast::<ErrorImpl<ContextError<D, E>>>();
685 if TypeId::of::<D>() == target {
686 // Safety: Layout of `*unerased` matches `ErrorImpl<ContextError<D, E>>`.
687 let addr = unsafe { ptr::addr_of_mut!((*unerased.ptr.as_ptr())._object.msg) };
688 // Safety: `addr` is not null, layout matches `D`.
689 Some(unsafe { NonNull::new_unchecked(addr).cast::<()>() })
690 } else if TypeId::of::<E>() == target {
691 // Safety: Layout of `*unerased` matches `ErrorImpl<ContextError<D, E>>`.
692 let addr = unsafe { ptr::addr_of_mut!((*unerased.ptr.as_ptr())._object.error) };
693 // Safety: `addr` is not null, layout matches `E`.
694 Some(unsafe { NonNull::new_unchecked(addr).cast::<()>() })
695 } else {
696 None
697 }
698}
699/// # Safety
700///
701/// Requires layout of *e to match ErrorImpl<ContextError<D, E>>.
702unsafe fn context_drop_rest<D, E>(e: OwnedPtr<ErrorImpl<()>>, target: TypeId)
703where
704 D: 'static,
705 E: 'static,
706{
707 // Called after downcasting by value to either the D or the E and doing a
708 // ptr::read to take ownership of that value.
709 if TypeId::of::<D>() == target {
710 unsafe {
711 e.cast::<ErrorImpl<ContextError<ManuallyDrop<D>, E>>>()
712 .into_box()
713 };
714 } else {
715 debug_assert_eq!(TypeId::of::<E>(), target);
716 unsafe {
717 e.cast::<ErrorImpl<ContextError<D, ManuallyDrop<E>>>>()
718 .into_box()
719 };
720 }
721}
722
723/// # Safety
724///
725/// Requires layout of *e to match ErrorImpl<ContextError<D, Report>>. Ensures that returned pointee's
726/// layout matches `target`.
727unsafe fn context_chain_downcast<D>(
728 e: RefPtr<'_, ErrorImpl<()>>,
729 target: TypeId,
730) -> Option<NonNull<()>>
731where
732 D: 'static,
733{
734 let unerased = e.cast::<ErrorImpl<ContextError<D, Report>>>();
735 if TypeId::of::<D>() == target {
736 // Safety: Layout of `*unerased` matches `ErrorImpl<ContextError<D, Report>>`.
737 let addr = unsafe { ptr::addr_of!((*unerased.ptr.as_ptr())._object.msg) };
738 // Safety: `addr` is not not null, layout matches `D`.
739 Some(unsafe { NonNull::new_unchecked(addr.cast_mut()).cast::<()>() })
740 } else {
741 // Recurse down the context chain per the inner error's vtable.
742 // Safety: Layout of *unerased matches `ErrorImpl<ContextExrror<D, Report>>`.
743 let source = unsafe { &unerased.as_ref()._object.error };
744 unsafe { (source.vtable().object_downcast)(source.inner.as_ref(), target) }
745 }
746}
747
748/// # Safety
749///
750/// Requires layout of *e to match ErrorImpl<ContextError<D, Report>>. Ensures that returned pointee's
751/// layout matches `target`.
752unsafe fn context_chain_downcast_mut<D>(
753 e: MutPtr<'_, ErrorImpl<()>>,
754 target: TypeId,
755) -> Option<NonNull<()>>
756where
757 D: 'static,
758{
759 let unerased = e.cast::<ErrorImpl<ContextError<D, Report>>>();
760 if TypeId::of::<D>() == target {
761 let addr = unsafe { ptr::addr_of_mut!((*unerased.ptr.as_ptr())._object.msg) };
762 Some(unsafe { NonNull::new_unchecked(addr).cast::<()>() })
763 } else {
764 // Recurse down the context chain per the inner error's vtable.
765 // Safety: Layout of *unerased matches `ErrorImpl<ContextExrror<D, Report>>`.
766 let source = unsafe { &mut unerased.into_mut()._object.error };
767 unsafe { (source.vtable().object_downcast_mut)(source.inner.as_mut(), target) }
768 }
769}
770
771/// # Safety
772///
773/// Requires layout of *e to match ErrorImpl<ContextError<D, Report>>.
774unsafe fn context_chain_drop_rest<D>(e: OwnedPtr<ErrorImpl<()>>, target: TypeId)
775where
776 D: 'static,
777{
778 // Called after downcasting by value to either the D or one of the causes
779 // and doing a ptr::read to take ownership of that value.
780 if TypeId::of::<D>() == target {
781 let unerased = unsafe {
782 e.cast::<ErrorImpl<ContextError<ManuallyDrop<D>, Report>>>()
783 .into_box()
784 };
785 // Drop the entire rest of the data structure rooted in the next Report.
786 drop(unerased);
787 } else {
788 unsafe {
789 let unerased = e
790 .cast::<ErrorImpl<ContextError<D, ManuallyDrop<Report>>>>()
791 .into_box();
792 // Read out a ManuallyDrop<Box<ErrorImpl<()>>> from the next error.
793 let inner = ptr::read(&unerased.as_ref()._object.error.inner);
794 drop(unerased);
795 // Recursively drop the next error using the same target typeid.
796 (header(inner.as_ref()).vtable.object_drop_rest)(inner, target);
797 }
798 }
799}
800
801#[repr(C)]
802pub(crate) struct ErrorHeader {
803 vtable: &'static ErrorVTable,
804 pub(crate) handler: Option<Box<dyn EyreHandler>>,
805}
806
807// repr C to ensure that E remains in the final position.
808#[repr(C)]
809pub(crate) struct ErrorImpl<E = ()> {
810 header: ErrorHeader,
811 // NOTE: Don't use directly. Use only through vtable. Erased type may have
812 // different alignment.
813 _object: E,
814}
815
816// repr C to ensure that ContextError<D, E> has the same layout as
817// ContextError<ManuallyDrop<D>, E> and ContextError<D, ManuallyDrop<E>>.
818#[repr(C)]
819pub(crate) struct ContextError<D, E> {
820 pub(crate) msg: D,
821 pub(crate) error: E,
822}
823
824impl<E> ErrorImpl<E> {
825 /// Returns a type erased Error
826 fn erase(&self) -> RefPtr<'_, ErrorImpl<()>> {
827 // Erase the concrete type of E but preserve the vtable in self.vtable
828 // for manipulating the resulting thin pointer. This is analogous to an
829 // unsize coersion.
830 RefPtr::new(self).cast()
831 }
832}
833
834// Reads the header out of `p`. This is the same as `p.as_ref().header`, but
835// avoids converting `p` into a reference of a shrunk provenance with a type different than the
836// allocation.
837fn header(p: RefPtr<'_, ErrorImpl<()>>) -> &'_ ErrorHeader {
838 // Safety: `ErrorHeader` is the first field of repr(C) `ErrorImpl`
839 unsafe { p.cast().as_ref() }
840}
841
842fn header_mut(p: MutPtr<'_, ErrorImpl<()>>) -> &mut ErrorHeader {
843 // Safety: `ErrorHeader` is the first field of repr(C) `ErrorImpl`
844 unsafe { p.cast().into_mut() }
845}
846
847impl ErrorImpl<()> {
848 pub(crate) fn error(this: RefPtr<'_, Self>) -> &(dyn StdError + Send + Sync + 'static) {
849 // Use vtable to attach E's native StdError vtable for the right
850 // original type E.
851 unsafe { (header(this).vtable.object_ref)(this) }
852 }
853
854 pub(crate) fn error_mut(this: MutPtr<'_, Self>) -> &mut (dyn StdError + Send + Sync + 'static) {
855 // Use vtable to attach E's native StdError vtable for the right
856 // original type E.
857 unsafe { (header_mut(this).vtable.object_mut)(this) }
858 }
859
860 pub(crate) fn chain(this: RefPtr<'_, Self>) -> Chain<'_> {
861 Chain::new(Self::error(this))
862 }
863
864 pub(crate) fn header(this: RefPtr<'_, ErrorImpl>) -> &ErrorHeader {
865 header(this)
866 }
867}
868
869impl<E> StdError for ErrorImpl<E>
870where
871 E: StdError,
872{
873 #[cfg(generic_member_access)]
874 fn provide<'a>(&'a self, request: &mut std::error::Request<'a>) {
875 self._object.provide(request)
876 }
877
878 fn source(&self) -> Option<&(dyn StdError + 'static)> {
879 ErrorImpl::<()>::error(self.erase()).source()
880 }
881}
882
883impl<E> Debug for ErrorImpl<E>
884where
885 E: Debug,
886{
887 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
888 ErrorImpl::debug(self.erase(), formatter)
889 }
890}
891
892impl<E> Display for ErrorImpl<E>
893where
894 E: Display,
895{
896 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
897 Display::fmt(ErrorImpl::error(self.erase()), formatter)
898 }
899}
900
901impl From<Report> for Box<dyn StdError + Send + Sync + 'static> {
902 fn from(error: Report) -> Self {
903 let outer = ManuallyDrop::new(error);
904 unsafe {
905 // Read Box<ErrorImpl<()>> from error. Can't move it out because
906 // Report has a Drop impl which we want to not run.
907 // Use vtable to attach ErrorImpl<E>'s native StdError vtable for
908 // the right original type E.
909 (header(outer.inner.as_ref()).vtable.object_boxed)(outer.inner)
910 }
911 }
912}
913
914impl From<Report> for Box<dyn StdError + 'static> {
915 fn from(error: Report) -> Self {
916 Box::<dyn StdError + Send + Sync>::from(error)
917 }
918}
919
920impl AsRef<dyn StdError + Send + Sync> for Report {
921 fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
922 &**self
923 }
924}
925
926impl AsRef<dyn StdError> for Report {
927 fn as_ref(&self) -> &(dyn StdError + 'static) {
928 &**self
929 }
930}