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(self, msg: D) -> Report where D: Display + Send + Sync + 'static; } impl Diag for E where E: Diagnostic + Send + Sync + 'static, { fn ext_report(self, msg: D) -> Report where D: Display + Send + Sync + 'static, { Report::from_msg(msg, self) } } impl Diag for Report { fn ext_report(self, msg: D) -> Report where D: Display + Send + Sync + 'static, { self.wrap_err(msg) } } } impl WrapErr for Result where E: ext::Diag + Send + Sync + 'static, { fn wrap_err(self, msg: D) -> Result where D: Display + Send + Sync + 'static, { match self { Ok(t) => Ok(t), Err(e) => Err(e.ext_report(msg)), } } fn wrap_err_with(self, msg: F) -> Result where D: Display + Send + Sync + 'static, F: FnOnce() -> D, { match self { Ok(t) => Ok(t), Err(e) => Err(e.ext_report(msg())), } } fn context(self, msg: D) -> Result where D: Display + Send + Sync + 'static, { self.wrap_err(msg) } fn with_context(self, msg: F) -> Result where D: Display + Send + Sync + 'static, F: FnOnce() -> D, { self.wrap_err_with(msg) } } impl Debug for ContextError 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 Display for ContextError where D: Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt(&self.msg, f) } } impl StdError for ContextError where D: Display, E: StdError + 'static, { fn source(&self) -> Option<&(dyn StdError + 'static)> { Some(&self.error) } } impl StdError for ContextError where D: Display, { fn source(&self) -> Option<&(dyn StdError + 'static)> { unsafe { Some(ErrorImpl::error(self.error.inner.by_ref())) } } } impl Diagnostic for ContextError where D: Display, E: Diagnostic + 'static, { fn code<'a>(&'a self) -> Option> { self.error.code() } fn severity(&self) -> Option { self.error.severity() } fn help<'a>(&'a self) -> Option> { self.error.help() } fn url<'a>(&'a self) -> Option> { self.error.url() } fn labels<'a>(&'a self) -> Option + 'a>> { self.error.labels() } fn source_code(&self) -> Option<&dyn crate::SourceCode> { self.error.source_code() } fn related<'a>(&'a self) -> Option + 'a>> { self.error.related() } } impl Diagnostic for ContextError where D: Display, { fn code<'a>(&'a self) -> Option> { unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).code() } } fn severity(&self) -> Option { unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).severity() } } fn help<'a>(&'a self) -> Option> { unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).help() } } fn url<'a>(&'a self) -> Option> { unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).url() } } fn labels<'a>(&'a self) -> Option + '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 + 'a>> { self.error.related() } } struct Quoted(D); impl Debug for Quoted 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 Sealed for Result where E: ext::Diag {} impl Sealed for Option {} }