1 use crate::error::ContextError; 2 use crate::{Context, Error, StdError}; 3 use core::convert::Infallible; 4 use core::fmt::{self, Debug, Display, Write}; 5 6 #[cfg(error_generic_member_access)] 7 use std::error::Request; 8 9 mod ext { 10 use super::*; 11 12 pub trait StdError { ext_context<C>(self, context: C) -> Error where C: Display + Send + Sync + 'static13 fn ext_context<C>(self, context: C) -> Error 14 where 15 C: Display + Send + Sync + 'static; 16 } 17 18 #[cfg(feature = "std")] 19 impl<E> StdError for E 20 where 21 E: std::error::Error + Send + Sync + 'static, 22 { ext_context<C>(self, context: C) -> Error where C: Display + Send + Sync + 'static,23 fn ext_context<C>(self, context: C) -> Error 24 where 25 C: Display + Send + Sync + 'static, 26 { 27 let backtrace = backtrace_if_absent!(&self); 28 Error::from_context(context, self, backtrace) 29 } 30 } 31 32 impl StdError for Error { ext_context<C>(self, context: C) -> Error where C: Display + Send + Sync + 'static,33 fn ext_context<C>(self, context: C) -> Error 34 where 35 C: Display + Send + Sync + 'static, 36 { 37 self.context(context) 38 } 39 } 40 } 41 42 impl<T, E> Context<T, E> for Result<T, E> 43 where 44 E: ext::StdError + Send + Sync + 'static, 45 { context<C>(self, context: C) -> Result<T, Error> where C: Display + Send + Sync + 'static,46 fn context<C>(self, context: C) -> Result<T, Error> 47 where 48 C: Display + Send + Sync + 'static, 49 { 50 // Not using map_err to save 2 useless frames off the captured backtrace 51 // in ext_context. 52 match self { 53 Ok(ok) => Ok(ok), 54 Err(error) => Err(error.ext_context(context)), 55 } 56 } 57 with_context<C, F>(self, context: F) -> Result<T, Error> where C: Display + Send + Sync + 'static, F: FnOnce() -> C,58 fn with_context<C, F>(self, context: F) -> Result<T, Error> 59 where 60 C: Display + Send + Sync + 'static, 61 F: FnOnce() -> C, 62 { 63 match self { 64 Ok(ok) => Ok(ok), 65 Err(error) => Err(error.ext_context(context())), 66 } 67 } 68 } 69 70 /// ``` 71 /// # type T = (); 72 /// # 73 /// use anyhow::{Context, Result}; 74 /// 75 /// fn maybe_get() -> Option<T> { 76 /// # const IGNORE: &str = stringify! { 77 /// ... 78 /// # }; 79 /// # unimplemented!() 80 /// } 81 /// 82 /// fn demo() -> Result<()> { 83 /// let t = maybe_get().context("there is no T")?; 84 /// # const IGNORE: &str = stringify! { 85 /// ... 86 /// # }; 87 /// # unimplemented!() 88 /// } 89 /// ``` 90 impl<T> Context<T, Infallible> for Option<T> { context<C>(self, context: C) -> Result<T, Error> where C: Display + Send + Sync + 'static,91 fn context<C>(self, context: C) -> Result<T, Error> 92 where 93 C: Display + Send + Sync + 'static, 94 { 95 // Not using ok_or_else to save 2 useless frames off the captured 96 // backtrace. 97 match self { 98 Some(ok) => Ok(ok), 99 None => Err(Error::from_display(context, backtrace!())), 100 } 101 } 102 with_context<C, F>(self, context: F) -> Result<T, Error> where C: Display + Send + Sync + 'static, F: FnOnce() -> C,103 fn with_context<C, F>(self, context: F) -> Result<T, Error> 104 where 105 C: Display + Send + Sync + 'static, 106 F: FnOnce() -> C, 107 { 108 match self { 109 Some(ok) => Ok(ok), 110 None => Err(Error::from_display(context(), backtrace!())), 111 } 112 } 113 } 114 115 impl<C, E> Debug for ContextError<C, E> 116 where 117 C: Display, 118 E: Debug, 119 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 121 f.debug_struct("Error") 122 .field("context", &Quoted(&self.context)) 123 .field("source", &self.error) 124 .finish() 125 } 126 } 127 128 impl<C, E> Display for ContextError<C, E> 129 where 130 C: Display, 131 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result132 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 133 Display::fmt(&self.context, f) 134 } 135 } 136 137 impl<C, E> StdError for ContextError<C, E> 138 where 139 C: Display, 140 E: StdError + 'static, 141 { source(&self) -> Option<&(dyn StdError + 'static)>142 fn source(&self) -> Option<&(dyn StdError + 'static)> { 143 Some(&self.error) 144 } 145 146 #[cfg(error_generic_member_access)] provide<'a>(&'a self, request: &mut Request<'a>)147 fn provide<'a>(&'a self, request: &mut Request<'a>) { 148 StdError::provide(&self.error, request); 149 } 150 } 151 152 impl<C> StdError for ContextError<C, Error> 153 where 154 C: Display, 155 { source(&self) -> Option<&(dyn StdError + 'static)>156 fn source(&self) -> Option<&(dyn StdError + 'static)> { 157 Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) }) 158 } 159 160 #[cfg(error_generic_member_access)] provide<'a>(&'a self, request: &mut Request<'a>)161 fn provide<'a>(&'a self, request: &mut Request<'a>) { 162 Error::provide(&self.error, request); 163 } 164 } 165 166 struct Quoted<C>(C); 167 168 impl<C> Debug for Quoted<C> 169 where 170 C: Display, 171 { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result172 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 173 formatter.write_char('"')?; 174 Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?; 175 formatter.write_char('"')?; 176 Ok(()) 177 } 178 } 179 180 impl Write for Quoted<&mut fmt::Formatter<'_>> { write_str(&mut self, s: &str) -> fmt::Result181 fn write_str(&mut self, s: &str) -> fmt::Result { 182 Display::fmt(&s.escape_debug(), self.0) 183 } 184 } 185 186 pub(crate) mod private { 187 use super::*; 188 189 pub trait Sealed {} 190 191 impl<T, E> Sealed for Result<T, E> where E: ext::StdError {} 192 impl<T> Sealed for Option<T> {} 193 } 194