1 use super::error::{ContextError, ErrorImpl}; 2 use super::{Report, WrapErr}; 3 use core::fmt::{self, Debug, Display, Write}; 4 5 use std::error::Error as StdError; 6 7 use crate::{Diagnostic, LabeledSpan}; 8 9 mod ext { 10 use super::*; 11 12 pub trait Diag { 13 #[cfg_attr(track_caller, track_caller)] ext_report<D>(self, msg: D) -> Report where D: Display + Send + Sync + 'static14 fn ext_report<D>(self, msg: D) -> Report 15 where 16 D: Display + Send + Sync + 'static; 17 } 18 19 impl<E> Diag for E 20 where 21 E: Diagnostic + Send + Sync + 'static, 22 { ext_report<D>(self, msg: D) -> Report where D: Display + Send + Sync + 'static,23 fn ext_report<D>(self, msg: D) -> Report 24 where 25 D: Display + Send + Sync + 'static, 26 { 27 Report::from_msg(msg, self) 28 } 29 } 30 31 impl Diag for Report { ext_report<D>(self, msg: D) -> Report where D: Display + Send + Sync + 'static,32 fn ext_report<D>(self, msg: D) -> Report 33 where 34 D: Display + Send + Sync + 'static, 35 { 36 self.wrap_err(msg) 37 } 38 } 39 } 40 41 impl<T, E> WrapErr<T, E> for Result<T, E> 42 where 43 E: ext::Diag + Send + Sync + 'static, 44 { wrap_err<D>(self, msg: D) -> Result<T, Report> where D: Display + Send + Sync + 'static,45 fn wrap_err<D>(self, msg: D) -> Result<T, Report> 46 where 47 D: Display + Send + Sync + 'static, 48 { 49 match self { 50 Ok(t) => Ok(t), 51 Err(e) => Err(e.ext_report(msg)), 52 } 53 } 54 wrap_err_with<D, F>(self, msg: F) -> Result<T, Report> where D: Display + Send + Sync + 'static, F: FnOnce() -> D,55 fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report> 56 where 57 D: Display + Send + Sync + 'static, 58 F: FnOnce() -> D, 59 { 60 match self { 61 Ok(t) => Ok(t), 62 Err(e) => Err(e.ext_report(msg())), 63 } 64 } 65 context<D>(self, msg: D) -> Result<T, Report> where D: Display + Send + Sync + 'static,66 fn context<D>(self, msg: D) -> Result<T, Report> 67 where 68 D: Display + Send + Sync + 'static, 69 { 70 self.wrap_err(msg) 71 } 72 with_context<D, F>(self, msg: F) -> Result<T, Report> where D: Display + Send + Sync + 'static, F: FnOnce() -> D,73 fn with_context<D, F>(self, msg: F) -> Result<T, Report> 74 where 75 D: Display + Send + Sync + 'static, 76 F: FnOnce() -> D, 77 { 78 self.wrap_err_with(msg) 79 } 80 } 81 82 impl<D, E> Debug for ContextError<D, E> 83 where 84 D: Display, 85 E: Debug, 86 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 88 f.debug_struct("Error") 89 .field("msg", &Quoted(&self.msg)) 90 .field("source", &self.error) 91 .finish() 92 } 93 } 94 95 impl<D, E> Display for ContextError<D, E> 96 where 97 D: Display, 98 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 100 Display::fmt(&self.msg, f) 101 } 102 } 103 104 impl<D, E> StdError for ContextError<D, E> 105 where 106 D: Display, 107 E: StdError + 'static, 108 { source(&self) -> Option<&(dyn StdError + 'static)>109 fn source(&self) -> Option<&(dyn StdError + 'static)> { 110 Some(&self.error) 111 } 112 } 113 114 impl<D> StdError for ContextError<D, Report> 115 where 116 D: Display, 117 { source(&self) -> Option<&(dyn StdError + 'static)>118 fn source(&self) -> Option<&(dyn StdError + 'static)> { 119 unsafe { Some(ErrorImpl::error(self.error.inner.by_ref())) } 120 } 121 } 122 123 impl<D, E> Diagnostic for ContextError<D, E> 124 where 125 D: Display, 126 E: Diagnostic + 'static, 127 { code<'a>(&'a self) -> Option<Box<dyn Display + 'a>>128 fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { 129 self.error.code() 130 } 131 severity(&self) -> Option<crate::Severity>132 fn severity(&self) -> Option<crate::Severity> { 133 self.error.severity() 134 } 135 help<'a>(&'a self) -> Option<Box<dyn Display + 'a>>136 fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { 137 self.error.help() 138 } 139 url<'a>(&'a self) -> Option<Box<dyn Display + 'a>>140 fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { 141 self.error.url() 142 } 143 labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>>144 fn labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>> { 145 self.error.labels() 146 } 147 source_code(&self) -> Option<&dyn crate::SourceCode>148 fn source_code(&self) -> Option<&dyn crate::SourceCode> { 149 self.error.source_code() 150 } 151 related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>>152 fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> { 153 self.error.related() 154 } 155 } 156 157 impl<D> Diagnostic for ContextError<D, Report> 158 where 159 D: Display, 160 { code<'a>(&'a self) -> Option<Box<dyn Display + 'a>>161 fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { 162 unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).code() } 163 } 164 severity(&self) -> Option<crate::Severity>165 fn severity(&self) -> Option<crate::Severity> { 166 unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).severity() } 167 } 168 help<'a>(&'a self) -> Option<Box<dyn Display + 'a>>169 fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { 170 unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).help() } 171 } 172 url<'a>(&'a self) -> Option<Box<dyn Display + 'a>>173 fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> { 174 unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).url() } 175 } 176 labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>>177 fn labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>> { 178 unsafe { ErrorImpl::diagnostic(self.error.inner.by_ref()).labels() } 179 } 180 source_code(&self) -> Option<&dyn crate::SourceCode>181 fn source_code(&self) -> Option<&dyn crate::SourceCode> { 182 self.error.source_code() 183 } 184 related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>>185 fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> { 186 self.error.related() 187 } 188 } 189 190 struct Quoted<D>(D); 191 192 impl<D> Debug for Quoted<D> 193 where 194 D: Display, 195 { fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result196 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 197 formatter.write_char('"')?; 198 Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?; 199 formatter.write_char('"')?; 200 Ok(()) 201 } 202 } 203 204 impl Write for Quoted<&mut fmt::Formatter<'_>> { write_str(&mut self, s: &str) -> fmt::Result205 fn write_str(&mut self, s: &str) -> fmt::Result { 206 Display::fmt(&s.escape_debug(), self.0) 207 } 208 } 209 210 pub(crate) mod private { 211 use super::*; 212 213 pub trait Sealed {} 214 215 impl<T, E> Sealed for Result<T, E> where E: ext::Diag {} 216 impl<T> Sealed for Option<T> {} 217 } 218