1 use core::any::TypeId;
2 use core::fmt::{self, Debug, Display};
3 use core::mem::ManuallyDrop;
4 use core::ptr::{self, NonNull};
5 use std::error::Error as StdError;
6 
7 use super::ptr::{Mut, Own, Ref};
8 use super::Report;
9 use super::ReportHandler;
10 use crate::chain::Chain;
11 use crate::eyreish::wrapper::WithSourceCode;
12 use crate::{Diagnostic, SourceCode};
13 use core::ops::{Deref, DerefMut};
14 
15 impl Report {
16     /// Create a new error object from any error type.
17     ///
18     /// The error type must be thread safe and `'static`, so that the `Report`
19     /// will be as well.
20     ///
21     /// If the error type does not provide a backtrace, a backtrace will be
22     /// created here to ensure that a backtrace exists.
23     #[cfg_attr(track_caller, track_caller)]
new<E>(error: E) -> Self where E: Diagnostic + Send + Sync + 'static,24     pub fn new<E>(error: E) -> Self
25     where
26         E: Diagnostic + Send + Sync + 'static,
27     {
28         Report::from_std(error)
29     }
30 
31     /// Create a new error object from a printable error message.
32     ///
33     /// If the argument implements std::error::Error, prefer `Report::new`
34     /// instead which preserves the underlying error's cause chain and
35     /// backtrace. If the argument may or may not implement std::error::Error
36     /// now or in the future, use `miette!(err)` which handles either way
37     /// correctly.
38     ///
39     /// `Report::msg("...")` is equivalent to `miette!("...")` but occasionally
40     /// convenient in places where a function is preferable over a macro, such
41     /// as iterator or stream combinators:
42     ///
43     /// ```
44     /// # mod ffi {
45     /// #     pub struct Input;
46     /// #     pub struct Output;
47     /// #     pub async fn do_some_work(_: Input) -> Result<Output, &'static str> {
48     /// #         unimplemented!()
49     /// #     }
50     /// # }
51     /// #
52     /// # use ffi::{Input, Output};
53     /// #
54     /// use futures::stream::{Stream, StreamExt, TryStreamExt};
55     /// use miette::{Report, Result};
56     ///
57     /// async fn demo<S>(stream: S) -> Result<Vec<Output>>
58     /// where
59     ///     S: Stream<Item = Input>,
60     /// {
61     ///     stream
62     ///         .then(ffi::do_some_work) // returns Result<Output, &str>
63     ///         .map_err(Report::msg)
64     ///         .try_collect()
65     ///         .await
66     /// }
67     /// ```
68     #[cfg_attr(track_caller, track_caller)]
msg<M>(message: M) -> Self where M: Display + Debug + Send + Sync + 'static,69     pub fn msg<M>(message: M) -> Self
70     where
71         M: Display + Debug + Send + Sync + 'static,
72     {
73         Report::from_adhoc(message)
74     }
75 
76     /// Create a new error object from a boxed [`Diagnostic`].
77     ///
78     /// The boxed type must be thread safe and 'static, so that the `Report`
79     /// will be as well.
80     ///
81     /// Boxed `Diagnostic`s don't implement `Diagnostic` themselves due to trait coherence issues.
82     /// This method allows you to create a `Report` from a boxed `Diagnostic`.
83     #[cfg_attr(track_caller, track_caller)]
new_boxed(error: Box<dyn Diagnostic + Send + Sync + 'static>) -> Self84     pub fn new_boxed(error: Box<dyn Diagnostic + Send + Sync + 'static>) -> Self {
85         Report::from_boxed(error)
86     }
87 
88     #[cfg_attr(track_caller, track_caller)]
from_std<E>(error: E) -> Self where E: Diagnostic + Send + Sync + 'static,89     pub(crate) fn from_std<E>(error: E) -> Self
90     where
91         E: Diagnostic + Send + Sync + 'static,
92     {
93         let vtable = &ErrorVTable {
94             object_drop: object_drop::<E>,
95             object_ref: object_ref::<E>,
96             object_ref_stderr: object_ref_stderr::<E>,
97             object_boxed: object_boxed::<E>,
98             object_boxed_stderr: object_boxed_stderr::<E>,
99             object_downcast: object_downcast::<E>,
100             object_drop_rest: object_drop_front::<E>,
101         };
102 
103         // Safety: passing vtable that operates on the right type E.
104         let handler = Some(super::capture_handler(&error));
105 
106         unsafe { Report::construct(error, vtable, handler) }
107     }
108 
109     #[cfg_attr(track_caller, track_caller)]
from_adhoc<M>(message: M) -> Self where M: Display + Debug + Send + Sync + 'static,110     pub(crate) fn from_adhoc<M>(message: M) -> Self
111     where
112         M: Display + Debug + Send + Sync + 'static,
113     {
114         use super::wrapper::MessageError;
115         let error: MessageError<M> = MessageError(message);
116         let vtable = &ErrorVTable {
117             object_drop: object_drop::<MessageError<M>>,
118             object_ref: object_ref::<MessageError<M>>,
119             object_ref_stderr: object_ref_stderr::<MessageError<M>>,
120             object_boxed: object_boxed::<MessageError<M>>,
121             object_boxed_stderr: object_boxed_stderr::<MessageError<M>>,
122             object_downcast: object_downcast::<M>,
123             object_drop_rest: object_drop_front::<M>,
124         };
125 
126         // Safety: MessageError is repr(transparent) so it is okay for the
127         // vtable to allow casting the MessageError<M> to M.
128         let handler = Some(super::capture_handler(&error));
129 
130         unsafe { Report::construct(error, vtable, handler) }
131     }
132 
133     #[cfg_attr(track_caller, track_caller)]
from_msg<D, E>(msg: D, error: E) -> Self where D: Display + Send + Sync + 'static, E: Diagnostic + Send + Sync + 'static,134     pub(crate) fn from_msg<D, E>(msg: D, error: E) -> Self
135     where
136         D: Display + Send + Sync + 'static,
137         E: Diagnostic + Send + Sync + 'static,
138     {
139         let error: ContextError<D, E> = ContextError { msg, error };
140 
141         let vtable = &ErrorVTable {
142             object_drop: object_drop::<ContextError<D, E>>,
143             object_ref: object_ref::<ContextError<D, E>>,
144             object_ref_stderr: object_ref_stderr::<ContextError<D, E>>,
145             object_boxed: object_boxed::<ContextError<D, E>>,
146             object_boxed_stderr: object_boxed_stderr::<ContextError<D, E>>,
147             object_downcast: context_downcast::<D, E>,
148             object_drop_rest: context_drop_rest::<D, E>,
149         };
150 
151         // Safety: passing vtable that operates on the right type.
152         let handler = Some(super::capture_handler(&error));
153 
154         unsafe { Report::construct(error, vtable, handler) }
155     }
156 
157     #[cfg_attr(track_caller, track_caller)]
from_boxed(error: Box<dyn Diagnostic + Send + Sync>) -> Self158     pub(crate) fn from_boxed(error: Box<dyn Diagnostic + Send + Sync>) -> Self {
159         use super::wrapper::BoxedError;
160         let error = BoxedError(error);
161         let handler = Some(super::capture_handler(&error));
162 
163         let vtable = &ErrorVTable {
164             object_drop: object_drop::<BoxedError>,
165             object_ref: object_ref::<BoxedError>,
166             object_ref_stderr: object_ref_stderr::<BoxedError>,
167             object_boxed: object_boxed::<BoxedError>,
168             object_boxed_stderr: object_boxed_stderr::<BoxedError>,
169             object_downcast: object_downcast::<Box<dyn Diagnostic + Send + Sync>>,
170             object_drop_rest: object_drop_front::<Box<dyn Diagnostic + Send + Sync>>,
171         };
172 
173         // Safety: BoxedError is repr(transparent) so it is okay for the vtable
174         // to allow casting to Box<dyn StdError + Send + Sync>.
175         unsafe { Report::construct(error, vtable, handler) }
176     }
177 
178     // Takes backtrace as argument rather than capturing it here so that the
179     // user sees one fewer layer of wrapping noise in the backtrace.
180     //
181     // Unsafe because the given vtable must have sensible behavior on the error
182     // value of type E.
construct<E>( error: E, vtable: &'static ErrorVTable, handler: Option<Box<dyn ReportHandler>>, ) -> Self where E: Diagnostic + Send + Sync + 'static,183     unsafe fn construct<E>(
184         error: E,
185         vtable: &'static ErrorVTable,
186         handler: Option<Box<dyn ReportHandler>>,
187     ) -> Self
188     where
189         E: Diagnostic + Send + Sync + 'static,
190     {
191         let inner = Box::new(ErrorImpl {
192             vtable,
193             handler,
194             _object: error,
195         });
196         // Erase the concrete type of E from the compile-time type system. This
197         // is equivalent to the safe unsize coercion from Box<ErrorImpl<E>> to
198         // Box<ErrorImpl<dyn StdError + Send + Sync + 'static>> except that the
199         // result is a thin pointer. The necessary behavior for manipulating the
200         // underlying ErrorImpl<E> is preserved in the vtable provided by the
201         // caller rather than a builtin fat pointer vtable.
202         let inner = Own::new(inner).cast::<ErasedErrorImpl>();
203         Report { inner }
204     }
205 
206     /// Create a new error from an error message to wrap the existing error.
207     ///
208     /// For attaching a higher level error message to a `Result` as it is
209     /// propagated, the [crate::WrapErr] extension trait may be more
210     /// convenient than this function.
211     ///
212     /// The primary reason to use `error.wrap_err(...)` instead of
213     /// `result.wrap_err(...)` via the `WrapErr` trait would be if the
214     /// message needs to depend on some data held by the underlying error:
wrap_err<D>(self, msg: D) -> Self where D: Display + Send + Sync + 'static,215     pub fn wrap_err<D>(self, msg: D) -> Self
216     where
217         D: Display + Send + Sync + 'static,
218     {
219         let handler = unsafe { self.inner.by_mut().deref_mut().handler.take() };
220         let error: ContextError<D, Report> = ContextError { msg, error: self };
221 
222         let vtable = &ErrorVTable {
223             object_drop: object_drop::<ContextError<D, Report>>,
224             object_ref: object_ref::<ContextError<D, Report>>,
225             object_ref_stderr: object_ref_stderr::<ContextError<D, Report>>,
226             object_boxed: object_boxed::<ContextError<D, Report>>,
227             object_boxed_stderr: object_boxed_stderr::<ContextError<D, Report>>,
228             object_downcast: context_chain_downcast::<D>,
229             object_drop_rest: context_chain_drop_rest::<D>,
230         };
231 
232         // Safety: passing vtable that operates on the right type.
233         unsafe { Report::construct(error, vtable, handler) }
234     }
235 
236     /// Compatibility re-export of wrap_err for interop with `anyhow`
context<D>(self, msg: D) -> Self where D: Display + Send + Sync + 'static,237     pub fn context<D>(self, msg: D) -> Self
238     where
239         D: Display + Send + Sync + 'static,
240     {
241         self.wrap_err(msg)
242     }
243 
244     /// An iterator of the chain of source errors contained by this Report.
245     ///
246     /// This iterator will visit every error in the cause chain of this error
247     /// object, beginning with the error that this error object was created
248     /// from.
249     ///
250     /// # Example
251     ///
252     /// ```
253     /// use miette::Report;
254     /// use std::io;
255     ///
256     /// pub fn underlying_io_error_kind(error: &Report) -> Option<io::ErrorKind> {
257     ///     for cause in error.chain() {
258     ///         if let Some(io_error) = cause.downcast_ref::<io::Error>() {
259     ///             return Some(io_error.kind());
260     ///         }
261     ///     }
262     ///     None
263     /// }
264     /// ```
chain(&self) -> Chain<'_>265     pub fn chain(&self) -> Chain<'_> {
266         unsafe { ErrorImpl::chain(self.inner.by_ref()) }
267     }
268 
269     /// The lowest level cause of this error &mdash; this error's cause's
270     /// cause's cause etc.
271     ///
272     /// The root cause is the last error in the iterator produced by
273     /// [`chain()`](Report::chain).
root_cause(&self) -> &(dyn StdError + 'static)274     pub fn root_cause(&self) -> &(dyn StdError + 'static) {
275         self.chain().last().unwrap()
276     }
277 
278     /// Returns true if `E` is the type held by this error object.
279     ///
280     /// For errors constructed from messages, this method returns true if `E`
281     /// matches the type of the message `D` **or** the type of the error on
282     /// which the message has been attached. For details about the
283     /// interaction between message and downcasting, [see here].
284     ///
285     /// [see here]: trait.WrapErr.html#effect-on-downcasting
is<E>(&self) -> bool where E: Display + Debug + Send + Sync + 'static,286     pub fn is<E>(&self) -> bool
287     where
288         E: Display + Debug + Send + Sync + 'static,
289     {
290         self.downcast_ref::<E>().is_some()
291     }
292 
293     /// Attempt to downcast the error object to a concrete type.
downcast<E>(self) -> Result<E, Self> where E: Display + Debug + Send + Sync + 'static,294     pub fn downcast<E>(self) -> Result<E, Self>
295     where
296         E: Display + Debug + Send + Sync + 'static,
297     {
298         let target = TypeId::of::<E>();
299         let inner = self.inner.by_mut();
300         unsafe {
301             // Use vtable to find NonNull<()> which points to a value of type E
302             // somewhere inside the data structure.
303             let addr = match (vtable(inner.ptr).object_downcast)(inner.by_ref(), target) {
304                 Some(addr) => addr.by_mut().extend(),
305                 None => return Err(self),
306             };
307 
308             // Prepare to read E out of the data structure. We'll drop the rest
309             // of the data structure separately so that E is not dropped.
310             let outer = ManuallyDrop::new(self);
311 
312             // Read E from where the vtable found it.
313             let error = addr.cast::<E>().read();
314 
315             // Drop rest of the data structure outside of E.
316             (vtable(outer.inner.ptr).object_drop_rest)(outer.inner, target);
317 
318             Ok(error)
319         }
320     }
321 
322     /// Downcast this error object by reference.
323     ///
324     /// # Example
325     ///
326     /// ```
327     /// # use miette::{Report, miette};
328     /// # use std::fmt::{self, Display};
329     /// # use std::task::Poll;
330     /// #
331     /// # #[derive(Debug)]
332     /// # enum DataStoreError {
333     /// #     Censored(()),
334     /// # }
335     /// #
336     /// # impl Display for DataStoreError {
337     /// #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
338     /// #         unimplemented!()
339     /// #     }
340     /// # }
341     /// #
342     /// # impl std::error::Error for DataStoreError {}
343     /// #
344     /// # const REDACTED_CONTENT: () = ();
345     /// #
346     /// # let error: Report = miette!("...");
347     /// # let root_cause = &error;
348     /// #
349     /// # let ret =
350     /// // If the error was caused by redaction, then return a tombstone instead
351     /// // of the content.
352     /// match root_cause.downcast_ref::<DataStoreError>() {
353     ///     Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
354     ///     None => Err(error),
355     /// }
356     /// # ;
357     /// ```
downcast_ref<E>(&self) -> Option<&E> where E: Display + Debug + Send + Sync + 'static,358     pub fn downcast_ref<E>(&self) -> Option<&E>
359     where
360         E: Display + Debug + Send + Sync + 'static,
361     {
362         let target = TypeId::of::<E>();
363         unsafe {
364             // Use vtable to find NonNull<()> which points to a value of type E
365             // somewhere inside the data structure.
366             let addr = (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?;
367             Some(addr.cast::<E>().deref())
368         }
369     }
370 
371     /// Downcast this error object by mutable reference.
downcast_mut<E>(&mut self) -> Option<&mut E> where E: Display + Debug + Send + Sync + 'static,372     pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
373     where
374         E: Display + Debug + Send + Sync + 'static,
375     {
376         let target = TypeId::of::<E>();
377         unsafe {
378             // Use vtable to find NonNull<()> which points to a value of type E
379             // somewhere inside the data structure.
380             let addr =
381                 (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?.by_mut();
382             Some(addr.cast::<E>().deref_mut())
383         }
384     }
385 
386     /// Get a reference to the Handler for this Report.
handler(&self) -> &dyn ReportHandler387     pub fn handler(&self) -> &dyn ReportHandler {
388         unsafe {
389             self.inner
390                 .by_ref()
391                 .deref()
392                 .handler
393                 .as_ref()
394                 .unwrap()
395                 .as_ref()
396         }
397     }
398 
399     /// Get a mutable reference to the Handler for this Report.
handler_mut(&mut self) -> &mut dyn ReportHandler400     pub fn handler_mut(&mut self) -> &mut dyn ReportHandler {
401         unsafe {
402             self.inner
403                 .by_mut()
404                 .deref_mut()
405                 .handler
406                 .as_mut()
407                 .unwrap()
408                 .as_mut()
409         }
410     }
411 
412     /// Provide source code for this error
with_source_code(self, source_code: impl SourceCode + Send + Sync + 'static) -> Report413     pub fn with_source_code(self, source_code: impl SourceCode + Send + Sync + 'static) -> Report {
414         WithSourceCode {
415             source_code,
416             error: self,
417         }
418         .into()
419     }
420 }
421 
422 impl<E> From<E> for Report
423 where
424     E: Diagnostic + Send + Sync + 'static,
425 {
426     #[cfg_attr(track_caller, track_caller)]
from(error: E) -> Self427     fn from(error: E) -> Self {
428         Report::from_std(error)
429     }
430 }
431 
432 impl Deref for Report {
433     type Target = dyn Diagnostic + Send + Sync + 'static;
434 
deref(&self) -> &Self::Target435     fn deref(&self) -> &Self::Target {
436         unsafe { ErrorImpl::diagnostic(self.inner.by_ref()) }
437     }
438 }
439 
440 impl DerefMut for Report {
deref_mut(&mut self) -> &mut Self::Target441     fn deref_mut(&mut self) -> &mut Self::Target {
442         unsafe { ErrorImpl::diagnostic_mut(self.inner.by_mut()) }
443     }
444 }
445 
446 impl Display for Report {
fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result447     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
448         unsafe { ErrorImpl::display(self.inner.by_ref(), formatter) }
449     }
450 }
451 
452 impl Debug for Report {
fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result453     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
454         unsafe { ErrorImpl::debug(self.inner.by_ref(), formatter) }
455     }
456 }
457 
458 impl Drop for Report {
drop(&mut self)459     fn drop(&mut self) {
460         unsafe {
461             // Invoke the vtable's drop behavior.
462             (vtable(self.inner.ptr).object_drop)(self.inner);
463         }
464     }
465 }
466 
467 struct ErrorVTable {
468     object_drop: unsafe fn(Own<ErasedErrorImpl>),
469     object_ref:
470         unsafe fn(Ref<'_, ErasedErrorImpl>) -> Ref<'_, dyn Diagnostic + Send + Sync + 'static>,
471     object_ref_stderr:
472         unsafe fn(Ref<'_, ErasedErrorImpl>) -> Ref<'_, dyn StdError + Send + Sync + 'static>,
473     #[allow(clippy::type_complexity)]
474     object_boxed: unsafe fn(Own<ErasedErrorImpl>) -> Box<dyn Diagnostic + Send + Sync + 'static>,
475     #[allow(clippy::type_complexity)]
476     object_boxed_stderr:
477         unsafe fn(Own<ErasedErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static>,
478     object_downcast: unsafe fn(Ref<'_, ErasedErrorImpl>, TypeId) -> Option<Ref<'_, ()>>,
479     object_drop_rest: unsafe fn(Own<ErasedErrorImpl>, TypeId),
480 }
481 
482 // Safety: requires layout of *e to match ErrorImpl<E>.
object_drop<E>(e: Own<ErasedErrorImpl>)483 unsafe fn object_drop<E>(e: Own<ErasedErrorImpl>) {
484     // Cast back to ErrorImpl<E> so that the allocator receives the correct
485     // Layout to deallocate the Box's memory.
486     let unerased = e.cast::<ErrorImpl<E>>().boxed();
487     drop(unerased);
488 }
489 
490 // Safety: requires layout of *e to match ErrorImpl<E>.
object_drop_front<E>(e: Own<ErasedErrorImpl>, target: TypeId)491 unsafe fn object_drop_front<E>(e: Own<ErasedErrorImpl>, target: TypeId) {
492     // Drop the fields of ErrorImpl other than E as well as the Box allocation,
493     // without dropping E itself. This is used by downcast after doing a
494     // ptr::read to take ownership of the E.
495     let _ = target;
496     let unerased = e.cast::<ErrorImpl<ManuallyDrop<E>>>().boxed();
497     drop(unerased);
498 }
499 
500 // Safety: requires layout of *e to match ErrorImpl<E>.
object_ref<E>( e: Ref<'_, ErasedErrorImpl>, ) -> Ref<'_, dyn Diagnostic + Send + Sync + 'static> where E: Diagnostic + Send + Sync + 'static,501 unsafe fn object_ref<E>(
502     e: Ref<'_, ErasedErrorImpl>,
503 ) -> Ref<'_, dyn Diagnostic + Send + Sync + 'static>
504 where
505     E: Diagnostic + Send + Sync + 'static,
506 {
507     // Attach E's native StdError vtable onto a pointer to self._object.
508     let unerased = e.cast::<ErrorImpl<E>>();
509 
510     Ref::from_raw(NonNull::new_unchecked(
511         ptr::addr_of!((*unerased.as_ptr())._object) as *mut E,
512     ))
513 }
514 
515 // Safety: requires layout of *e to match ErrorImpl<E>.
object_ref_stderr<E>( e: Ref<'_, ErasedErrorImpl>, ) -> Ref<'_, dyn StdError + Send + Sync + 'static> where E: StdError + Send + Sync + 'static,516 unsafe fn object_ref_stderr<E>(
517     e: Ref<'_, ErasedErrorImpl>,
518 ) -> Ref<'_, dyn StdError + Send + Sync + 'static>
519 where
520     E: StdError + Send + Sync + 'static,
521 {
522     // Attach E's native StdError vtable onto a pointer to self._object.
523     let unerased = e.cast::<ErrorImpl<E>>();
524 
525     Ref::from_raw(NonNull::new_unchecked(
526         ptr::addr_of!((*unerased.as_ptr())._object) as *mut E,
527     ))
528 }
529 
530 // Safety: requires layout of *e to match ErrorImpl<E>.
object_boxed<E>(e: Own<ErasedErrorImpl>) -> Box<dyn Diagnostic + Send + Sync + 'static> where E: Diagnostic + Send + Sync + 'static,531 unsafe fn object_boxed<E>(e: Own<ErasedErrorImpl>) -> Box<dyn Diagnostic + Send + Sync + 'static>
532 where
533     E: Diagnostic + Send + Sync + 'static,
534 {
535     // Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below.
536     e.cast::<ErrorImpl<E>>().boxed()
537 }
538 
539 // Safety: requires layout of *e to match ErrorImpl<E>.
object_boxed_stderr<E>( e: Own<ErasedErrorImpl>, ) -> Box<dyn StdError + Send + Sync + 'static> where E: StdError + Send + Sync + 'static,540 unsafe fn object_boxed_stderr<E>(
541     e: Own<ErasedErrorImpl>,
542 ) -> Box<dyn StdError + Send + Sync + 'static>
543 where
544     E: StdError + Send + Sync + 'static,
545 {
546     // Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below.
547     e.cast::<ErrorImpl<E>>().boxed()
548 }
549 
550 // Safety: requires layout of *e to match ErrorImpl<E>.
object_downcast<E>(e: Ref<'_, ErasedErrorImpl>, target: TypeId) -> Option<Ref<'_, ()>> where E: 'static,551 unsafe fn object_downcast<E>(e: Ref<'_, ErasedErrorImpl>, target: TypeId) -> Option<Ref<'_, ()>>
552 where
553     E: 'static,
554 {
555     if TypeId::of::<E>() == target {
556         // Caller is looking for an E pointer and e is ErrorImpl<E>, take a
557         // pointer to its E field.
558         let unerased = e.cast::<ErrorImpl<E>>();
559 
560         Some(
561             Ref::from_raw(NonNull::new_unchecked(
562                 ptr::addr_of!((*unerased.as_ptr())._object) as *mut E,
563             ))
564             .cast::<()>(),
565         )
566     } else {
567         None
568     }
569 }
570 
571 // Safety: requires layout of *e to match ErrorImpl<ContextError<D, E>>.
context_downcast<D, E>(e: Ref<'_, ErasedErrorImpl>, target: TypeId) -> Option<Ref<'_, ()>> where D: 'static, E: 'static,572 unsafe fn context_downcast<D, E>(e: Ref<'_, ErasedErrorImpl>, target: TypeId) -> Option<Ref<'_, ()>>
573 where
574     D: 'static,
575     E: 'static,
576 {
577     if TypeId::of::<D>() == target {
578         let unerased = e.cast::<ErrorImpl<ContextError<D, E>>>().deref();
579         Some(Ref::new(&unerased._object.msg).cast::<()>())
580     } else if TypeId::of::<E>() == target {
581         let unerased = e.cast::<ErrorImpl<ContextError<D, E>>>().deref();
582         Some(Ref::new(&unerased._object.error).cast::<()>())
583     } else {
584         None
585     }
586 }
587 
588 // Safety: requires layout of *e to match ErrorImpl<ContextError<D, E>>.
context_drop_rest<D, E>(e: Own<ErasedErrorImpl>, target: TypeId) where D: 'static, E: 'static,589 unsafe fn context_drop_rest<D, E>(e: Own<ErasedErrorImpl>, target: TypeId)
590 where
591     D: 'static,
592     E: 'static,
593 {
594     // Called after downcasting by value to either the D or the E and doing a
595     // ptr::read to take ownership of that value.
596     if TypeId::of::<D>() == target {
597         let unerased = e
598             .cast::<ErrorImpl<ContextError<ManuallyDrop<D>, E>>>()
599             .boxed();
600         drop(unerased);
601     } else {
602         let unerased = e
603             .cast::<ErrorImpl<ContextError<D, ManuallyDrop<E>>>>()
604             .boxed();
605         drop(unerased);
606     }
607 }
608 
609 // Safety: requires layout of *e to match ErrorImpl<ContextError<D, Report>>.
context_chain_downcast<D>( e: Ref<'_, ErasedErrorImpl>, target: TypeId, ) -> Option<Ref<'_, ()>> where D: 'static,610 unsafe fn context_chain_downcast<D>(
611     e: Ref<'_, ErasedErrorImpl>,
612     target: TypeId,
613 ) -> Option<Ref<'_, ()>>
614 where
615     D: 'static,
616 {
617     let unerased = e.cast::<ErrorImpl<ContextError<D, Report>>>().deref();
618     if TypeId::of::<D>() == target {
619         Some(Ref::new(&unerased._object.msg).cast::<()>())
620     } else {
621         // Recurse down the context chain per the inner error's vtable.
622         let source = &unerased._object.error;
623         (vtable(source.inner.ptr).object_downcast)(source.inner.by_ref(), target)
624     }
625 }
626 
627 // Safety: requires layout of *e to match ErrorImpl<ContextError<D, Report>>.
context_chain_drop_rest<D>(e: Own<ErasedErrorImpl>, target: TypeId) where D: 'static,628 unsafe fn context_chain_drop_rest<D>(e: Own<ErasedErrorImpl>, target: TypeId)
629 where
630     D: 'static,
631 {
632     // Called after downcasting by value to either the D or one of the causes
633     // and doing a ptr::read to take ownership of that value.
634     if TypeId::of::<D>() == target {
635         let unerased = e
636             .cast::<ErrorImpl<ContextError<ManuallyDrop<D>, Report>>>()
637             .boxed();
638         // Drop the entire rest of the data structure rooted in the next Report.
639         drop(unerased);
640     } else {
641         let unerased = e
642             .cast::<ErrorImpl<ContextError<D, ManuallyDrop<Report>>>>()
643             .boxed();
644         // Read out a ManuallyDrop<Box<ErasedErrorImpl>> from the next error.
645         let inner = unerased._object.error.inner;
646         drop(unerased);
647         let vtable = vtable(inner.ptr);
648         // Recursively drop the next error using the same target typeid.
649         (vtable.object_drop_rest)(inner, target);
650     }
651 }
652 
653 // repr C to ensure that E remains in the final position.
654 #[repr(C)]
655 pub(crate) struct ErrorImpl<E> {
656     vtable: &'static ErrorVTable,
657     pub(crate) handler: Option<Box<dyn ReportHandler>>,
658     // NOTE: Don't use directly. Use only through vtable. Erased type may have
659     // different alignment.
660     _object: E,
661 }
662 
663 // repr C to ensure that ContextError<D, E> has the same layout as
664 // ContextError<ManuallyDrop<D>, E> and ContextError<D, ManuallyDrop<E>>.
665 #[repr(C)]
666 pub(crate) struct ContextError<D, E> {
667     pub(crate) msg: D,
668     pub(crate) error: E,
669 }
670 
671 type ErasedErrorImpl = ErrorImpl<()>;
672 
673 // Safety: `ErrorVTable` must be the first field of `ErrorImpl`
vtable(p: NonNull<ErasedErrorImpl>) -> &'static ErrorVTable674 unsafe fn vtable(p: NonNull<ErasedErrorImpl>) -> &'static ErrorVTable {
675     (p.as_ptr() as *const &'static ErrorVTable).read()
676 }
677 
678 impl<E> ErrorImpl<E> {
erase(&self) -> Ref<'_, ErasedErrorImpl>679     fn erase(&self) -> Ref<'_, ErasedErrorImpl> {
680         // Erase the concrete type of E but preserve the vtable in self.vtable
681         // for manipulating the resulting thin pointer. This is analogous to an
682         // unsize coercion.
683         Ref::new(self).cast::<ErasedErrorImpl>()
684     }
685 }
686 
687 impl ErasedErrorImpl {
error<'a>( this: Ref<'a, Self>, ) -> &'a (dyn StdError + Send + Sync + 'static)688     pub(crate) unsafe fn error<'a>(
689         this: Ref<'a, Self>,
690     ) -> &'a (dyn StdError + Send + Sync + 'static) {
691         // Use vtable to attach E's native StdError vtable for the right
692         // original type E.
693         (vtable(this.ptr).object_ref_stderr)(this).deref()
694     }
695 
diagnostic<'a>( this: Ref<'a, Self>, ) -> &'a (dyn Diagnostic + Send + Sync + 'static)696     pub(crate) unsafe fn diagnostic<'a>(
697         this: Ref<'a, Self>,
698     ) -> &'a (dyn Diagnostic + Send + Sync + 'static) {
699         // Use vtable to attach E's native StdError vtable for the right
700         // original type E.
701         (vtable(this.ptr).object_ref)(this).deref()
702     }
703 
diagnostic_mut<'a>( this: Mut<'a, Self>, ) -> &'a mut (dyn Diagnostic + Send + Sync + 'static)704     pub(crate) unsafe fn diagnostic_mut<'a>(
705         this: Mut<'a, Self>,
706     ) -> &'a mut (dyn Diagnostic + Send + Sync + 'static) {
707         // Use vtable to attach E's native StdError vtable for the right
708         // original type E.
709         (vtable(this.ptr).object_ref)(this.by_ref())
710             .by_mut()
711             .deref_mut()
712     }
713 
chain(this: Ref<'_, Self>) -> Chain<'_>714     pub(crate) unsafe fn chain(this: Ref<'_, Self>) -> Chain<'_> {
715         Chain::new(Self::error(this))
716     }
717 }
718 
719 impl<E> StdError for ErrorImpl<E>
720 where
721     E: StdError,
722 {
source(&self) -> Option<&(dyn std::error::Error + 'static)>723     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
724         unsafe { ErrorImpl::diagnostic(self.erase()).source() }
725     }
726 }
727 
728 impl<E> Diagnostic for ErrorImpl<E> where E: Diagnostic {}
729 
730 impl<E> Debug for ErrorImpl<E>
731 where
732     E: Debug,
733 {
fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result734     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
735         unsafe { ErrorImpl::debug(self.erase(), formatter) }
736     }
737 }
738 
739 impl<E> Display for ErrorImpl<E>
740 where
741     E: Display,
742 {
fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result743     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
744         unsafe { Display::fmt(ErrorImpl::diagnostic(self.erase()), formatter) }
745     }
746 }
747 
748 impl From<Report> for Box<dyn Diagnostic + Send + Sync + 'static> {
from(error: Report) -> Self749     fn from(error: Report) -> Self {
750         let outer = ManuallyDrop::new(error);
751         unsafe {
752             // Use vtable to attach ErrorImpl<E>'s native StdError vtable for
753             // the right original type E.
754             (vtable(outer.inner.ptr).object_boxed)(outer.inner)
755         }
756     }
757 }
758 
759 impl From<Report> for Box<dyn StdError + Send + Sync + 'static> {
from(error: Report) -> Self760     fn from(error: Report) -> Self {
761         let outer = ManuallyDrop::new(error);
762         unsafe {
763             // Use vtable to attach ErrorImpl<E>'s native StdError vtable for
764             // the right original type E.
765             (vtable(outer.inner.ptr).object_boxed_stderr)(outer.inner)
766         }
767     }
768 }
769 
770 impl From<Report> for Box<dyn Diagnostic + 'static> {
from(error: Report) -> Self771     fn from(error: Report) -> Self {
772         Box::<dyn Diagnostic + Send + Sync>::from(error)
773     }
774 }
775 
776 impl From<Report> for Box<dyn StdError + 'static> {
from(error: Report) -> Self777     fn from(error: Report) -> Self {
778         Box::<dyn StdError + Send + Sync>::from(error)
779     }
780 }
781 
782 impl AsRef<dyn Diagnostic + Send + Sync> for Report {
as_ref(&self) -> &(dyn Diagnostic + Send + Sync + 'static)783     fn as_ref(&self) -> &(dyn Diagnostic + Send + Sync + 'static) {
784         &**self
785     }
786 }
787 
788 impl AsRef<dyn Diagnostic> for Report {
as_ref(&self) -> &(dyn Diagnostic + 'static)789     fn as_ref(&self) -> &(dyn Diagnostic + 'static) {
790         &**self
791     }
792 }
793 
794 impl AsRef<dyn StdError + Send + Sync> for Report {
as_ref(&self) -> &(dyn StdError + Send + Sync + 'static)795     fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
796         unsafe { ErrorImpl::error(self.inner.by_ref()) }
797     }
798 }
799 
800 impl AsRef<dyn StdError> for Report {
as_ref(&self) -> &(dyn StdError + 'static)801     fn as_ref(&self) -> &(dyn StdError + 'static) {
802         unsafe { ErrorImpl::error(self.inner.by_ref()) }
803     }
804 }
805 
806 impl std::borrow::Borrow<dyn Diagnostic> for Report {
borrow(&self) -> &(dyn Diagnostic + 'static)807     fn borrow(&self) -> &(dyn Diagnostic + 'static) {
808         self.as_ref()
809     }
810 }
811