diff options
author | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
commit | 1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch) | |
tree | 7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/miette/src/eyreish | |
parent | 5ecd8cf2cba827454317368b68571df0d13d7842 (diff) | |
download | fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip |
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/miette/src/eyreish')
-rw-r--r-- | vendor/miette/src/eyreish/context.rs | 217 | ||||
-rw-r--r-- | vendor/miette/src/eyreish/error.rs | 810 | ||||
-rw-r--r-- | vendor/miette/src/eyreish/fmt.rs | 20 | ||||
-rw-r--r-- | vendor/miette/src/eyreish/into_diagnostic.rs | 33 | ||||
-rw-r--r-- | vendor/miette/src/eyreish/kind.rs | 111 | ||||
-rw-r--r-- | vendor/miette/src/eyreish/macros.rs | 300 | ||||
-rw-r--r-- | vendor/miette/src/eyreish/mod.rs | 485 | ||||
-rw-r--r-- | vendor/miette/src/eyreish/ptr.rs | 188 | ||||
-rw-r--r-- | vendor/miette/src/eyreish/wrapper.rs | 234 |
9 files changed, 2398 insertions, 0 deletions
diff --git a/vendor/miette/src/eyreish/context.rs b/vendor/miette/src/eyreish/context.rs new file mode 100644 index 0000000..3d9238b --- /dev/null +++ b/vendor/miette/src/eyreish/context.rs @@ -0,0 +1,217 @@ +use super::error::{ContextError, ErrorImpl}; +use super::{Report, WrapErr}; +use core::fmt::{self, Debug, Display, Write}; + +use std::error::Error as StdError; + +use crate::{Diagnostic, LabeledSpan}; + +mod ext { + use super::*; + + pub trait Diag { + #[cfg_attr(track_caller, track_caller)] + fn ext_report<D>(self, msg: D) -> Report + where + D: Display + Send + Sync + 'static; + } + + impl<E> Diag for E + where + E: Diagnostic + Send + Sync + 'static, + { + fn ext_report<D>(self, msg: D) -> Report + where + D: Display + Send + Sync + 'static, + { + Report::from_msg(msg, self) + } + } + + impl Diag for Report { + fn ext_report<D>(self, msg: D) -> Report + where + D: Display + Send + Sync + 'static, + { + self.wrap_err(msg) + } + } +} + +impl<T, E> WrapErr<T, E> for Result<T, E> +where + E: ext::Diag + Send + Sync + 'static, +{ + fn wrap_err<D>(self, msg: D) -> Result<T, Report> + where + D: Display + Send + Sync + 'static, + { + match self { + Ok(t) => Ok(t), + Err(e) => Err(e.ext_report(msg)), + } + } + + fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report> + where + D: Display + Send + Sync + 'static, + F: FnOnce() -> D, + { + match self { + Ok(t) => Ok(t), + Err(e) => Err(e.ext_report(msg())), + } + } + + fn context<D>(self, msg: D) -> Result<T, Report> + where + D: Display + Send + Sync + 'static, + { + self.wrap_err(msg) + } + + fn with_context<D, F>(self, msg: F) -> Result<T, Report> + where + D: Display + Send + Sync + 'static, + F: FnOnce() -> D, + { + self.wrap_err_with(msg) + } +} + +impl<D, E> Debug for ContextError<D, E> +where + D: Display, + E: Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Error") + .field("msg", &Quoted(&self.msg)) + .field("source", &self.error) + .finish() + } +} + +impl<D, E> Display for ContextError<D, E> +where + D: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.msg, f) + } +} + +impl<D, E> StdError for ContextError<D, E> +where + D: Display, + E: StdError + 'static, +{ + fn source(&self) -> Option<&(dyn StdError + 'static)> { + Some(&self.error) + } +} + +impl<D> StdError for ContextError<D, Report> +where + D: Display, +{ + fn source(&self) -> Option<&(dyn StdError + 'static)> { + unsafe { Some(ErrorImpl::error(self.error.inner.by_ref())) } + } +} + +impl<D, E> Diagnostic for ContextError<D, E> +where + D: Display, + E: Diagnostic + 'static, +{ + fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.error.code() + } + + fn severity(&self) -> Option<crate::Severity> { + self.error.severity() + } + + fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.error.help() + } + + fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.error.url() + } + + fn labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>> { + self.error.labels() + } + + fn source_code(&self) -> Option<&dyn crate::SourceCode> { + self.error.source_code() + } + + fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> { + self.error.related() + } +} + +impl<D> Diagnostic for ContextError<D, Report> +where + D: Display, +{ + fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).code() } + } + + fn severity(&self) -> Option<crate::Severity> { + unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).severity() } + } + + fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).help() } + } + + fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).url() } + } + + fn labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>> { + unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).labels() } + } + + fn source_code(&self) -> Option<&dyn crate::SourceCode> { + self.error.source_code() + } + + fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> { + self.error.related() + } +} + +struct Quoted<D>(D); + +impl<D> Debug for Quoted<D> +where + D: Display, +{ + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_char('"')?; + Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?; + formatter.write_char('"')?; + Ok(()) + } +} + +impl Write for Quoted<&mut fmt::Formatter<'_>> { + fn write_str(&mut self, s: &str) -> fmt::Result { + Display::fmt(&s.escape_debug(), self.0) + } +} + +pub(crate) mod private { + use super::*; + + pub trait Sealed {} + + impl<T, E> Sealed for Result<T, E> where E: ext::Diag {} + impl<T> Sealed for Option<T> {} +} diff --git a/vendor/miette/src/eyreish/error.rs b/vendor/miette/src/eyreish/error.rs new file mode 100644 index 0000000..6b0dc34 --- /dev/null +++ b/vendor/miette/src/eyreish/error.rs @@ -0,0 +1,810 @@ +use core::any::TypeId; +use core::fmt::{self, Debug, Display}; +use core::mem::ManuallyDrop; +use core::ptr::{self, NonNull}; +use std::error::Error as StdError; + +use super::ptr::{Mut, Own, Ref}; +use super::Report; +use super::ReportHandler; +use crate::chain::Chain; +use crate::eyreish::wrapper::WithSourceCode; +use crate::{Diagnostic, SourceCode}; +use core::ops::{Deref, DerefMut}; + +impl Report { + /// Create a new error object from any error type. + /// + /// The error type must be thread safe and `'static`, so that the `Report` + /// will be as well. + /// + /// If the error type does not provide a backtrace, a backtrace will be + /// created here to ensure that a backtrace exists. + #[cfg_attr(track_caller, track_caller)] + pub fn new<E>(error: E) -> Self + where + E: Diagnostic + Send + Sync + 'static, + { + Report::from_std(error) + } + + /// Create a new error object from a printable error message. + /// + /// If the argument implements std::error::Error, prefer `Report::new` + /// instead which preserves the underlying error's cause chain and + /// backtrace. If the argument may or may not implement std::error::Error + /// now or in the future, use `miette!(err)` which handles either way + /// correctly. + /// + /// `Report::msg("...")` is equivalent to `miette!("...")` but occasionally + /// convenient in places where a function is preferable over a macro, such + /// as iterator or stream combinators: + /// + /// ``` + /// # mod ffi { + /// # pub struct Input; + /// # pub struct Output; + /// # pub async fn do_some_work(_: Input) -> Result<Output, &'static str> { + /// # unimplemented!() + /// # } + /// # } + /// # + /// # use ffi::{Input, Output}; + /// # + /// use futures::stream::{Stream, StreamExt, TryStreamExt}; + /// use miette::{Report, Result}; + /// + /// async fn demo<S>(stream: S) -> Result<Vec<Output>> + /// where + /// S: Stream<Item = Input>, + /// { + /// stream + /// .then(ffi::do_some_work) // returns Result<Output, &str> + /// .map_err(Report::msg) + /// .try_collect() + /// .await + /// } + /// ``` + #[cfg_attr(track_caller, track_caller)] + pub fn msg<M>(message: M) -> Self + where + M: Display + Debug + Send + Sync + 'static, + { + Report::from_adhoc(message) + } + + /// Create a new error object from a boxed [`Diagnostic`]. + /// + /// The boxed type must be thread safe and 'static, so that the `Report` + /// will be as well. + /// + /// Boxed `Diagnostic`s don't implement `Diagnostic` themselves due to trait coherence issues. + /// This method allows you to create a `Report` from a boxed `Diagnostic`. + #[cfg_attr(track_caller, track_caller)] + pub fn new_boxed(error: Box<dyn Diagnostic + Send + Sync + 'static>) -> Self { + Report::from_boxed(error) + } + + #[cfg_attr(track_caller, track_caller)] + pub(crate) fn from_std<E>(error: E) -> Self + where + E: Diagnostic + Send + Sync + 'static, + { + let vtable = &ErrorVTable { + object_drop: object_drop::<E>, + object_ref: object_ref::<E>, + object_ref_stderr: object_ref_stderr::<E>, + object_boxed: object_boxed::<E>, + object_boxed_stderr: object_boxed_stderr::<E>, + object_downcast: object_downcast::<E>, + object_drop_rest: object_drop_front::<E>, + }; + + // Safety: passing vtable that operates on the right type E. + let handler = Some(super::capture_handler(&error)); + + unsafe { Report::construct(error, vtable, handler) } + } + + #[cfg_attr(track_caller, track_caller)] + pub(crate) fn from_adhoc<M>(message: M) -> Self + where + M: Display + Debug + Send + Sync + 'static, + { + use super::wrapper::MessageError; + let error: MessageError<M> = MessageError(message); + let vtable = &ErrorVTable { + object_drop: object_drop::<MessageError<M>>, + object_ref: object_ref::<MessageError<M>>, + object_ref_stderr: object_ref_stderr::<MessageError<M>>, + object_boxed: object_boxed::<MessageError<M>>, + object_boxed_stderr: object_boxed_stderr::<MessageError<M>>, + object_downcast: object_downcast::<M>, + object_drop_rest: object_drop_front::<M>, + }; + + // Safety: MessageError is repr(transparent) so it is okay for the + // vtable to allow casting the MessageError<M> to M. + let handler = Some(super::capture_handler(&error)); + + unsafe { Report::construct(error, vtable, handler) } + } + + #[cfg_attr(track_caller, track_caller)] + pub(crate) fn from_msg<D, E>(msg: D, error: E) -> Self + where + D: Display + Send + Sync + 'static, + E: Diagnostic + Send + Sync + 'static, + { + let error: ContextError<D, E> = ContextError { msg, error }; + + let vtable = &ErrorVTable { + object_drop: object_drop::<ContextError<D, E>>, + object_ref: object_ref::<ContextError<D, E>>, + object_ref_stderr: object_ref_stderr::<ContextError<D, E>>, + object_boxed: object_boxed::<ContextError<D, E>>, + object_boxed_stderr: object_boxed_stderr::<ContextError<D, E>>, + object_downcast: context_downcast::<D, E>, + object_drop_rest: context_drop_rest::<D, E>, + }; + + // Safety: passing vtable that operates on the right type. + let handler = Some(super::capture_handler(&error)); + + unsafe { Report::construct(error, vtable, handler) } + } + + #[cfg_attr(track_caller, track_caller)] + pub(crate) fn from_boxed(error: Box<dyn Diagnostic + Send + Sync>) -> Self { + use super::wrapper::BoxedError; + let error = BoxedError(error); + let handler = Some(super::capture_handler(&error)); + + let vtable = &ErrorVTable { + object_drop: object_drop::<BoxedError>, + object_ref: object_ref::<BoxedError>, + object_ref_stderr: object_ref_stderr::<BoxedError>, + object_boxed: object_boxed::<BoxedError>, + object_boxed_stderr: object_boxed_stderr::<BoxedError>, + object_downcast: object_downcast::<Box<dyn Diagnostic + Send + Sync>>, + object_drop_rest: object_drop_front::<Box<dyn Diagnostic + Send + Sync>>, + }; + + // Safety: BoxedError is repr(transparent) so it is okay for the vtable + // to allow casting to Box<dyn StdError + Send + Sync>. + unsafe { Report::construct(error, vtable, handler) } + } + + // Takes backtrace as argument rather than capturing it here so that the + // user sees one fewer layer of wrapping noise in the backtrace. + // + // Unsafe because the given vtable must have sensible behavior on the error + // value of type E. + unsafe fn construct<E>( + error: E, + vtable: &'static ErrorVTable, + handler: Option<Box<dyn ReportHandler>>, + ) -> Self + where + E: Diagnostic + Send + Sync + 'static, + { + let inner = Box::new(ErrorImpl { + vtable, + handler, + _object: error, + }); + // Erase the concrete type of E from the compile-time type system. This + // is equivalent to the safe unsize coercion from Box<ErrorImpl<E>> to + // Box<ErrorImpl<dyn StdError + Send + Sync + 'static>> except that the + // result is a thin pointer. The necessary behavior for manipulating the + // underlying ErrorImpl<E> is preserved in the vtable provided by the + // caller rather than a builtin fat pointer vtable. + let inner = Own::new(inner).cast::<ErasedErrorImpl>(); + Report { inner } + } + + /// Create a new error from an error message to wrap the existing error. + /// + /// For attaching a higher level error message to a `Result` as it is + /// propagated, the [crate::WrapErr] extension trait may be more + /// convenient than this function. + /// + /// The primary reason to use `error.wrap_err(...)` instead of + /// `result.wrap_err(...)` via the `WrapErr` trait would be if the + /// message needs to depend on some data held by the underlying error: + pub fn wrap_err<D>(self, msg: D) -> Self + where + D: Display + Send + Sync + 'static, + { + let handler = unsafe { self.inner.by_mut().deref_mut().handler.take() }; + let error: ContextError<D, Report> = ContextError { msg, error: self }; + + let vtable = &ErrorVTable { + object_drop: object_drop::<ContextError<D, Report>>, + object_ref: object_ref::<ContextError<D, Report>>, + object_ref_stderr: object_ref_stderr::<ContextError<D, Report>>, + object_boxed: object_boxed::<ContextError<D, Report>>, + object_boxed_stderr: object_boxed_stderr::<ContextError<D, Report>>, + object_downcast: context_chain_downcast::<D>, + object_drop_rest: context_chain_drop_rest::<D>, + }; + + // Safety: passing vtable that operates on the right type. + unsafe { Report::construct(error, vtable, handler) } + } + + /// Compatibility re-export of wrap_err for interop with `anyhow` + pub fn context<D>(self, msg: D) -> Self + where + D: Display + Send + Sync + 'static, + { + self.wrap_err(msg) + } + + /// An iterator of the chain of source errors contained by this Report. + /// + /// This iterator will visit every error in the cause chain of this error + /// object, beginning with the error that this error object was created + /// from. + /// + /// # Example + /// + /// ``` + /// use miette::Report; + /// use std::io; + /// + /// pub fn underlying_io_error_kind(error: &Report) -> Option<io::ErrorKind> { + /// for cause in error.chain() { + /// if let Some(io_error) = cause.downcast_ref::<io::Error>() { + /// return Some(io_error.kind()); + /// } + /// } + /// None + /// } + /// ``` + pub fn chain(&self) -> Chain<'_> { + unsafe { ErrorImpl::chain(self.inner.by_ref()) } + } + + /// The lowest level cause of this error — this error's cause's + /// cause's cause etc. + /// + /// The root cause is the last error in the iterator produced by + /// [`chain()`](Report::chain). + pub fn root_cause(&self) -> &(dyn StdError + 'static) { + self.chain().last().unwrap() + } + + /// Returns true if `E` is the type held by this error object. + /// + /// For errors constructed from messages, this method returns true if `E` + /// matches the type of the message `D` **or** the type of the error on + /// which the message has been attached. For details about the + /// interaction between message and downcasting, [see here]. + /// + /// [see here]: trait.WrapErr.html#effect-on-downcasting + pub fn is<E>(&self) -> bool + where + E: Display + Debug + Send + Sync + 'static, + { + self.downcast_ref::<E>().is_some() + } + + /// Attempt to downcast the error object to a concrete type. + pub fn downcast<E>(self) -> Result<E, Self> + where + E: Display + Debug + Send + Sync + 'static, + { + let target = TypeId::of::<E>(); + let inner = self.inner.by_mut(); + unsafe { + // Use vtable to find NonNull<()> which points to a value of type E + // somewhere inside the data structure. + let addr = match (vtable(inner.ptr).object_downcast)(inner.by_ref(), target) { + Some(addr) => addr.by_mut().extend(), + None => return Err(self), + }; + + // Prepare to read E out of the data structure. We'll drop the rest + // of the data structure separately so that E is not dropped. + let outer = ManuallyDrop::new(self); + + // Read E from where the vtable found it. + let error = addr.cast::<E>().read(); + + // Drop rest of the data structure outside of E. + (vtable(outer.inner.ptr).object_drop_rest)(outer.inner, target); + + Ok(error) + } + } + + /// Downcast this error object by reference. + /// + /// # Example + /// + /// ``` + /// # use miette::{Report, miette}; + /// # use std::fmt::{self, Display}; + /// # use std::task::Poll; + /// # + /// # #[derive(Debug)] + /// # enum DataStoreError { + /// # Censored(()), + /// # } + /// # + /// # impl Display for DataStoreError { + /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// # unimplemented!() + /// # } + /// # } + /// # + /// # impl std::error::Error for DataStoreError {} + /// # + /// # const REDACTED_CONTENT: () = (); + /// # + /// # let error: Report = miette!("..."); + /// # let root_cause = &error; + /// # + /// # let ret = + /// // If the error was caused by redaction, then return a tombstone instead + /// // of the content. + /// match root_cause.downcast_ref::<DataStoreError>() { + /// Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), + /// None => Err(error), + /// } + /// # ; + /// ``` + pub fn downcast_ref<E>(&self) -> Option<&E> + where + E: Display + Debug + Send + Sync + 'static, + { + let target = TypeId::of::<E>(); + unsafe { + // Use vtable to find NonNull<()> which points to a value of type E + // somewhere inside the data structure. + let addr = (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?; + Some(addr.cast::<E>().deref()) + } + } + + /// Downcast this error object by mutable reference. + pub fn downcast_mut<E>(&mut self) -> Option<&mut E> + where + E: Display + Debug + Send + Sync + 'static, + { + let target = TypeId::of::<E>(); + unsafe { + // Use vtable to find NonNull<()> which points to a value of type E + // somewhere inside the data structure. + let addr = + (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?.by_mut(); + Some(addr.cast::<E>().deref_mut()) + } + } + + /// Get a reference to the Handler for this Report. + pub fn handler(&self) -> &dyn ReportHandler { + unsafe { + self.inner + .by_ref() + .deref() + .handler + .as_ref() + .unwrap() + .as_ref() + } + } + + /// Get a mutable reference to the Handler for this Report. + pub fn handler_mut(&mut self) -> &mut dyn ReportHandler { + unsafe { + self.inner + .by_mut() + .deref_mut() + .handler + .as_mut() + .unwrap() + .as_mut() + } + } + + /// Provide source code for this error + pub fn with_source_code(self, source_code: impl SourceCode + Send + Sync + 'static) -> Report { + WithSourceCode { + source_code, + error: self, + } + .into() + } +} + +impl<E> From<E> for Report +where + E: Diagnostic + Send + Sync + 'static, +{ + #[cfg_attr(track_caller, track_caller)] + fn from(error: E) -> Self { + Report::from_std(error) + } +} + +impl Deref for Report { + type Target = dyn Diagnostic + Send + Sync + 'static; + + fn deref(&self) -> &Self::Target { + unsafe { ErrorImpl::diagnostic(self.inner.by_ref()) } + } +} + +impl DerefMut for Report { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { ErrorImpl::diagnostic_mut(self.inner.by_mut()) } + } +} + +impl Display for Report { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { ErrorImpl::display(self.inner.by_ref(), formatter) } + } +} + +impl Debug for Report { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { ErrorImpl::debug(self.inner.by_ref(), formatter) } + } +} + +impl Drop for Report { + fn drop(&mut self) { + unsafe { + // Invoke the vtable's drop behavior. + (vtable(self.inner.ptr).object_drop)(self.inner); + } + } +} + +struct ErrorVTable { + object_drop: unsafe fn(Own<ErasedErrorImpl>), + object_ref: + unsafe fn(Ref<'_, ErasedErrorImpl>) -> Ref<'_, dyn Diagnostic + Send + Sync + 'static>, + object_ref_stderr: + unsafe fn(Ref<'_, ErasedErrorImpl>) -> Ref<'_, dyn StdError + Send + Sync + 'static>, + #[allow(clippy::type_complexity)] + object_boxed: unsafe fn(Own<ErasedErrorImpl>) -> Box<dyn Diagnostic + Send + Sync + 'static>, + #[allow(clippy::type_complexity)] + object_boxed_stderr: + unsafe fn(Own<ErasedErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static>, + object_downcast: unsafe fn(Ref<'_, ErasedErrorImpl>, TypeId) -> Option<Ref<'_, ()>>, + object_drop_rest: unsafe fn(Own<ErasedErrorImpl>, TypeId), +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_drop<E>(e: Own<ErasedErrorImpl>) { + // Cast back to ErrorImpl<E> so that the allocator receives the correct + // Layout to deallocate the Box's memory. + let unerased = e.cast::<ErrorImpl<E>>().boxed(); + drop(unerased); +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_drop_front<E>(e: Own<ErasedErrorImpl>, target: TypeId) { + // Drop the fields of ErrorImpl other than E as well as the Box allocation, + // without dropping E itself. This is used by downcast after doing a + // ptr::read to take ownership of the E. + let _ = target; + let unerased = e.cast::<ErrorImpl<ManuallyDrop<E>>>().boxed(); + drop(unerased); +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_ref<E>( + e: Ref<'_, ErasedErrorImpl>, +) -> Ref<'_, dyn Diagnostic + Send + Sync + 'static> +where + E: Diagnostic + Send + Sync + 'static, +{ + // Attach E's native StdError vtable onto a pointer to self._object. + let unerased = e.cast::<ErrorImpl<E>>(); + + Ref::from_raw(NonNull::new_unchecked( + ptr::addr_of!((*unerased.as_ptr())._object) as *mut E, + )) +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_ref_stderr<E>( + e: Ref<'_, ErasedErrorImpl>, +) -> Ref<'_, dyn StdError + Send + Sync + 'static> +where + E: StdError + Send + Sync + 'static, +{ + // Attach E's native StdError vtable onto a pointer to self._object. + let unerased = e.cast::<ErrorImpl<E>>(); + + Ref::from_raw(NonNull::new_unchecked( + ptr::addr_of!((*unerased.as_ptr())._object) as *mut E, + )) +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_boxed<E>(e: Own<ErasedErrorImpl>) -> Box<dyn Diagnostic + Send + Sync + 'static> +where + E: Diagnostic + Send + Sync + 'static, +{ + // Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below. + e.cast::<ErrorImpl<E>>().boxed() +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_boxed_stderr<E>( + e: Own<ErasedErrorImpl>, +) -> Box<dyn StdError + Send + Sync + 'static> +where + E: StdError + Send + Sync + 'static, +{ + // Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below. + e.cast::<ErrorImpl<E>>().boxed() +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_downcast<E>(e: Ref<'_, ErasedErrorImpl>, target: TypeId) -> Option<Ref<'_, ()>> +where + E: 'static, +{ + if TypeId::of::<E>() == target { + // Caller is looking for an E pointer and e is ErrorImpl<E>, take a + // pointer to its E field. + let unerased = e.cast::<ErrorImpl<E>>(); + + Some( + Ref::from_raw(NonNull::new_unchecked( + ptr::addr_of!((*unerased.as_ptr())._object) as *mut E, + )) + .cast::<()>(), + ) + } else { + None + } +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<D, E>>. +unsafe fn context_downcast<D, E>(e: Ref<'_, ErasedErrorImpl>, target: TypeId) -> Option<Ref<'_, ()>> +where + D: 'static, + E: 'static, +{ + if TypeId::of::<D>() == target { + let unerased = e.cast::<ErrorImpl<ContextError<D, E>>>().deref(); + Some(Ref::new(&unerased._object.msg).cast::<()>()) + } else if TypeId::of::<E>() == target { + let unerased = e.cast::<ErrorImpl<ContextError<D, E>>>().deref(); + Some(Ref::new(&unerased._object.error).cast::<()>()) + } else { + None + } +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<D, E>>. +unsafe fn context_drop_rest<D, E>(e: Own<ErasedErrorImpl>, target: TypeId) +where + D: 'static, + E: 'static, +{ + // Called after downcasting by value to either the D or the E and doing a + // ptr::read to take ownership of that value. + if TypeId::of::<D>() == target { + let unerased = e + .cast::<ErrorImpl<ContextError<ManuallyDrop<D>, E>>>() + .boxed(); + drop(unerased); + } else { + let unerased = e + .cast::<ErrorImpl<ContextError<D, ManuallyDrop<E>>>>() + .boxed(); + drop(unerased); + } +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<D, Report>>. +unsafe fn context_chain_downcast<D>( + e: Ref<'_, ErasedErrorImpl>, + target: TypeId, +) -> Option<Ref<'_, ()>> +where + D: 'static, +{ + let unerased = e.cast::<ErrorImpl<ContextError<D, Report>>>().deref(); + if TypeId::of::<D>() == target { + Some(Ref::new(&unerased._object.msg).cast::<()>()) + } else { + // Recurse down the context chain per the inner error's vtable. + let source = &unerased._object.error; + (vtable(source.inner.ptr).object_downcast)(source.inner.by_ref(), target) + } +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<D, Report>>. +unsafe fn context_chain_drop_rest<D>(e: Own<ErasedErrorImpl>, target: TypeId) +where + D: 'static, +{ + // Called after downcasting by value to either the D or one of the causes + // and doing a ptr::read to take ownership of that value. + if TypeId::of::<D>() == target { + let unerased = e + .cast::<ErrorImpl<ContextError<ManuallyDrop<D>, Report>>>() + .boxed(); + // Drop the entire rest of the data structure rooted in the next Report. + drop(unerased); + } else { + let unerased = e + .cast::<ErrorImpl<ContextError<D, ManuallyDrop<Report>>>>() + .boxed(); + // Read out a ManuallyDrop<Box<ErasedErrorImpl>> from the next error. + let inner = unerased._object.error.inner; + drop(unerased); + let vtable = vtable(inner.ptr); + // Recursively drop the next error using the same target typeid. + (vtable.object_drop_rest)(inner, target); + } +} + +// repr C to ensure that E remains in the final position. +#[repr(C)] +pub(crate) struct ErrorImpl<E> { + vtable: &'static ErrorVTable, + pub(crate) handler: Option<Box<dyn ReportHandler>>, + // NOTE: Don't use directly. Use only through vtable. Erased type may have + // different alignment. + _object: E, +} + +// repr C to ensure that ContextError<D, E> has the same layout as +// ContextError<ManuallyDrop<D>, E> and ContextError<D, ManuallyDrop<E>>. +#[repr(C)] +pub(crate) struct ContextError<D, E> { + pub(crate) msg: D, + pub(crate) error: E, +} + +type ErasedErrorImpl = ErrorImpl<()>; + +// Safety: `ErrorVTable` must be the first field of `ErrorImpl` +unsafe fn vtable(p: NonNull<ErasedErrorImpl>) -> &'static ErrorVTable { + (p.as_ptr() as *const &'static ErrorVTable).read() +} + +impl<E> ErrorImpl<E> { + fn erase(&self) -> Ref<'_, ErasedErrorImpl> { + // Erase the concrete type of E but preserve the vtable in self.vtable + // for manipulating the resulting thin pointer. This is analogous to an + // unsize coercion. + Ref::new(self).cast::<ErasedErrorImpl>() + } +} + +impl ErasedErrorImpl { + pub(crate) unsafe fn error<'a>( + this: Ref<'a, Self>, + ) -> &'a (dyn StdError + Send + Sync + 'static) { + // Use vtable to attach E's native StdError vtable for the right + // original type E. + (vtable(this.ptr).object_ref_stderr)(this).deref() + } + + pub(crate) unsafe fn diagnostic<'a>( + this: Ref<'a, Self>, + ) -> &'a (dyn Diagnostic + Send + Sync + 'static) { + // Use vtable to attach E's native StdError vtable for the right + // original type E. + (vtable(this.ptr).object_ref)(this).deref() + } + + pub(crate) unsafe fn diagnostic_mut<'a>( + this: Mut<'a, Self>, + ) -> &'a mut (dyn Diagnostic + Send + Sync + 'static) { + // Use vtable to attach E's native StdError vtable for the right + // original type E. + (vtable(this.ptr).object_ref)(this.by_ref()) + .by_mut() + .deref_mut() + } + + pub(crate) unsafe fn chain(this: Ref<'_, Self>) -> Chain<'_> { + Chain::new(Self::error(this)) + } +} + +impl<E> StdError for ErrorImpl<E> +where + E: StdError, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + unsafe { ErrorImpl::diagnostic(self.erase()).source() } + } +} + +impl<E> Diagnostic for ErrorImpl<E> where E: Diagnostic {} + +impl<E> Debug for ErrorImpl<E> +where + E: Debug, +{ + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { ErrorImpl::debug(self.erase(), formatter) } + } +} + +impl<E> Display for ErrorImpl<E> +where + E: Display, +{ + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { Display::fmt(ErrorImpl::diagnostic(self.erase()), formatter) } + } +} + +impl From<Report> for Box<dyn Diagnostic + Send + Sync + 'static> { + fn from(error: Report) -> Self { + let outer = ManuallyDrop::new(error); + unsafe { + // Use vtable to attach ErrorImpl<E>'s native StdError vtable for + // the right original type E. + (vtable(outer.inner.ptr).object_boxed)(outer.inner) + } + } +} + +impl From<Report> for Box<dyn StdError + Send + Sync + 'static> { + fn from(error: Report) -> Self { + let outer = ManuallyDrop::new(error); + unsafe { + // Use vtable to attach ErrorImpl<E>'s native StdError vtable for + // the right original type E. + (vtable(outer.inner.ptr).object_boxed_stderr)(outer.inner) + } + } +} + +impl From<Report> for Box<dyn Diagnostic + 'static> { + fn from(error: Report) -> Self { + Box::<dyn Diagnostic + Send + Sync>::from(error) + } +} + +impl From<Report> for Box<dyn StdError + 'static> { + fn from(error: Report) -> Self { + Box::<dyn StdError + Send + Sync>::from(error) + } +} + +impl AsRef<dyn Diagnostic + Send + Sync> for Report { + fn as_ref(&self) -> &(dyn Diagnostic + Send + Sync + 'static) { + &**self + } +} + +impl AsRef<dyn Diagnostic> for Report { + fn as_ref(&self) -> &(dyn Diagnostic + 'static) { + &**self + } +} + +impl AsRef<dyn StdError + Send + Sync> for Report { + fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) { + unsafe { ErrorImpl::error(self.inner.by_ref()) } + } +} + +impl AsRef<dyn StdError> for Report { + fn as_ref(&self) -> &(dyn StdError + 'static) { + unsafe { ErrorImpl::error(self.inner.by_ref()) } + } +} + +impl std::borrow::Borrow<dyn Diagnostic> for Report { + fn borrow(&self) -> &(dyn Diagnostic + 'static) { + self.as_ref() + } +} diff --git a/vendor/miette/src/eyreish/fmt.rs b/vendor/miette/src/eyreish/fmt.rs new file mode 100644 index 0000000..9e385d1 --- /dev/null +++ b/vendor/miette/src/eyreish/fmt.rs @@ -0,0 +1,20 @@ +use super::{error::ErrorImpl, ptr::Ref}; +use core::fmt; + +impl ErrorImpl<()> { + pub(crate) unsafe fn display(this: Ref<'_, Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result { + this.deref() + .handler + .as_ref() + .map(|handler| handler.display(Self::error(this), f)) + .unwrap_or_else(|| core::fmt::Display::fmt(Self::diagnostic(this), f)) + } + + pub(crate) unsafe fn debug(this: Ref<'_, Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result { + this.deref() + .handler + .as_ref() + .map(|handler| handler.debug(Self::diagnostic(this), f)) + .unwrap_or_else(|| core::fmt::Debug::fmt(Self::diagnostic(this), f)) + } +} diff --git a/vendor/miette/src/eyreish/into_diagnostic.rs b/vendor/miette/src/eyreish/into_diagnostic.rs new file mode 100644 index 0000000..6480013 --- /dev/null +++ b/vendor/miette/src/eyreish/into_diagnostic.rs @@ -0,0 +1,33 @@ +use thiserror::Error; + +use crate::{Diagnostic, Report}; + +/// Convenience [`Diagnostic`] that can be used as an "anonymous" wrapper for +/// Errors. This is intended to be paired with [`IntoDiagnostic`]. +#[derive(Debug, Error)] +#[error(transparent)] +struct DiagnosticError(Box<dyn std::error::Error + Send + Sync + 'static>); +impl Diagnostic for DiagnosticError {} + +/** +Convenience trait that adds a [`.into_diagnostic()`](IntoDiagnostic::into_diagnostic) method that converts a type implementing +[`std::error::Error`] to a [`Result<T, Report>`]. + +## Warning + +Calling this on a type implementing [`Diagnostic`] will reduce it to the common denominator of +[`std::error::Error`]. Meaning all extra information provided by [`Diagnostic`] will be +inaccessible. If you have a type implementing [`Diagnostic`] consider simply returning it or using +[`Into`] or the [`Try`](std::ops::Try) operator (`?`). +*/ +pub trait IntoDiagnostic<T, E> { + /// Converts [`Result`] types that return regular [`std::error::Error`]s + /// into a [`Result`] that returns a [`Diagnostic`]. + fn into_diagnostic(self) -> Result<T, Report>; +} + +impl<T, E: std::error::Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> { + fn into_diagnostic(self) -> Result<T, Report> { + self.map_err(|e| DiagnosticError(Box::new(e)).into()) + } +} diff --git a/vendor/miette/src/eyreish/kind.rs b/vendor/miette/src/eyreish/kind.rs new file mode 100644 index 0000000..ce60b50 --- /dev/null +++ b/vendor/miette/src/eyreish/kind.rs @@ -0,0 +1,111 @@ +#![allow(missing_debug_implementations, missing_docs)] +// Tagged dispatch mechanism for resolving the behavior of `miette!($expr)`. +// +// When miette! is given a single expr argument to turn into miette::Report, we +// want the resulting Report to pick up the input's implementation of source() +// and backtrace() if it has a std::error::Error impl, otherwise require nothing +// more than Display and Debug. +// +// Expressed in terms of specialization, we want something like: +// +// trait EyreNew { +// fn new(self) -> Report; +// } +// +// impl<T> EyreNew for T +// where +// T: Display + Debug + Send + Sync + 'static, +// { +// default fn new(self) -> Report { +// /* no std error impl */ +// } +// } +// +// impl<T> EyreNew for T +// where +// T: std::error::Error + Send + Sync + 'static, +// { +// fn new(self) -> Report { +// /* use std error's source() and backtrace() */ +// } +// } +// +// Since specialization is not stable yet, instead we rely on autoref behavior +// of method resolution to perform tagged dispatch. Here we have two traits +// AdhocKind and TraitKind that both have an miette_kind() method. AdhocKind is +// implemented whether or not the caller's type has a std error impl, while +// TraitKind is implemented only when a std error impl does exist. The ambiguity +// is resolved by AdhocKind requiring an extra autoref so that it has lower +// precedence. +// +// The miette! macro will set up the call in this form: +// +// #[allow(unused_imports)] +// use $crate::private::{AdhocKind, TraitKind}; +// let error = $msg; +// (&error).miette_kind().new(error) + +use super::Report; +use core::fmt::{Debug, Display}; + +use crate::Diagnostic; + +pub struct Adhoc; + +pub trait AdhocKind: Sized { + #[inline] + fn miette_kind(&self) -> Adhoc { + Adhoc + } +} + +impl<T> AdhocKind for &T where T: ?Sized + Display + Debug + Send + Sync + 'static {} + +impl Adhoc { + #[cfg_attr(track_caller, track_caller)] + pub fn new<M>(self, message: M) -> Report + where + M: Display + Debug + Send + Sync + 'static, + { + Report::from_adhoc(message) + } +} + +pub struct Trait; + +pub trait TraitKind: Sized { + #[inline] + fn miette_kind(&self) -> Trait { + Trait + } +} + +impl<E> TraitKind for E where E: Into<Report> {} + +impl Trait { + #[cfg_attr(track_caller, track_caller)] + pub fn new<E>(self, error: E) -> Report + where + E: Into<Report>, + { + error.into() + } +} + +pub struct Boxed; + +pub trait BoxedKind: Sized { + #[inline] + fn miette_kind(&self) -> Boxed { + Boxed + } +} + +impl BoxedKind for Box<dyn Diagnostic + Send + Sync> {} + +impl Boxed { + #[cfg_attr(track_caller, track_caller)] + pub fn new(self, error: Box<dyn Diagnostic + Send + Sync>) -> Report { + Report::from_boxed(error) + } +} diff --git a/vendor/miette/src/eyreish/macros.rs b/vendor/miette/src/eyreish/macros.rs new file mode 100644 index 0000000..e13309f --- /dev/null +++ b/vendor/miette/src/eyreish/macros.rs @@ -0,0 +1,300 @@ +/// Return early with an error. +/// +/// This macro is equivalent to `return Err(From::from($err))`. +/// +/// # Example +/// +/// ``` +/// # use miette::{bail, Result}; +/// # +/// # fn has_permission(user: usize, resource: usize) -> bool { +/// # true +/// # } +/// # +/// # fn main() -> Result<()> { +/// # let user = 0; +/// # let resource = 0; +/// # +/// if !has_permission(user, resource) { +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#" bail!("permission denied for accessing {resource}");"# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#" bail!("permission denied for accessing {}", resource);"# +)] +/// } +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// # use miette::{bail, Result}; +/// # use thiserror::Error; +/// # +/// # const MAX_DEPTH: usize = 1; +/// # +/// #[derive(Error, Debug)] +/// enum ScienceError { +/// #[error("recursion limit exceeded")] +/// RecursionLimitExceeded, +/// # #[error("...")] +/// # More = (stringify! { +/// ... +/// # }, 1).1, +/// } +/// +/// # fn main() -> Result<()> { +/// # let depth = 0; +/// # let err: &'static dyn std::error::Error = &ScienceError::RecursionLimitExceeded; +/// # +/// if depth > MAX_DEPTH { +/// bail!(ScienceError::RecursionLimitExceeded); +/// } +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// use miette::{bail, Result, Severity}; +/// +/// fn divide(x: f64, y: f64) -> Result<f64> { +/// if y.abs() < 1e-3 { +/// bail!( +/// severity = Severity::Warning, +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#" "dividing by value ({y}) close to 0""# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#" "dividing by value ({}) close to 0", y"# +)] +/// ); +/// } +/// Ok(x / y) +/// } +/// ``` +#[macro_export] +macro_rules! bail { + ($($key:ident = $value:expr,)* $fmt:literal $($arg:tt)*) => { + return $crate::private::Err( + $crate::miette!($($key = $value,)* $fmt $($arg)*) + ); + }; + ($err:expr $(,)?) => { + return $crate::private::Err($crate::miette!($err)); + }; +} + +/// Return early with an error if a condition is not satisfied. +/// +/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`. +/// +/// Analogously to `assert!`, `ensure!` takes a condition and exits the function +/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error` +/// rather than panicking. +/// +/// # Example +/// +/// ``` +/// # use miette::{ensure, Result}; +/// # +/// # fn main() -> Result<()> { +/// # let user = 0; +/// # +/// ensure!(user == 0, "only user 0 is allowed"); +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// # use miette::{ensure, Result}; +/// # use thiserror::Error; +/// # +/// # const MAX_DEPTH: usize = 1; +/// # +/// #[derive(Error, Debug)] +/// enum ScienceError { +/// #[error("recursion limit exceeded")] +/// RecursionLimitExceeded, +/// # #[error("...")] +/// # More = (stringify! { +/// ... +/// # }, 1).1, +/// } +/// +/// # fn main() -> Result<()> { +/// # let depth = 0; +/// # +/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded); +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// use miette::{ensure, Result, Severity}; +/// +/// fn divide(x: f64, y: f64) -> Result<f64> { +/// ensure!( +/// y.abs() >= 1e-3, +/// severity = Severity::Warning, +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#" "dividing by value ({y}) close to 0""# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#" "dividing by value ({}) close to 0", y"# +)] +/// ); +/// Ok(x / y) +/// } +/// ``` +#[macro_export] +macro_rules! ensure { + ($cond:expr, $($key:ident = $value:expr,)* $fmt:literal $($arg:tt)*) => { + if !$cond { + return $crate::private::Err( + $crate::miette!($($key = $value,)* $fmt $($arg)*) + ); + } + }; + ($cond:expr, $err:expr $(,)?) => { + if !$cond { + return $crate::private::Err($crate::miette!($err)); + } + }; +} + +/// Construct an ad-hoc [`Report`]. +/// +/// # Examples +/// +/// With string literal and interpolation: +/// ``` +/// # use miette::miette; +/// let x = 1; +/// let y = 2; +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#"let report = miette!("{x} + {} = {z}", y, z = x + y);"# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#"let report = miette!("{} + {} = {z}", x, y, z = x + y);"# +)] +/// +/// assert_eq!(report.to_string().as_str(), "1 + 2 = 3"); +/// +/// let z = x + y; +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#"let report = miette!("{x} + {y} = {z}");"# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#"let report = miette!("{} + {} = {}", x, y, z);"# +)] +/// assert_eq!(report.to_string().as_str(), "1 + 2 = 3"); +/// ``` +/// +/// With [`diagnostic!`]-like arguments: +/// ``` +/// use miette::{miette, LabeledSpan, Severity}; +/// +/// let source = "(2 + 2".to_string(); +/// let report = miette!( +/// // Those fields are optional +/// severity = Severity::Error, +/// code = "expected::rparen", +/// help = "always close your parens", +/// labels = vec![LabeledSpan::at_offset(6, "here")], +/// url = "https://example.com", +/// // Rest of the arguments are passed to `format!` +/// // to form diagnostic message +/// "expected closing ')'" +/// ) +/// .with_source_code(source); +/// ``` +/// +/// ## `anyhow`/`eyre` Users +/// +/// You can just replace `use`s of the `anyhow!`/`eyre!` macros with `miette!`. +/// +/// [`diagnostic!`]: crate::diagnostic! +/// [`Report`]: crate::Report +#[macro_export] +macro_rules! miette { + ($($key:ident = $value:expr,)* $fmt:literal $($arg:tt)*) => { + $crate::Report::from( + $crate::diagnostic!($($key = $value,)* $fmt $($arg)*) + ) + }; + ($err:expr $(,)?) => ({ + use $crate::private::kind::*; + let error = $err; + (&error).miette_kind().new(error) + }); +} + +/// Construct a [`MietteDiagnostic`] in more user-friendly way. +/// +/// # Examples +/// ``` +/// use miette::{diagnostic, LabeledSpan, Severity}; +/// +/// let source = "(2 + 2".to_string(); +/// let diag = diagnostic!( +/// // Those fields are optional +/// severity = Severity::Error, +/// code = "expected::rparen", +/// help = "always close your parens", +/// labels = vec![LabeledSpan::at_offset(6, "here")], +/// url = "https://example.com", +/// // Rest of the arguments are passed to `format!` +/// // to form diagnostic message +/// "expected closing ')'", +/// ); +/// ``` +/// Diagnostic without any fields: +/// ``` +/// # use miette::diagnostic; +/// let x = 1; +/// let y = 2; +/// +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#" let diag = diagnostic!("{x} + {} = {z}", y, z = x + y);"# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#" let diag = diagnostic!("{} + {} = {z}", x, y, z = x + y);"# +)] +/// assert_eq!(diag.message, "1 + 2 = 3"); +/// +/// let z = x + y; +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#"let diag = diagnostic!("{x} + {y} = {z}");"# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#"let diag = diagnostic!("{} + {} = {}", x, y, z);"# +)] +/// assert_eq!(diag.message, "1 + 2 = 3"); +/// ``` +/// +/// [`MietteDiagnostic`]: crate::MietteDiagnostic +#[macro_export] +macro_rules! diagnostic { + ($fmt:literal $($arg:tt)*) => {{ + $crate::MietteDiagnostic::new(format!($fmt $($arg)*)) + }}; + ($($key:ident = $value:expr,)+ $fmt:literal $($arg:tt)*) => {{ + let mut diag = $crate::MietteDiagnostic::new(format!($fmt $($arg)*)); + $(diag.$key = Some($value.into());)* + diag + }}; +} diff --git a/vendor/miette/src/eyreish/mod.rs b/vendor/miette/src/eyreish/mod.rs new file mode 100644 index 0000000..0efceed --- /dev/null +++ b/vendor/miette/src/eyreish/mod.rs @@ -0,0 +1,485 @@ +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![allow( + clippy::needless_doctest_main, + clippy::new_ret_no_self, + clippy::wrong_self_convention +)] +use core::fmt::Display; + +use std::error::Error as StdError; + +use once_cell::sync::OnceCell; + +#[allow(unreachable_pub)] +pub use into_diagnostic::*; +#[doc(hidden)] +#[allow(unreachable_pub)] +pub use Report as ErrReport; +/// Compatibility re-export of `Report` for interop with `anyhow` +#[allow(unreachable_pub)] +pub use Report as Error; +#[doc(hidden)] +#[allow(unreachable_pub)] +pub use ReportHandler as EyreContext; +/// Compatibility re-export of `WrapErr` for interop with `anyhow` +#[allow(unreachable_pub)] +pub use WrapErr as Context; + +#[cfg(not(feature = "fancy-no-backtrace"))] +use crate::DebugReportHandler; +use crate::Diagnostic; +#[cfg(feature = "fancy-no-backtrace")] +use crate::MietteHandler; + +use error::ErrorImpl; + +use self::ptr::Own; + +mod context; +mod error; +mod fmt; +mod into_diagnostic; +mod kind; +mod macros; +mod ptr; +mod wrapper; + +/** +Core Diagnostic wrapper type. + +## `eyre` Users + +You can just replace `use`s of `eyre::Report` with `miette::Report`. +*/ +pub struct Report { + inner: Own<ErrorImpl<()>>, +} + +unsafe impl Sync for Report {} +unsafe impl Send for Report {} + +/// +pub type ErrorHook = + Box<dyn Fn(&(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> + Sync + Send + 'static>; + +static HOOK: OnceCell<ErrorHook> = OnceCell::new(); + +/// Error indicating that [`set_hook()`] was unable to install the provided +/// [`ErrorHook`]. +#[derive(Debug)] +pub struct InstallError; + +impl core::fmt::Display for InstallError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_str("cannot install provided ErrorHook, a hook has already been installed") + } +} + +impl StdError for InstallError {} +impl Diagnostic for InstallError {} + +/** +Set the error hook. +*/ +pub fn set_hook(hook: ErrorHook) -> Result<(), InstallError> { + HOOK.set(hook).map_err(|_| InstallError) +} + +#[cfg_attr(track_caller, track_caller)] +#[cfg_attr(not(track_caller), allow(unused_mut))] +fn capture_handler(error: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> { + let hook = HOOK.get_or_init(|| Box::new(get_default_printer)).as_ref(); + + #[cfg(track_caller)] + { + let mut handler = hook(error); + handler.track_caller(std::panic::Location::caller()); + handler + } + #[cfg(not(track_caller))] + { + hook(error) + } +} + +fn get_default_printer(_err: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler + 'static> { + #[cfg(feature = "fancy-no-backtrace")] + return Box::new(MietteHandler::new()); + #[cfg(not(feature = "fancy-no-backtrace"))] + return Box::new(DebugReportHandler::new()); +} + +impl dyn ReportHandler { + /// + pub fn is<T: ReportHandler>(&self) -> bool { + // Get `TypeId` of the type this function is instantiated with. + let t = core::any::TypeId::of::<T>(); + + // Get `TypeId` of the type in the trait object (`self`). + let concrete = self.type_id(); + + // Compare both `TypeId`s on equality. + t == concrete + } + + /// + pub fn downcast_ref<T: ReportHandler>(&self) -> Option<&T> { + if self.is::<T>() { + unsafe { Some(&*(self as *const dyn ReportHandler as *const T)) } + } else { + None + } + } + + /// + pub fn downcast_mut<T: ReportHandler>(&mut self) -> Option<&mut T> { + if self.is::<T>() { + unsafe { Some(&mut *(self as *mut dyn ReportHandler as *mut T)) } + } else { + None + } + } +} + +/// Error Report Handler trait for customizing `miette::Report` +pub trait ReportHandler: core::any::Any + Send + Sync { + /// Define the report format + /// + /// Used to override the report format of `miette::Report` + /// + /// # Example + /// + /// ```rust + /// use indenter::indented; + /// use miette::{Diagnostic, ReportHandler}; + /// + /// pub struct Handler; + /// + /// impl ReportHandler for Handler { + /// fn debug( + /// &self, + /// error: &dyn Diagnostic, + /// f: &mut core::fmt::Formatter<'_>, + /// ) -> core::fmt::Result { + /// use core::fmt::Write as _; + /// + /// if f.alternate() { + /// return core::fmt::Debug::fmt(error, f); + /// } + /// + /// write!(f, "{}", error)?; + /// + /// Ok(()) + /// } + /// } + /// ``` + fn debug( + &self, + error: &(dyn Diagnostic), + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result; + + /// Override for the `Display` format + fn display( + &self, + error: &(dyn StdError + 'static), + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + write!(f, "{}", error)?; + + if f.alternate() { + for cause in crate::chain::Chain::new(error).skip(1) { + write!(f, ": {}", cause)?; + } + } + + Ok(()) + } + + /// Store the location of the caller who constructed this error report + #[allow(unused_variables)] + fn track_caller(&mut self, location: &'static std::panic::Location<'static>) {} +} + +/// type alias for `Result<T, Report>` +/// +/// This is a reasonable return type to use throughout your application but also +/// for `main()`. If you do, failures will be printed along with a backtrace if +/// one was captured. +/// +/// `miette::Result` may be used with one *or* two type parameters. +/// +/// ```rust +/// use miette::Result; +/// +/// # const IGNORE: &str = stringify! { +/// fn demo1() -> Result<T> {...} +/// // ^ equivalent to std::result::Result<T, miette::Error> +/// +/// fn demo2() -> Result<T, OtherError> {...} +/// // ^ equivalent to std::result::Result<T, OtherError> +/// # }; +/// ``` +/// +/// # Example +/// +/// ``` +/// # pub trait Deserialize {} +/// # +/// # mod serde_json { +/// # use super::Deserialize; +/// # use std::io; +/// # +/// # pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> { +/// # unimplemented!() +/// # } +/// # } +/// # +/// # #[derive(Debug)] +/// # struct ClusterMap; +/// # +/// # impl Deserialize for ClusterMap {} +/// # +/// use miette::{IntoDiagnostic, Result}; +/// +/// fn main() -> Result<()> { +/// # return Ok(()); +/// let config = std::fs::read_to_string("cluster.json").into_diagnostic()?; +/// let map: ClusterMap = serde_json::from_str(&config).into_diagnostic()?; +/// println!("cluster info: {:#?}", map); +/// Ok(()) +/// } +/// ``` +/// +/// ## `anyhow`/`eyre` Users +/// +/// You can just replace `use`s of `anyhow::Result`/`eyre::Result` with +/// `miette::Result`. +pub type Result<T, E = Report> = core::result::Result<T, E>; + +/// Provides the [`wrap_err()`](WrapErr::wrap_err) method for [`Result`]. +/// +/// This trait is sealed and cannot be implemented for types outside of +/// `miette`. +/// +/// # Example +/// +/// ``` +/// use miette::{WrapErr, IntoDiagnostic, Result}; +/// use std::{fs, path::PathBuf}; +/// +/// pub struct ImportantThing { +/// path: PathBuf, +/// } +/// +/// impl ImportantThing { +/// # const IGNORE: &'static str = stringify! { +/// pub fn detach(&mut self) -> Result<()> {...} +/// # }; +/// # fn detach(&mut self) -> Result<()> { +/// # unimplemented!() +/// # } +/// } +/// +/// pub fn do_it(mut it: ImportantThing) -> Result<Vec<u8>> { +/// it.detach().wrap_err("Failed to detach the important thing")?; +/// +/// let path = &it.path; +/// let content = fs::read(path) +/// .into_diagnostic() +/// .wrap_err_with(|| format!( +/// "Failed to read instrs from {}", +/// path.display()) +/// )?; +/// +/// Ok(content) +/// } +/// ``` +/// +/// When printed, the outermost error would be printed first and the lower +/// level underlying causes would be enumerated below. +/// +/// ```console +/// Error: Failed to read instrs from ./path/to/instrs.json +/// +/// Caused by: +/// No such file or directory (os error 2) +/// ``` +/// +/// # Wrapping Types That Do Not Implement `Error` +/// +/// For example `&str` and `Box<dyn Error>`. +/// +/// Due to restrictions for coherence `Report` cannot implement `From` for types +/// that don't implement `Error`. Attempts to do so will give `"this type might +/// implement Error in the future"` as an error. As such, `wrap_err()`, which +/// uses `From` under the hood, cannot be used to wrap these types. Instead we +/// encourage you to use the combinators provided for `Result` in `std`/`core`. +/// +/// For example, instead of this: +/// +/// ```rust,compile_fail +/// use std::error::Error; +/// use miette::{WrapErr, Report}; +/// +/// fn wrap_example(err: Result<(), Box<dyn Error + Send + Sync + 'static>>) +/// -> Result<(), Report> +/// { +/// err.wrap_err("saw a downstream error") +/// } +/// ``` +/// +/// We encourage you to write this: +/// +/// ```rust +/// use miette::{miette, Report, WrapErr}; +/// use std::error::Error; +/// +/// fn wrap_example(err: Result<(), Box<dyn Error + Send + Sync + 'static>>) -> Result<(), Report> { +/// err.map_err(|e| miette!(e)) +/// .wrap_err("saw a downstream error") +/// } +/// ``` +/// +/// # Effect on Downcasting +/// +/// After attaching a message of type `D` onto an error of type `E`, the +/// resulting `miette::Error` may be downcast to `D` **or** to `E`. +/// +/// That is, in codebases that rely on downcasting, `miette`'s `wrap_err()` +/// supports both of the following use cases: +/// +/// - **Attaching messages whose type is insignificant onto errors whose type +/// is used in downcasts.** +/// +/// In other error libraries whose `wrap_err()` is not designed this way, it +/// can be risky to introduce messages to existing code because new message +/// might break existing working downcasts. In miette, any downcast that +/// worked before adding the message will continue to work after you add a +/// message, so you should freely wrap errors wherever it would be helpful. +/// +/// ``` +/// # use miette::bail; +/// # use thiserror::Error; +/// # +/// # #[derive(Error, Debug)] +/// # #[error("???")] +/// # struct SuspiciousError; +/// # +/// # fn helper() -> Result<()> { +/// # bail!(SuspiciousError); +/// # } +/// # +/// use miette::{WrapErr, Result}; +/// +/// fn do_it() -> Result<()> { +/// helper().wrap_err("Failed to complete the work")?; +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # unreachable!() +/// } +/// +/// fn main() { +/// let err = do_it().unwrap_err(); +/// if let Some(e) = err.downcast_ref::<SuspiciousError>() { +/// // If helper() returned SuspiciousError, this downcast will +/// // correctly succeed even with the message in between. +/// # return; +/// } +/// # panic!("expected downcast to succeed"); +/// } +/// ``` +/// +/// - **Attaching message whose type is used in downcasts onto errors whose +/// type is insignificant.** +/// +/// Some codebases prefer to use machine-readable messages to categorize +/// lower level errors in a way that will be actionable to higher levels of +/// the application. +/// +/// ``` +/// # use miette::bail; +/// # use thiserror::Error; +/// # +/// # #[derive(Error, Debug)] +/// # #[error("???")] +/// # struct HelperFailed; +/// # +/// # fn helper() -> Result<()> { +/// # bail!("no such file or directory"); +/// # } +/// # +/// use miette::{WrapErr, Result}; +/// +/// fn do_it() -> Result<()> { +/// helper().wrap_err(HelperFailed)?; +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # unreachable!() +/// } +/// +/// fn main() { +/// let err = do_it().unwrap_err(); +/// if let Some(e) = err.downcast_ref::<HelperFailed>() { +/// // If helper failed, this downcast will succeed because +/// // HelperFailed is the message that has been attached to +/// // that error. +/// # return; +/// } +/// # panic!("expected downcast to succeed"); +/// } +/// ``` +pub trait WrapErr<T, E>: context::private::Sealed { + /// Wrap the error value with a new adhoc error + #[cfg_attr(track_caller, track_caller)] + fn wrap_err<D>(self, msg: D) -> Result<T, Report> + where + D: Display + Send + Sync + 'static; + + /// Wrap the error value with a new adhoc error that is evaluated lazily + /// only once an error does occur. + #[cfg_attr(track_caller, track_caller)] + fn wrap_err_with<D, F>(self, f: F) -> Result<T, Report> + where + D: Display + Send + Sync + 'static, + F: FnOnce() -> D; + + /// Compatibility re-export of `wrap_err()` for interop with `anyhow` + #[cfg_attr(track_caller, track_caller)] + fn context<D>(self, msg: D) -> Result<T, Report> + where + D: Display + Send + Sync + 'static; + + /// Compatibility re-export of `wrap_err_with()` for interop with `anyhow` + #[cfg_attr(track_caller, track_caller)] + fn with_context<D, F>(self, f: F) -> Result<T, Report> + where + D: Display + Send + Sync + 'static, + F: FnOnce() -> D; +} + +// Private API. Referenced by macro-generated code. +#[doc(hidden)] +pub mod private { + use super::Report; + use core::fmt::{Debug, Display}; + + pub use core::result::Result::Err; + + #[doc(hidden)] + pub mod kind { + pub use super::super::kind::{AdhocKind, TraitKind}; + + pub use super::super::kind::BoxedKind; + } + + #[cfg_attr(track_caller, track_caller)] + pub fn new_adhoc<M>(message: M) -> Report + where + M: Display + Debug + Send + Sync + 'static, + { + Report::from_adhoc(message) + } +} diff --git a/vendor/miette/src/eyreish/ptr.rs b/vendor/miette/src/eyreish/ptr.rs new file mode 100644 index 0000000..fa954d1 --- /dev/null +++ b/vendor/miette/src/eyreish/ptr.rs @@ -0,0 +1,188 @@ +use std::{marker::PhantomData, ptr::NonNull}; + +#[repr(transparent)] +/// A raw pointer that owns its pointee +pub(crate) struct Own<T> +where + T: ?Sized, +{ + pub(crate) ptr: NonNull<T>, +} + +unsafe impl<T> Send for Own<T> where T: ?Sized {} +unsafe impl<T> Sync for Own<T> where T: ?Sized {} + +impl<T> Copy for Own<T> where T: ?Sized {} + +impl<T> Clone for Own<T> +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl<T> Own<T> +where + T: ?Sized, +{ + pub(crate) fn new(ptr: Box<T>) -> Self { + Own { + ptr: unsafe { NonNull::new_unchecked(Box::into_raw(ptr)) }, + } + } + + pub(crate) fn cast<U: CastTo>(self) -> Own<U::Target> { + Own { + ptr: self.ptr.cast(), + } + } + + pub(crate) unsafe fn boxed(self) -> Box<T> { + Box::from_raw(self.ptr.as_ptr()) + } + + pub(crate) const fn by_ref<'a>(&self) -> Ref<'a, T> { + Ref { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub(crate) fn by_mut<'a>(self) -> Mut<'a, T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } +} + +#[allow(explicit_outlives_requirements)] +#[repr(transparent)] +/// A raw pointer that represents a shared borrow of its pointee +pub(crate) struct Ref<'a, T> +where + T: ?Sized, +{ + pub(crate) ptr: NonNull<T>, + lifetime: PhantomData<&'a T>, +} + +impl<'a, T> Copy for Ref<'a, T> where T: ?Sized {} + +impl<'a, T> Clone for Ref<'a, T> +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> Ref<'a, T> +where + T: ?Sized, +{ + pub(crate) fn new(ptr: &'a T) -> Self { + Ref { + ptr: NonNull::from(ptr), + lifetime: PhantomData, + } + } + + pub(crate) const fn from_raw(ptr: NonNull<T>) -> Self { + Ref { + ptr, + lifetime: PhantomData, + } + } + + pub(crate) fn cast<U: CastTo>(self) -> Ref<'a, U::Target> { + Ref { + ptr: self.ptr.cast(), + lifetime: PhantomData, + } + } + + pub(crate) fn by_mut(self) -> Mut<'a, T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub(crate) const fn as_ptr(self) -> *const T { + self.ptr.as_ptr() as *const T + } + + pub(crate) unsafe fn deref(self) -> &'a T { + &*self.ptr.as_ptr() + } +} + +#[allow(explicit_outlives_requirements)] +#[repr(transparent)] +/// A raw pointer that represents a unique borrow of its pointee +pub(crate) struct Mut<'a, T> +where + T: ?Sized, +{ + pub(crate) ptr: NonNull<T>, + lifetime: PhantomData<&'a mut T>, +} + +impl<'a, T> Copy for Mut<'a, T> where T: ?Sized {} + +impl<'a, T> Clone for Mut<'a, T> +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> Mut<'a, T> +where + T: ?Sized, +{ + pub(crate) fn cast<U: CastTo>(self) -> Mut<'a, U::Target> { + Mut { + ptr: self.ptr.cast(), + lifetime: PhantomData, + } + } + + pub(crate) const fn by_ref(self) -> Ref<'a, T> { + Ref { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub(crate) fn extend<'b>(self) -> Mut<'b, T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub(crate) unsafe fn deref_mut(self) -> &'a mut T { + &mut *self.ptr.as_ptr() + } +} + +impl<'a, T> Mut<'a, T> { + pub(crate) unsafe fn read(self) -> T { + self.ptr.as_ptr().read() + } +} + +pub(crate) trait CastTo { + type Target; +} + +impl<T> CastTo for T { + type Target = T; +} diff --git a/vendor/miette/src/eyreish/wrapper.rs b/vendor/miette/src/eyreish/wrapper.rs new file mode 100644 index 0000000..91a5ef3 --- /dev/null +++ b/vendor/miette/src/eyreish/wrapper.rs @@ -0,0 +1,234 @@ +use core::fmt::{self, Debug, Display}; + +use std::error::Error as StdError; + +use crate::{Diagnostic, LabeledSpan, Report, SourceCode}; + +use crate as miette; + +#[repr(transparent)] +pub(crate) struct DisplayError<M>(pub(crate) M); + +#[repr(transparent)] +pub(crate) struct MessageError<M>(pub(crate) M); + +pub(crate) struct NoneError; + +impl<M> Debug for DisplayError<M> +where + M: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl<M> Display for DisplayError<M> +where + M: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl<M> StdError for DisplayError<M> where M: Display + 'static {} +impl<M> Diagnostic for DisplayError<M> where M: Display + 'static {} + +impl<M> Debug for MessageError<M> +where + M: Display + Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.0, f) + } +} + +impl<M> Display for MessageError<M> +where + M: Display + Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {} +impl<M> Diagnostic for MessageError<M> where M: Display + Debug + 'static {} + +impl Debug for NoneError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt("Option was None", f) + } +} + +impl Display for NoneError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt("Option was None", f) + } +} + +impl StdError for NoneError {} +impl Diagnostic for NoneError {} + +#[repr(transparent)] +pub(crate) struct BoxedError(pub(crate) Box<dyn Diagnostic + Send + Sync>); + +impl Diagnostic for BoxedError { + fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.0.code() + } + + fn severity(&self) -> Option<miette::Severity> { + self.0.severity() + } + + fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.0.help() + } + + fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.0.url() + } + + fn labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>> { + self.0.labels() + } + + fn source_code(&self) -> Option<&dyn miette::SourceCode> { + self.0.source_code() + } + + fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> { + self.0.related() + } + + fn diagnostic_source(&self) -> Option<&dyn Diagnostic> { + self.0.diagnostic_source() + } +} + +impl Debug for BoxedError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.0, f) + } +} + +impl Display for BoxedError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl StdError for BoxedError { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.0.source() + } + + fn description(&self) -> &str { + #[allow(deprecated)] + self.0.description() + } + + fn cause(&self) -> Option<&dyn StdError> { + #[allow(deprecated)] + self.0.cause() + } +} + +pub(crate) struct WithSourceCode<E, C> { + pub(crate) error: E, + pub(crate) source_code: C, +} + +impl<E: Diagnostic, C: SourceCode> Diagnostic for WithSourceCode<E, C> { + fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.error.code() + } + + fn severity(&self) -> Option<miette::Severity> { + self.error.severity() + } + + fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.error.help() + } + + fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.error.url() + } + + fn labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>> { + self.error.labels() + } + + fn source_code(&self) -> Option<&dyn miette::SourceCode> { + Some(&self.source_code) + } + + fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> { + self.error.related() + } + + fn diagnostic_source(&self) -> Option<&dyn Diagnostic> { + self.error.diagnostic_source() + } +} + +impl<C: SourceCode> Diagnostic for WithSourceCode<Report, C> { + fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.error.code() + } + + fn severity(&self) -> Option<miette::Severity> { + self.error.severity() + } + + fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.error.help() + } + + fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { + self.error.url() + } + + fn labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>> { + self.error.labels() + } + + fn source_code(&self) -> Option<&dyn miette::SourceCode> { + Some(&self.source_code) + } + + fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> { + self.error.related() + } + + fn diagnostic_source(&self) -> Option<&dyn Diagnostic> { + self.error.diagnostic_source() + } +} + +impl<E: Debug, C> Debug for WithSourceCode<E, C> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.error, f) + } +} + +impl<E: Display, C> Display for WithSourceCode<E, C> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.error, f) + } +} + +impl<E: StdError, C> StdError for WithSourceCode<E, C> { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.error.source() + } +} + +impl<C> StdError for WithSourceCode<Report, C> { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.error.source() + } +} |