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 #[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 #[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 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 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 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 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 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 unsafe { Report::construct(error, vtable, handler) }
186 }
187
188 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 let ptr = OwnedPtr::<ErrorImpl<E>>::new(inner);
211
212 let ptr = ptr.cast::<ErrorImpl<()>>();
214 Report { inner: ptr }
215 }
216
217 pub fn wrap_err<D>(mut self, msg: D) -> Self
271 where
272 D: Display + Send + Sync + 'static,
273 {
274 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 unsafe { Report::construct(error, vtable, handler) }
293 }
294
295 fn vtable(&self) -> &'static ErrorVTable {
297 header(self.inner.as_ref()).vtable
298 }
299
300 pub fn chain(&self) -> Chain<'_> {
322 ErrorImpl::chain(self.inner.as_ref())
323 }
324
325 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 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 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 let addr = match (self.vtable().object_downcast)(self.inner.as_ref(), target) {
363 Some(addr) => addr,
364 None => return Err(self),
365 };
366
367 let outer = ManuallyDrop::new(self);
370
371 let error = ptr::read(addr.cast::<E>().as_ptr());
373
374 let inner = ptr::read(&outer.inner);
377
378 (outer.vtable().object_drop_rest)(inner, target);
380
381 Ok(error)
382 }
383 }
384
385 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 let addr = (self.vtable().object_downcast)(self.inner.as_ref(), target)?;
433 Some(addr.cast::<E>().as_ref())
434 }
435 }
436
437 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 let addr = (self.vtable().object_downcast_mut)(self.inner.as_mut(), target)?;
447 Some(addr.cast::<E>().as_mut())
448 }
449 }
450
451 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 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 #[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 #[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 (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
546unsafe fn object_drop<E>(e: OwnedPtr<ErrorImpl<()>>) {
550 let unerased = unsafe { e.cast::<ErrorImpl<E>>().into_box() };
552 drop(unerased);
553}
554
555unsafe fn object_drop_front<E>(e: OwnedPtr<ErrorImpl<()>>, target: TypeId) {
559 let _ = target;
563 let unerased = unsafe { e.cast::<ErrorImpl<E>>().into_box() };
568
569 mem::forget(unerased._object)
570}
571
572unsafe fn object_ref<E>(e: RefPtr<'_, ErrorImpl<()>>) -> &(dyn StdError + Send + Sync + 'static)
576where
577 E: StdError + Send + Sync + 'static,
578{
579 &unsafe { e.cast::<ErrorImpl<E>>().as_ref() }._object
581}
582
583unsafe fn object_mut<E>(e: MutPtr<'_, ErrorImpl<()>>) -> &mut (dyn StdError + Send + Sync + 'static)
587where
588 E: StdError + Send + Sync + 'static,
589{
590 &mut unsafe { e.cast::<ErrorImpl<E>>().into_mut() }._object
592}
593
594unsafe fn object_boxed<E>(e: OwnedPtr<ErrorImpl<()>>) -> Box<dyn StdError + Send + Sync + 'static>
598where
599 E: StdError + Send + Sync + 'static,
600{
601 unsafe { e.cast::<ErrorImpl<E>>().into_box() }
603}
604
605unsafe fn object_downcast<E>(e: RefPtr<'_, ErrorImpl<()>>, target: TypeId) -> Option<NonNull<()>>
609where
610 E: 'static,
611{
612 if TypeId::of::<E>() == target {
613 let unerased = unsafe { e.cast::<ErrorImpl<E>>().as_ref() };
616 Some(NonNull::from(&(unerased._object)).cast::<()>())
617 } else {
618 None
619 }
620}
621
622unsafe fn object_downcast_mut<E>(
626 e: MutPtr<'_, ErrorImpl<()>>,
627 target: TypeId,
628) -> Option<NonNull<()>>
629where
630 E: 'static,
631{
632 if TypeId::of::<E>() == target {
633 let unerased = unsafe { e.cast::<ErrorImpl<E>>().into_mut() };
636 Some(NonNull::from(&mut (unerased._object)).cast::<()>())
637 } else {
638 None
639 }
640}
641
642unsafe fn context_downcast<D, E>(
646 e: RefPtr<'_, ErrorImpl<()>>,
647 target: TypeId,
648) -> Option<NonNull<()>>
649where
650 D: 'static,
651 E: 'static,
652{
653 if TypeId::of::<D>() == target {
654 let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, E>>>().as_ref() };
655 let addr = NonNull::from(&unerased._object.msg).cast::<()>();
656 Some(addr)
657 } else if TypeId::of::<E>() == target {
658 let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, E>>>().as_ref() };
659 let addr = NonNull::from(&unerased._object.error).cast::<()>();
660 Some(addr)
661 } else {
662 None
663 }
664}
665
666unsafe fn context_downcast_mut<D, E>(
670 e: MutPtr<'_, ErrorImpl<()>>,
671 target: TypeId,
672) -> Option<NonNull<()>>
673where
674 D: 'static,
675 E: 'static,
676{
677 if TypeId::of::<D>() == target {
678 let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, E>>>().into_mut() };
679 let addr = NonNull::from(&unerased._object.msg).cast::<()>();
680 Some(addr)
681 } else if TypeId::of::<E>() == target {
682 let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, E>>>().into_mut() };
683 let addr = NonNull::from(&mut unerased._object.error).cast::<()>();
684 Some(addr)
685 } else {
686 None
687 }
688}
689unsafe fn context_drop_rest<D, E>(e: OwnedPtr<ErrorImpl<()>>, target: TypeId)
693where
694 D: 'static,
695 E: 'static,
696{
697 if TypeId::of::<D>() == target {
700 unsafe {
701 e.cast::<ErrorImpl<ContextError<ManuallyDrop<D>, E>>>()
702 .into_box()
703 };
704 } else {
705 debug_assert_eq!(TypeId::of::<E>(), target);
706 unsafe {
707 e.cast::<ErrorImpl<ContextError<D, ManuallyDrop<E>>>>()
708 .into_box()
709 };
710 }
711}
712
713unsafe fn context_chain_downcast<D>(
717 e: RefPtr<'_, ErrorImpl<()>>,
718 target: TypeId,
719) -> Option<NonNull<()>>
720where
721 D: 'static,
722{
723 let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, Report>>>().as_ref() };
724 if TypeId::of::<D>() == target {
725 let addr = NonNull::from(&unerased._object.msg).cast::<()>();
726 Some(addr)
727 } else {
728 let source = &unerased._object.error;
730 unsafe { (source.vtable().object_downcast)(source.inner.as_ref(), target) }
731 }
732}
733
734unsafe fn context_chain_downcast_mut<D>(
738 e: MutPtr<'_, ErrorImpl<()>>,
739 target: TypeId,
740) -> Option<NonNull<()>>
741where
742 D: 'static,
743{
744 let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, Report>>>().into_mut() };
745 if TypeId::of::<D>() == target {
746 let addr = NonNull::from(&unerased._object.msg).cast::<()>();
747 Some(addr)
748 } else {
749 let source = &mut unerased._object.error;
751 unsafe { (source.vtable().object_downcast_mut)(source.inner.as_mut(), target) }
752 }
753}
754
755unsafe fn context_chain_drop_rest<D>(e: OwnedPtr<ErrorImpl<()>>, target: TypeId)
759where
760 D: 'static,
761{
762 if TypeId::of::<D>() == target {
765 let unerased = unsafe {
766 e.cast::<ErrorImpl<ContextError<ManuallyDrop<D>, Report>>>()
767 .into_box()
768 };
769 drop(unerased);
771 } else {
772 unsafe {
773 let unerased = e
774 .cast::<ErrorImpl<ContextError<D, ManuallyDrop<Report>>>>()
775 .into_box();
776 let inner = ptr::read(&unerased.as_ref()._object.error.inner);
778 drop(unerased);
779 (header(inner.as_ref()).vtable.object_drop_rest)(inner, target);
781 }
782 }
783}
784
785#[repr(C)]
786pub(crate) struct ErrorHeader {
787 vtable: &'static ErrorVTable,
788 pub(crate) handler: Option<Box<dyn EyreHandler>>,
789}
790
791#[repr(C)]
793pub(crate) struct ErrorImpl<E = ()> {
794 header: ErrorHeader,
795 _object: E,
798}
799
800#[repr(C)]
803pub(crate) struct ContextError<D, E> {
804 pub(crate) msg: D,
805 pub(crate) error: E,
806}
807
808impl<E> ErrorImpl<E> {
809 fn erase(&self) -> RefPtr<'_, ErrorImpl<()>> {
811 RefPtr::new(self).cast()
815 }
816}
817
818fn header(p: RefPtr<'_, ErrorImpl<()>>) -> &'_ ErrorHeader {
822 unsafe { p.cast().as_ref() }
824}
825
826fn header_mut(p: MutPtr<'_, ErrorImpl<()>>) -> &mut ErrorHeader {
827 unsafe { p.cast().into_mut() }
829}
830
831impl ErrorImpl<()> {
832 pub(crate) fn error(this: RefPtr<'_, Self>) -> &(dyn StdError + Send + Sync + 'static) {
833 unsafe { (header(this).vtable.object_ref)(this) }
836 }
837
838 pub(crate) fn error_mut(this: MutPtr<'_, Self>) -> &mut (dyn StdError + Send + Sync + 'static) {
839 unsafe { (header_mut(this).vtable.object_mut)(this) }
842 }
843
844 pub(crate) fn chain(this: RefPtr<'_, Self>) -> Chain<'_> {
845 Chain::new(Self::error(this))
846 }
847
848 pub(crate) fn header(this: RefPtr<'_, ErrorImpl>) -> &ErrorHeader {
849 header(this)
850 }
851}
852
853impl<E> StdError for ErrorImpl<E>
854where
855 E: StdError,
856{
857 fn source(&self) -> Option<&(dyn StdError + 'static)> {
858 ErrorImpl::<()>::error(self.erase()).source()
859 }
860}
861
862impl<E> Debug for ErrorImpl<E>
863where
864 E: Debug,
865{
866 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
867 ErrorImpl::debug(self.erase(), formatter)
868 }
869}
870
871impl<E> Display for ErrorImpl<E>
872where
873 E: Display,
874{
875 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
876 Display::fmt(ErrorImpl::error(self.erase()), formatter)
877 }
878}
879
880impl From<Report> for Box<dyn StdError + Send + Sync + 'static> {
881 fn from(error: Report) -> Self {
882 let outer = ManuallyDrop::new(error);
883 unsafe {
884 (header(outer.inner.as_ref()).vtable.object_boxed)(outer.inner)
889 }
890 }
891}
892
893impl From<Report> for Box<dyn StdError + 'static> {
894 fn from(error: Report) -> Self {
895 Box::<dyn StdError + Send + Sync>::from(error)
896 }
897}
898
899impl AsRef<dyn StdError + Send + Sync> for Report {
900 fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
901 &**self
902 }
903}
904
905impl AsRef<dyn StdError> for Report {
906 fn as_ref(&self) -> &(dyn StdError + 'static) {
907 &**self
908 }
909}
910
911#[cfg(feature = "pyo3")]
912mod pyo3_compat;