/rust/registry/src/index.crates.io-6f17d22bba15001f/anyhow-1.0.98/src/error.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::backtrace::Backtrace; |
2 | | use crate::chain::Chain; |
3 | | #[cfg(error_generic_member_access)] |
4 | | use crate::nightly::{self, Request}; |
5 | | #[cfg(any(feature = "std", not(anyhow_no_core_error), anyhow_no_ptr_addr_of))] |
6 | | use crate::ptr::Mut; |
7 | | use crate::ptr::{Own, Ref}; |
8 | | use crate::{Error, StdError}; |
9 | | use alloc::boxed::Box; |
10 | | use core::any::TypeId; |
11 | | use core::fmt::{self, Debug, Display}; |
12 | | use core::mem::ManuallyDrop; |
13 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
14 | | use core::ops::{Deref, DerefMut}; |
15 | | #[cfg(not(anyhow_no_core_unwind_safe))] |
16 | | use core::panic::{RefUnwindSafe, UnwindSafe}; |
17 | | #[cfg(not(anyhow_no_ptr_addr_of))] |
18 | | use core::ptr; |
19 | | use core::ptr::NonNull; |
20 | | #[cfg(all(feature = "std", anyhow_no_core_unwind_safe))] |
21 | | use std::panic::{RefUnwindSafe, UnwindSafe}; |
22 | | |
23 | | impl Error { |
24 | | /// Create a new error object from any error type. |
25 | | /// |
26 | | /// The error type must be threadsafe and `'static`, so that the `Error` |
27 | | /// will be as well. |
28 | | /// |
29 | | /// If the error type does not provide a backtrace, a backtrace will be |
30 | | /// created here to ensure that a backtrace exists. |
31 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
32 | | #[cold] |
33 | | #[must_use] |
34 | 0 | pub fn new<E>(error: E) -> Self |
35 | 0 | where |
36 | 0 | E: StdError + Send + Sync + 'static, |
37 | 0 | { |
38 | 0 | let backtrace = backtrace_if_absent!(&error); |
39 | 0 | Error::construct_from_std(error, backtrace) |
40 | 0 | } |
41 | | |
42 | | /// Create a new error object from a printable error message. |
43 | | /// |
44 | | /// If the argument implements std::error::Error, prefer `Error::new` |
45 | | /// instead which preserves the underlying error's cause chain and |
46 | | /// backtrace. If the argument may or may not implement std::error::Error |
47 | | /// now or in the future, use `anyhow!(err)` which handles either way |
48 | | /// correctly. |
49 | | /// |
50 | | /// `Error::msg("...")` is equivalent to `anyhow!("...")` but occasionally |
51 | | /// convenient in places where a function is preferable over a macro, such |
52 | | /// as iterator or stream combinators: |
53 | | /// |
54 | | /// ``` |
55 | | /// # mod ffi { |
56 | | /// # pub struct Input; |
57 | | /// # pub struct Output; |
58 | | /// # pub async fn do_some_work(_: Input) -> Result<Output, &'static str> { |
59 | | /// # unimplemented!() |
60 | | /// # } |
61 | | /// # } |
62 | | /// # |
63 | | /// # use ffi::{Input, Output}; |
64 | | /// # |
65 | | /// use anyhow::{Error, Result}; |
66 | | /// use futures::stream::{Stream, StreamExt, TryStreamExt}; |
67 | | /// |
68 | | /// async fn demo<S>(stream: S) -> Result<Vec<Output>> |
69 | | /// where |
70 | | /// S: Stream<Item = Input>, |
71 | | /// { |
72 | | /// stream |
73 | | /// .then(ffi::do_some_work) // returns Result<Output, &str> |
74 | | /// .map_err(Error::msg) |
75 | | /// .try_collect() |
76 | | /// .await |
77 | | /// } |
78 | | /// ``` |
79 | | #[cold] |
80 | | #[must_use] |
81 | 0 | pub fn msg<M>(message: M) -> Self |
82 | 0 | where |
83 | 0 | M: Display + Debug + Send + Sync + 'static, |
84 | 0 | { |
85 | 0 | Error::construct_from_adhoc(message, backtrace!()) |
86 | 0 | } Unexecuted instantiation: <anyhow::Error>::msg::<alloc::string::String> Unexecuted instantiation: <anyhow::Error>::msg::<&str> |
87 | | |
88 | | /// Construct an error object from a type-erased standard library error. |
89 | | /// |
90 | | /// This is mostly useful for interop with other error libraries. |
91 | | /// |
92 | | /// # Example |
93 | | /// |
94 | | /// Here is a skeleton of a library that provides its own error abstraction. |
95 | | /// The pair of `From` impls provide bidirectional support for `?` |
96 | | /// conversion between `Report` and `anyhow::Error`. |
97 | | /// |
98 | | /// ``` |
99 | | /// use std::error::Error as StdError; |
100 | | /// |
101 | | /// pub struct Report {/* ... */} |
102 | | /// |
103 | | /// impl<E> From<E> for Report |
104 | | /// where |
105 | | /// E: Into<anyhow::Error>, |
106 | | /// Result<(), E>: anyhow::Context<(), E>, |
107 | | /// { |
108 | | /// fn from(error: E) -> Self { |
109 | | /// let anyhow_error: anyhow::Error = error.into(); |
110 | | /// let boxed_error: Box<dyn StdError + Send + Sync + 'static> = anyhow_error.into(); |
111 | | /// Report::from_boxed(boxed_error) |
112 | | /// } |
113 | | /// } |
114 | | /// |
115 | | /// impl From<Report> for anyhow::Error { |
116 | | /// fn from(report: Report) -> Self { |
117 | | /// let boxed_error: Box<dyn StdError + Send + Sync + 'static> = report.into_boxed(); |
118 | | /// anyhow::Error::from_boxed(boxed_error) |
119 | | /// } |
120 | | /// } |
121 | | /// |
122 | | /// impl Report { |
123 | | /// fn from_boxed(boxed_error: Box<dyn StdError + Send + Sync + 'static>) -> Self { |
124 | | /// todo!() |
125 | | /// } |
126 | | /// fn into_boxed(self) -> Box<dyn StdError + Send + Sync + 'static> { |
127 | | /// todo!() |
128 | | /// } |
129 | | /// } |
130 | | /// |
131 | | /// // Example usage: can use `?` in both directions. |
132 | | /// fn a() -> anyhow::Result<()> { |
133 | | /// b()?; |
134 | | /// Ok(()) |
135 | | /// } |
136 | | /// fn b() -> Result<(), Report> { |
137 | | /// a()?; |
138 | | /// Ok(()) |
139 | | /// } |
140 | | /// ``` |
141 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
142 | | #[cold] |
143 | | #[must_use] |
144 | 0 | pub fn from_boxed(boxed_error: Box<dyn StdError + Send + Sync + 'static>) -> Self { |
145 | 0 | let backtrace = backtrace_if_absent!(&*boxed_error); |
146 | 0 | Error::construct_from_boxed(boxed_error, backtrace) |
147 | 0 | } |
148 | | |
149 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
150 | | #[cold] |
151 | 0 | pub(crate) fn construct_from_std<E>(error: E, backtrace: Option<Backtrace>) -> Self |
152 | 0 | where |
153 | 0 | E: StdError + Send + Sync + 'static, |
154 | 0 | { |
155 | 0 | let vtable = &ErrorVTable { |
156 | 0 | object_drop: object_drop::<E>, |
157 | 0 | object_ref: object_ref::<E>, |
158 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
159 | 0 | object_mut: object_mut::<E>, |
160 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
161 | 0 | object_boxed: object_boxed::<E>, |
162 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
163 | 0 | object_reallocate_boxed: object_reallocate_boxed::<E>, |
164 | 0 | object_downcast: object_downcast::<E>, |
165 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
166 | 0 | object_downcast_mut: object_downcast_mut::<E>, |
167 | 0 | object_drop_rest: object_drop_front::<E>, |
168 | 0 | #[cfg(all( |
169 | 0 | not(error_generic_member_access), |
170 | 0 | any(std_backtrace, feature = "backtrace") |
171 | 0 | ))] |
172 | 0 | object_backtrace: no_backtrace, |
173 | 0 | }; |
174 | 0 |
|
175 | 0 | // Safety: passing vtable that operates on the right type E. |
176 | 0 | unsafe { Error::construct(error, vtable, backtrace) } |
177 | 0 | } Unexecuted instantiation: <anyhow::Error>::construct_from_std::<std::io::error::Error> Unexecuted instantiation: <anyhow::Error>::construct_from_std::<_> |
178 | | |
179 | | #[cold] |
180 | 0 | pub(crate) fn construct_from_adhoc<M>(message: M, backtrace: Option<Backtrace>) -> Self |
181 | 0 | where |
182 | 0 | M: Display + Debug + Send + Sync + 'static, |
183 | 0 | { |
184 | | use crate::wrapper::MessageError; |
185 | 0 | let error: MessageError<M> = MessageError(message); |
186 | 0 | let vtable = &ErrorVTable { |
187 | 0 | object_drop: object_drop::<MessageError<M>>, |
188 | 0 | object_ref: object_ref::<MessageError<M>>, |
189 | 0 | #[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))] |
190 | 0 | object_mut: object_mut::<MessageError<M>>, |
191 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
192 | 0 | object_boxed: object_boxed::<MessageError<M>>, |
193 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
194 | 0 | object_reallocate_boxed: object_reallocate_boxed::<MessageError<M>>, |
195 | 0 | object_downcast: object_downcast::<M>, |
196 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
197 | 0 | object_downcast_mut: object_downcast_mut::<M>, |
198 | 0 | object_drop_rest: object_drop_front::<M>, |
199 | 0 | #[cfg(all( |
200 | 0 | not(error_generic_member_access), |
201 | 0 | any(std_backtrace, feature = "backtrace") |
202 | 0 | ))] |
203 | 0 | object_backtrace: no_backtrace, |
204 | 0 | }; |
205 | 0 |
|
206 | 0 | // Safety: MessageError is repr(transparent) so it is okay for the |
207 | 0 | // vtable to allow casting the MessageError<M> to M. |
208 | 0 | unsafe { Error::construct(error, vtable, backtrace) } |
209 | 0 | } Unexecuted instantiation: <anyhow::Error>::construct_from_adhoc::<alloc::string::String> Unexecuted instantiation: <anyhow::Error>::construct_from_adhoc::<&str> |
210 | | |
211 | | #[cold] |
212 | 0 | pub(crate) fn construct_from_display<M>(message: M, backtrace: Option<Backtrace>) -> Self |
213 | 0 | where |
214 | 0 | M: Display + Send + Sync + 'static, |
215 | 0 | { |
216 | | use crate::wrapper::DisplayError; |
217 | 0 | let error: DisplayError<M> = DisplayError(message); |
218 | 0 | let vtable = &ErrorVTable { |
219 | 0 | object_drop: object_drop::<DisplayError<M>>, |
220 | 0 | object_ref: object_ref::<DisplayError<M>>, |
221 | 0 | #[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))] |
222 | 0 | object_mut: object_mut::<DisplayError<M>>, |
223 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
224 | 0 | object_boxed: object_boxed::<DisplayError<M>>, |
225 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
226 | 0 | object_reallocate_boxed: object_reallocate_boxed::<DisplayError<M>>, |
227 | 0 | object_downcast: object_downcast::<M>, |
228 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
229 | 0 | object_downcast_mut: object_downcast_mut::<M>, |
230 | 0 | object_drop_rest: object_drop_front::<M>, |
231 | 0 | #[cfg(all( |
232 | 0 | not(error_generic_member_access), |
233 | 0 | any(std_backtrace, feature = "backtrace") |
234 | 0 | ))] |
235 | 0 | object_backtrace: no_backtrace, |
236 | 0 | }; |
237 | 0 |
|
238 | 0 | // Safety: DisplayError is repr(transparent) so it is okay for the |
239 | 0 | // vtable to allow casting the DisplayError<M> to M. |
240 | 0 | unsafe { Error::construct(error, vtable, backtrace) } |
241 | 0 | } |
242 | | |
243 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
244 | | #[cold] |
245 | 0 | pub(crate) fn construct_from_context<C, E>( |
246 | 0 | context: C, |
247 | 0 | error: E, |
248 | 0 | backtrace: Option<Backtrace>, |
249 | 0 | ) -> Self |
250 | 0 | where |
251 | 0 | C: Display + Send + Sync + 'static, |
252 | 0 | E: StdError + Send + Sync + 'static, |
253 | 0 | { |
254 | 0 | let error: ContextError<C, E> = ContextError { context, error }; |
255 | 0 |
|
256 | 0 | let vtable = &ErrorVTable { |
257 | 0 | object_drop: object_drop::<ContextError<C, E>>, |
258 | 0 | object_ref: object_ref::<ContextError<C, E>>, |
259 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
260 | 0 | object_mut: object_mut::<ContextError<C, E>>, |
261 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
262 | 0 | object_boxed: object_boxed::<ContextError<C, E>>, |
263 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
264 | 0 | object_reallocate_boxed: object_reallocate_boxed::<ContextError<C, E>>, |
265 | 0 | object_downcast: context_downcast::<C, E>, |
266 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
267 | 0 | object_downcast_mut: context_downcast_mut::<C, E>, |
268 | 0 | object_drop_rest: context_drop_rest::<C, E>, |
269 | 0 | #[cfg(all( |
270 | 0 | not(error_generic_member_access), |
271 | 0 | any(std_backtrace, feature = "backtrace") |
272 | 0 | ))] |
273 | 0 | object_backtrace: no_backtrace, |
274 | 0 | }; |
275 | 0 |
|
276 | 0 | // Safety: passing vtable that operates on the right type. |
277 | 0 | unsafe { Error::construct(error, vtable, backtrace) } |
278 | 0 | } |
279 | | |
280 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
281 | | #[cold] |
282 | 0 | pub(crate) fn construct_from_boxed( |
283 | 0 | error: Box<dyn StdError + Send + Sync>, |
284 | 0 | backtrace: Option<Backtrace>, |
285 | 0 | ) -> Self { |
286 | | use crate::wrapper::BoxedError; |
287 | 0 | let error = BoxedError(error); |
288 | 0 | let vtable = &ErrorVTable { |
289 | 0 | object_drop: object_drop::<BoxedError>, |
290 | 0 | object_ref: object_ref::<BoxedError>, |
291 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
292 | 0 | object_mut: object_mut::<BoxedError>, |
293 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
294 | 0 | object_boxed: object_boxed::<BoxedError>, |
295 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
296 | 0 | object_reallocate_boxed: object_reallocate_boxed::<BoxedError>, |
297 | 0 | object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>>, |
298 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
299 | 0 | object_downcast_mut: object_downcast_mut::<Box<dyn StdError + Send + Sync>>, |
300 | 0 | object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>>, |
301 | 0 | #[cfg(all( |
302 | 0 | not(error_generic_member_access), |
303 | 0 | any(std_backtrace, feature = "backtrace") |
304 | 0 | ))] |
305 | 0 | object_backtrace: no_backtrace, |
306 | 0 | }; |
307 | 0 |
|
308 | 0 | // Safety: BoxedError is repr(transparent) so it is okay for the vtable |
309 | 0 | // to allow casting to Box<dyn StdError + Send + Sync>. |
310 | 0 | unsafe { Error::construct(error, vtable, backtrace) } |
311 | 0 | } |
312 | | |
313 | | // Takes backtrace as argument rather than capturing it here so that the |
314 | | // user sees one fewer layer of wrapping noise in the backtrace. |
315 | | // |
316 | | // Unsafe because the given vtable must have sensible behavior on the error |
317 | | // value of type E. |
318 | | #[cold] |
319 | 0 | unsafe fn construct<E>( |
320 | 0 | error: E, |
321 | 0 | vtable: &'static ErrorVTable, |
322 | 0 | backtrace: Option<Backtrace>, |
323 | 0 | ) -> Self |
324 | 0 | where |
325 | 0 | E: StdError + Send + Sync + 'static, |
326 | 0 | { |
327 | 0 | let inner: Box<ErrorImpl<E>> = Box::new(ErrorImpl { |
328 | 0 | vtable, |
329 | 0 | backtrace, |
330 | 0 | _object: error, |
331 | 0 | }); |
332 | 0 | // Erase the concrete type of E from the compile-time type system. This |
333 | 0 | // is equivalent to the safe unsize coercion from Box<ErrorImpl<E>> to |
334 | 0 | // Box<ErrorImpl<dyn StdError + Send + Sync + 'static>> except that the |
335 | 0 | // result is a thin pointer. The necessary behavior for manipulating the |
336 | 0 | // underlying ErrorImpl<E> is preserved in the vtable provided by the |
337 | 0 | // caller rather than a builtin fat pointer vtable. |
338 | 0 | let inner = Own::new(inner).cast::<ErrorImpl>(); |
339 | 0 | Error { inner } |
340 | 0 | } Unexecuted instantiation: <anyhow::Error>::construct::<std::io::error::Error> Unexecuted instantiation: <anyhow::Error>::construct::<anyhow::wrapper::MessageError<alloc::string::String>> Unexecuted instantiation: <anyhow::Error>::construct::<anyhow::wrapper::MessageError<&str>> Unexecuted instantiation: <anyhow::Error>::construct::<anyhow::wrapper::BoxedError> |
341 | | |
342 | | /// Wrap the error value with additional context. |
343 | | /// |
344 | | /// For attaching context to a `Result` as it is propagated, the |
345 | | /// [`Context`][crate::Context] extension trait may be more convenient than |
346 | | /// this function. |
347 | | /// |
348 | | /// The primary reason to use `error.context(...)` instead of |
349 | | /// `result.context(...)` via the `Context` trait would be if the context |
350 | | /// needs to depend on some data held by the underlying error: |
351 | | /// |
352 | | /// ``` |
353 | | /// # use std::fmt::{self, Debug, Display}; |
354 | | /// # |
355 | | /// # type T = (); |
356 | | /// # |
357 | | /// # impl std::error::Error for ParseError {} |
358 | | /// # impl Debug for ParseError { |
359 | | /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
360 | | /// # unimplemented!() |
361 | | /// # } |
362 | | /// # } |
363 | | /// # impl Display for ParseError { |
364 | | /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
365 | | /// # unimplemented!() |
366 | | /// # } |
367 | | /// # } |
368 | | /// # |
369 | | /// use anyhow::Result; |
370 | | /// use std::fs::File; |
371 | | /// use std::path::Path; |
372 | | /// |
373 | | /// struct ParseError { |
374 | | /// line: usize, |
375 | | /// column: usize, |
376 | | /// } |
377 | | /// |
378 | | /// fn parse_impl(file: File) -> Result<T, ParseError> { |
379 | | /// # const IGNORE: &str = stringify! { |
380 | | /// ... |
381 | | /// # }; |
382 | | /// # unimplemented!() |
383 | | /// } |
384 | | /// |
385 | | /// pub fn parse(path: impl AsRef<Path>) -> Result<T> { |
386 | | /// let file = File::open(&path)?; |
387 | | /// parse_impl(file).map_err(|error| { |
388 | | /// let context = format!( |
389 | | /// "only the first {} lines of {} are valid", |
390 | | /// error.line, path.as_ref().display(), |
391 | | /// ); |
392 | | /// anyhow::Error::new(error).context(context) |
393 | | /// }) |
394 | | /// } |
395 | | /// ``` |
396 | | #[cold] |
397 | | #[must_use] |
398 | 0 | pub fn context<C>(self, context: C) -> Self |
399 | 0 | where |
400 | 0 | C: Display + Send + Sync + 'static, |
401 | 0 | { |
402 | 0 | let error: ContextError<C, Error> = ContextError { |
403 | 0 | context, |
404 | 0 | error: self, |
405 | 0 | }; |
406 | 0 |
|
407 | 0 | let vtable = &ErrorVTable { |
408 | 0 | object_drop: object_drop::<ContextError<C, Error>>, |
409 | 0 | object_ref: object_ref::<ContextError<C, Error>>, |
410 | 0 | #[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))] |
411 | 0 | object_mut: object_mut::<ContextError<C, Error>>, |
412 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
413 | 0 | object_boxed: object_boxed::<ContextError<C, Error>>, |
414 | 0 | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
415 | 0 | object_reallocate_boxed: object_reallocate_boxed::<ContextError<C, Error>>, |
416 | 0 | object_downcast: context_chain_downcast::<C>, |
417 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
418 | 0 | object_downcast_mut: context_chain_downcast_mut::<C>, |
419 | 0 | object_drop_rest: context_chain_drop_rest::<C>, |
420 | 0 | #[cfg(all( |
421 | 0 | not(error_generic_member_access), |
422 | 0 | any(std_backtrace, feature = "backtrace") |
423 | 0 | ))] |
424 | 0 | object_backtrace: context_backtrace::<C>, |
425 | 0 | }; |
426 | 0 |
|
427 | 0 | // As the cause is anyhow::Error, we already have a backtrace for it. |
428 | 0 | let backtrace = None; |
429 | 0 |
|
430 | 0 | // Safety: passing vtable that operates on the right type. |
431 | 0 | unsafe { Error::construct(error, vtable, backtrace) } |
432 | 0 | } |
433 | | |
434 | | /// Get the backtrace for this Error. |
435 | | /// |
436 | | /// In order for the backtrace to be meaningful, one of the two environment |
437 | | /// variables `RUST_LIB_BACKTRACE=1` or `RUST_BACKTRACE=1` must be defined |
438 | | /// and `RUST_LIB_BACKTRACE` must not be `0`. Backtraces are somewhat |
439 | | /// expensive to capture in Rust, so we don't necessarily want to be |
440 | | /// capturing them all over the place all the time. |
441 | | /// |
442 | | /// - If you want panics and errors to both have backtraces, set |
443 | | /// `RUST_BACKTRACE=1`; |
444 | | /// - If you want only errors to have backtraces, set |
445 | | /// `RUST_LIB_BACKTRACE=1`; |
446 | | /// - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and |
447 | | /// `RUST_LIB_BACKTRACE=0`. |
448 | | /// |
449 | | /// # Stability |
450 | | /// |
451 | | /// Standard library backtraces are only available when using Rust ≥ |
452 | | /// 1.65. On older compilers, this function is only available if the crate's |
453 | | /// "backtrace" feature is enabled, and will use the `backtrace` crate as |
454 | | /// the underlying backtrace implementation. The return type of this |
455 | | /// function on old compilers is `&(impl Debug + Display)`. |
456 | | /// |
457 | | /// ```toml |
458 | | /// [dependencies] |
459 | | /// anyhow = { version = "1.0", features = ["backtrace"] } |
460 | | /// ``` |
461 | | #[cfg(any(std_backtrace, feature = "backtrace"))] |
462 | 0 | pub fn backtrace(&self) -> &impl_backtrace!() { |
463 | 0 | unsafe { ErrorImpl::backtrace(self.inner.by_ref()) } |
464 | 0 | } |
465 | | |
466 | | /// An iterator of the chain of source errors contained by this Error. |
467 | | /// |
468 | | /// This iterator will visit every error in the cause chain of this error |
469 | | /// object, beginning with the error that this error object was created |
470 | | /// from. |
471 | | /// |
472 | | /// # Example |
473 | | /// |
474 | | /// ``` |
475 | | /// use anyhow::Error; |
476 | | /// use std::io; |
477 | | /// |
478 | | /// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> { |
479 | | /// for cause in error.chain() { |
480 | | /// if let Some(io_error) = cause.downcast_ref::<io::Error>() { |
481 | | /// return Some(io_error.kind()); |
482 | | /// } |
483 | | /// } |
484 | | /// None |
485 | | /// } |
486 | | /// ``` |
487 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
488 | | #[cold] |
489 | 0 | pub fn chain(&self) -> Chain { |
490 | 0 | unsafe { ErrorImpl::chain(self.inner.by_ref()) } |
491 | 0 | } |
492 | | |
493 | | /// The lowest level cause of this error — this error's cause's |
494 | | /// cause's cause etc. |
495 | | /// |
496 | | /// The root cause is the last error in the iterator produced by |
497 | | /// [`chain()`][Error::chain]. |
498 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
499 | | #[allow(clippy::double_ended_iterator_last)] |
500 | 0 | pub fn root_cause(&self) -> &(dyn StdError + 'static) { |
501 | 0 | self.chain().last().unwrap() |
502 | 0 | } |
503 | | |
504 | | /// Returns true if `E` is the type held by this error object. |
505 | | /// |
506 | | /// For errors with context, this method returns true if `E` matches the |
507 | | /// type of the context `C` **or** the type of the error on which the |
508 | | /// context has been attached. For details about the interaction between |
509 | | /// context and downcasting, [see here]. |
510 | | /// |
511 | | /// [see here]: crate::Context#effect-on-downcasting |
512 | 0 | pub fn is<E>(&self) -> bool |
513 | 0 | where |
514 | 0 | E: Display + Debug + Send + Sync + 'static, |
515 | 0 | { |
516 | 0 | self.downcast_ref::<E>().is_some() |
517 | 0 | } |
518 | | |
519 | | /// Attempt to downcast the error object to a concrete type. |
520 | 0 | pub fn downcast<E>(mut self) -> Result<E, Self> |
521 | 0 | where |
522 | 0 | E: Display + Debug + Send + Sync + 'static, |
523 | 0 | { |
524 | 0 | let target = TypeId::of::<E>(); |
525 | 0 | let inner = self.inner.by_mut(); |
526 | | unsafe { |
527 | | // Use vtable to find NonNull<()> which points to a value of type E |
528 | | // somewhere inside the data structure. |
529 | | #[cfg(not(anyhow_no_ptr_addr_of))] |
530 | 0 | let addr = match (vtable(inner.ptr).object_downcast)(inner.by_ref(), target) { |
531 | 0 | Some(addr) => addr.by_mut().extend(), |
532 | 0 | None => return Err(self), |
533 | | }; |
534 | | #[cfg(anyhow_no_ptr_addr_of)] |
535 | | let addr = match (vtable(inner.ptr).object_downcast_mut)(inner, target) { |
536 | | Some(addr) => addr.extend(), |
537 | | None => return Err(self), |
538 | | }; |
539 | | |
540 | | // Prepare to read E out of the data structure. We'll drop the rest |
541 | | // of the data structure separately so that E is not dropped. |
542 | 0 | let outer = ManuallyDrop::new(self); |
543 | 0 |
|
544 | 0 | // Read E from where the vtable found it. |
545 | 0 | let error = addr.cast::<E>().read(); |
546 | 0 |
|
547 | 0 | // Drop rest of the data structure outside of E. |
548 | 0 | (vtable(outer.inner.ptr).object_drop_rest)(outer.inner, target); |
549 | 0 |
|
550 | 0 | Ok(error) |
551 | | } |
552 | 0 | } |
553 | | |
554 | | /// Downcast this error object by reference. |
555 | | /// |
556 | | /// # Example |
557 | | /// |
558 | | /// ``` |
559 | | /// # use anyhow::anyhow; |
560 | | /// # use std::fmt::{self, Display}; |
561 | | /// # use std::task::Poll; |
562 | | /// # |
563 | | /// # #[derive(Debug)] |
564 | | /// # enum DataStoreError { |
565 | | /// # Censored(()), |
566 | | /// # } |
567 | | /// # |
568 | | /// # impl Display for DataStoreError { |
569 | | /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
570 | | /// # unimplemented!() |
571 | | /// # } |
572 | | /// # } |
573 | | /// # |
574 | | /// # impl std::error::Error for DataStoreError {} |
575 | | /// # |
576 | | /// # const REDACTED_CONTENT: () = (); |
577 | | /// # |
578 | | /// # let error = anyhow!("..."); |
579 | | /// # let root_cause = &error; |
580 | | /// # |
581 | | /// # let ret = |
582 | | /// // If the error was caused by redaction, then return a tombstone instead |
583 | | /// // of the content. |
584 | | /// match root_cause.downcast_ref::<DataStoreError>() { |
585 | | /// Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), |
586 | | /// None => Err(error), |
587 | | /// } |
588 | | /// # ; |
589 | | /// ``` |
590 | 0 | pub fn downcast_ref<E>(&self) -> Option<&E> |
591 | 0 | where |
592 | 0 | E: Display + Debug + Send + Sync + 'static, |
593 | 0 | { |
594 | 0 | let target = TypeId::of::<E>(); |
595 | | unsafe { |
596 | | // Use vtable to find NonNull<()> which points to a value of type E |
597 | | // somewhere inside the data structure. |
598 | 0 | let addr = (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?; |
599 | 0 | Some(addr.cast::<E>().deref()) |
600 | | } |
601 | 0 | } |
602 | | |
603 | | /// Downcast this error object by mutable reference. |
604 | 0 | pub fn downcast_mut<E>(&mut self) -> Option<&mut E> |
605 | 0 | where |
606 | 0 | E: Display + Debug + Send + Sync + 'static, |
607 | 0 | { |
608 | 0 | let target = TypeId::of::<E>(); |
609 | | unsafe { |
610 | | // Use vtable to find NonNull<()> which points to a value of type E |
611 | | // somewhere inside the data structure. |
612 | | |
613 | | #[cfg(not(anyhow_no_ptr_addr_of))] |
614 | 0 | let addr = |
615 | 0 | (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?.by_mut(); |
616 | 0 |
|
617 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
618 | 0 | let addr = (vtable(self.inner.ptr).object_downcast_mut)(self.inner.by_mut(), target)?; |
619 | 0 |
|
620 | 0 | Some(addr.cast::<E>().deref_mut()) |
621 | | } |
622 | 0 | } |
623 | | |
624 | | /// Convert to a standard library error trait object. |
625 | | /// |
626 | | /// This is implemented as a cheap pointer cast that does not allocate or |
627 | | /// deallocate memory. Like [`anyhow::Error::from_boxed`], it's useful for |
628 | | /// interop with other error libraries. |
629 | | /// |
630 | | /// The same conversion is also available as |
631 | | /// <code style="display:inline;white-space:normal;">impl From<anyhow::Error> |
632 | | /// for Box<dyn Error + Send + Sync + 'static></code>. |
633 | | /// |
634 | | /// If a backtrace was collected during construction of the `anyhow::Error`, |
635 | | /// that backtrace remains accessible using the standard library `Error` |
636 | | /// trait's provider API, but as a consequence, the resulting boxed error |
637 | | /// can no longer be downcast to its original underlying type. |
638 | | /// |
639 | | /// ``` |
640 | | #[cfg_attr(not(error_generic_member_access), doc = "# _ = stringify! {")] |
641 | | /// #![feature(error_generic_member_access)] |
642 | | /// |
643 | | /// use anyhow::anyhow; |
644 | | /// use std::backtrace::Backtrace; |
645 | | /// use thiserror::Error; |
646 | | /// |
647 | | /// #[derive(Error, Debug)] |
648 | | /// #[error("...")] |
649 | | /// struct MyError; |
650 | | /// |
651 | | /// let anyhow_error = anyhow!(MyError); |
652 | | /// println!("{}", anyhow_error.backtrace()); // has Backtrace |
653 | | /// assert!(anyhow_error.downcast_ref::<MyError>().is_some()); // can downcast |
654 | | /// |
655 | | /// let boxed_dyn_error = anyhow_error.into_boxed_dyn_error(); |
656 | | /// assert!(std::error::request_ref::<Backtrace>(&*boxed_dyn_error).is_some()); // has Backtrace |
657 | | /// assert!(boxed_dyn_error.downcast_ref::<MyError>().is_none()); // can no longer downcast |
658 | | #[cfg_attr(not(error_generic_member_access), doc = "# };")] |
659 | | /// ``` |
660 | | /// |
661 | | /// [`anyhow::Error::from_boxed`]: Self::from_boxed |
662 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
663 | | #[must_use] |
664 | 0 | pub fn into_boxed_dyn_error(self) -> Box<dyn StdError + Send + Sync + 'static> { |
665 | 0 | let outer = ManuallyDrop::new(self); |
666 | 0 | unsafe { |
667 | 0 | // Use vtable to attach ErrorImpl<E>'s native StdError vtable for |
668 | 0 | // the right original type E. |
669 | 0 | (vtable(outer.inner.ptr).object_boxed)(outer.inner) |
670 | 0 | } |
671 | 0 | } |
672 | | |
673 | | /// Convert to a standard library error trait object. |
674 | | /// |
675 | | /// Unlike `self.into_boxed_dyn_error()`, this method relocates the |
676 | | /// underlying error into a new allocation in order to make it downcastable |
677 | | /// to `&E` or `Box<E>` for its original underlying error type. Any |
678 | | /// backtrace collected during construction of the `anyhow::Error` is |
679 | | /// discarded. |
680 | | /// |
681 | | /// ``` |
682 | | #[cfg_attr(not(error_generic_member_access), doc = "# _ = stringify!{")] |
683 | | /// #![feature(error_generic_member_access)] |
684 | | /// |
685 | | /// use anyhow::anyhow; |
686 | | /// use std::backtrace::Backtrace; |
687 | | /// use thiserror::Error; |
688 | | /// |
689 | | /// #[derive(Error, Debug)] |
690 | | /// #[error("...")] |
691 | | /// struct MyError; |
692 | | /// |
693 | | /// let anyhow_error = anyhow!(MyError); |
694 | | /// println!("{}", anyhow_error.backtrace()); // has Backtrace |
695 | | /// assert!(anyhow_error.downcast_ref::<MyError>().is_some()); // can downcast |
696 | | /// |
697 | | /// let boxed_dyn_error = anyhow_error.reallocate_into_boxed_dyn_error_without_backtrace(); |
698 | | /// assert!(std::error::request_ref::<Backtrace>(&*boxed_dyn_error).is_none()); // Backtrace lost |
699 | | /// assert!(boxed_dyn_error.downcast_ref::<MyError>().is_some()); // can downcast to &MyError |
700 | | /// assert!(boxed_dyn_error.downcast::<MyError>().is_ok()); // can downcast to Box<MyError> |
701 | | #[cfg_attr(not(error_generic_member_access), doc = "# };")] |
702 | | /// ``` |
703 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
704 | | #[must_use] |
705 | 0 | pub fn reallocate_into_boxed_dyn_error_without_backtrace( |
706 | 0 | self, |
707 | 0 | ) -> Box<dyn StdError + Send + Sync + 'static> { |
708 | 0 | let outer = ManuallyDrop::new(self); |
709 | 0 | unsafe { |
710 | 0 | // Use vtable to attach E's native StdError vtable for the right |
711 | 0 | // original type E. |
712 | 0 | (vtable(outer.inner.ptr).object_reallocate_boxed)(outer.inner) |
713 | 0 | } |
714 | 0 | } |
715 | | |
716 | | #[cfg(error_generic_member_access)] |
717 | 0 | pub(crate) fn provide<'a>(&'a self, request: &mut Request<'a>) { |
718 | 0 | unsafe { ErrorImpl::provide(self.inner.by_ref(), request) } |
719 | 0 | } |
720 | | |
721 | | // Called by thiserror when you have `#[source] anyhow::Error`. This provide |
722 | | // implementation includes the anyhow::Error's Backtrace if any, unlike |
723 | | // deref'ing to dyn Error where the provide implementation would include |
724 | | // only the original error's Backtrace from before it got wrapped into an |
725 | | // anyhow::Error. |
726 | | #[cfg(error_generic_member_access)] |
727 | | #[doc(hidden)] |
728 | 0 | pub fn thiserror_provide<'a>(&'a self, request: &mut Request<'a>) { |
729 | 0 | Self::provide(self, request); |
730 | 0 | } |
731 | | } |
732 | | |
733 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
734 | | impl<E> From<E> for Error |
735 | | where |
736 | | E: StdError + Send + Sync + 'static, |
737 | | { |
738 | | #[cold] |
739 | 0 | fn from(error: E) -> Self { |
740 | 0 | let backtrace = backtrace_if_absent!(&error); |
741 | 0 | Error::construct_from_std(error, backtrace) |
742 | 0 | } Unexecuted instantiation: <anyhow::Error as core::convert::From<std::io::error::Error>>::from Unexecuted instantiation: <anyhow::Error as core::convert::From<_>>::from |
743 | | } |
744 | | |
745 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
746 | | impl Deref for Error { |
747 | | type Target = dyn StdError + Send + Sync + 'static; |
748 | | |
749 | 0 | fn deref(&self) -> &Self::Target { |
750 | 0 | unsafe { ErrorImpl::error(self.inner.by_ref()) } |
751 | 0 | } |
752 | | } |
753 | | |
754 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
755 | | impl DerefMut for Error { |
756 | 0 | fn deref_mut(&mut self) -> &mut Self::Target { |
757 | 0 | unsafe { ErrorImpl::error_mut(self.inner.by_mut()) } |
758 | 0 | } |
759 | | } |
760 | | |
761 | | impl Display for Error { |
762 | 0 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
763 | 0 | unsafe { ErrorImpl::display(self.inner.by_ref(), formatter) } |
764 | 0 | } |
765 | | } |
766 | | |
767 | | impl Debug for Error { |
768 | 0 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
769 | 0 | unsafe { ErrorImpl::debug(self.inner.by_ref(), formatter) } |
770 | 0 | } |
771 | | } |
772 | | |
773 | | impl Drop for Error { |
774 | 0 | fn drop(&mut self) { |
775 | 0 | unsafe { |
776 | 0 | // Invoke the vtable's drop behavior. |
777 | 0 | (vtable(self.inner.ptr).object_drop)(self.inner); |
778 | 0 | } |
779 | 0 | } |
780 | | } |
781 | | |
782 | | struct ErrorVTable { |
783 | | object_drop: unsafe fn(Own<ErrorImpl>), |
784 | | object_ref: unsafe fn(Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static>, |
785 | | #[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))] |
786 | | object_mut: unsafe fn(Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static), |
787 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
788 | | object_boxed: unsafe fn(Own<ErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static>, |
789 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
790 | | object_reallocate_boxed: unsafe fn(Own<ErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static>, |
791 | | object_downcast: unsafe fn(Ref<ErrorImpl>, TypeId) -> Option<Ref<()>>, |
792 | | #[cfg(anyhow_no_ptr_addr_of)] |
793 | | object_downcast_mut: unsafe fn(Mut<ErrorImpl>, TypeId) -> Option<Mut<()>>, |
794 | | object_drop_rest: unsafe fn(Own<ErrorImpl>, TypeId), |
795 | | #[cfg(all( |
796 | | not(error_generic_member_access), |
797 | | any(std_backtrace, feature = "backtrace") |
798 | | ))] |
799 | | object_backtrace: unsafe fn(Ref<ErrorImpl>) -> Option<&Backtrace>, |
800 | | } |
801 | | |
802 | | // Safety: requires layout of *e to match ErrorImpl<E>. |
803 | 0 | unsafe fn object_drop<E>(e: Own<ErrorImpl>) { |
804 | 0 | // Cast back to ErrorImpl<E> so that the allocator receives the correct |
805 | 0 | // Layout to deallocate the Box's memory. |
806 | 0 | let unerased_own = e.cast::<ErrorImpl<E>>(); |
807 | 0 | drop(unsafe { unerased_own.boxed() }); |
808 | 0 | } Unexecuted instantiation: anyhow::error::object_drop::<std::io::error::Error> Unexecuted instantiation: anyhow::error::object_drop::<anyhow::wrapper::MessageError<alloc::string::String>> Unexecuted instantiation: anyhow::error::object_drop::<anyhow::wrapper::MessageError<&str>> Unexecuted instantiation: anyhow::error::object_drop::<anyhow::wrapper::BoxedError> |
809 | | |
810 | | // Safety: requires layout of *e to match ErrorImpl<E>. |
811 | 0 | unsafe fn object_drop_front<E>(e: Own<ErrorImpl>, target: TypeId) { |
812 | 0 | // Drop the fields of ErrorImpl other than E as well as the Box allocation, |
813 | 0 | // without dropping E itself. This is used by downcast after doing a |
814 | 0 | // ptr::read to take ownership of the E. |
815 | 0 | let _ = target; |
816 | 0 | let unerased_own = e.cast::<ErrorImpl<ManuallyDrop<E>>>(); |
817 | 0 | drop(unsafe { unerased_own.boxed() }); |
818 | 0 | } Unexecuted instantiation: anyhow::error::object_drop_front::<std::io::error::Error> Unexecuted instantiation: anyhow::error::object_drop_front::<alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>> Unexecuted instantiation: anyhow::error::object_drop_front::<alloc::string::String> Unexecuted instantiation: anyhow::error::object_drop_front::<&str> |
819 | | |
820 | | // Safety: requires layout of *e to match ErrorImpl<E>. |
821 | 0 | unsafe fn object_ref<E>(e: Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static> |
822 | 0 | where |
823 | 0 | E: StdError + Send + Sync + 'static, |
824 | 0 | { |
825 | 0 | // Attach E's native StdError vtable onto a pointer to self._object. |
826 | 0 |
|
827 | 0 | let unerased_ref = e.cast::<ErrorImpl<E>>(); |
828 | 0 |
|
829 | 0 | #[cfg(not(anyhow_no_ptr_addr_of))] |
830 | 0 | return Ref::from_raw(unsafe { |
831 | 0 | NonNull::new_unchecked(ptr::addr_of!((*unerased_ref.as_ptr())._object) as *mut E) |
832 | 0 | }); |
833 | 0 |
|
834 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
835 | 0 | return Ref::new(unsafe { &unerased_ref.deref()._object }); |
836 | 0 | } Unexecuted instantiation: anyhow::error::object_ref::<std::io::error::Error> Unexecuted instantiation: anyhow::error::object_ref::<anyhow::wrapper::MessageError<alloc::string::String>> Unexecuted instantiation: anyhow::error::object_ref::<anyhow::wrapper::MessageError<&str>> Unexecuted instantiation: anyhow::error::object_ref::<anyhow::wrapper::BoxedError> |
837 | | |
838 | | // Safety: requires layout of *e to match ErrorImpl<E>, and for `e` to be derived |
839 | | // from a `&mut` |
840 | | #[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))] |
841 | | unsafe fn object_mut<E>(e: Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static) |
842 | | where |
843 | | E: StdError + Send + Sync + 'static, |
844 | | { |
845 | | // Attach E's native StdError vtable onto a pointer to self._object. |
846 | | let unerased_mut = e.cast::<ErrorImpl<E>>(); |
847 | | unsafe { &mut unerased_mut.deref_mut()._object } |
848 | | } |
849 | | |
850 | | // Safety: requires layout of *e to match ErrorImpl<E>. |
851 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
852 | 0 | unsafe fn object_boxed<E>(e: Own<ErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static> |
853 | 0 | where |
854 | 0 | E: StdError + Send + Sync + 'static, |
855 | 0 | { |
856 | 0 | // Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below. |
857 | 0 | let unerased_own = e.cast::<ErrorImpl<E>>(); |
858 | 0 | unsafe { unerased_own.boxed() } |
859 | 0 | } Unexecuted instantiation: anyhow::error::object_boxed::<std::io::error::Error> Unexecuted instantiation: anyhow::error::object_boxed::<anyhow::wrapper::MessageError<alloc::string::String>> Unexecuted instantiation: anyhow::error::object_boxed::<anyhow::wrapper::MessageError<&str>> Unexecuted instantiation: anyhow::error::object_boxed::<anyhow::wrapper::BoxedError> |
860 | | |
861 | | // Safety: requires layout of *e to match ErrorImpl<E>. |
862 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
863 | 0 | unsafe fn object_reallocate_boxed<E>(e: Own<ErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static> |
864 | 0 | where |
865 | 0 | E: StdError + Send + Sync + 'static, |
866 | 0 | { |
867 | 0 | // Attach E's native StdError vtable. |
868 | 0 | let unerased_own = e.cast::<ErrorImpl<E>>(); |
869 | 0 | Box::new(unsafe { unerased_own.boxed() }._object) |
870 | 0 | } Unexecuted instantiation: anyhow::error::object_reallocate_boxed::<std::io::error::Error> Unexecuted instantiation: anyhow::error::object_reallocate_boxed::<anyhow::wrapper::MessageError<alloc::string::String>> Unexecuted instantiation: anyhow::error::object_reallocate_boxed::<anyhow::wrapper::MessageError<&str>> Unexecuted instantiation: anyhow::error::object_reallocate_boxed::<anyhow::wrapper::BoxedError> |
871 | | |
872 | | // Safety: requires layout of *e to match ErrorImpl<E>. |
873 | 0 | unsafe fn object_downcast<E>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>> |
874 | 0 | where |
875 | 0 | E: 'static, |
876 | 0 | { |
877 | 0 | if TypeId::of::<E>() == target { |
878 | | // Caller is looking for an E pointer and e is ErrorImpl<E>, take a |
879 | | // pointer to its E field. |
880 | | |
881 | 0 | let unerased_ref = e.cast::<ErrorImpl<E>>(); |
882 | 0 |
|
883 | 0 | #[cfg(not(anyhow_no_ptr_addr_of))] |
884 | 0 | return Some( |
885 | 0 | Ref::from_raw(unsafe { |
886 | 0 | NonNull::new_unchecked(ptr::addr_of!((*unerased_ref.as_ptr())._object) as *mut E) |
887 | 0 | }) |
888 | 0 | .cast::<()>(), |
889 | 0 | ); |
890 | | |
891 | | #[cfg(anyhow_no_ptr_addr_of)] |
892 | | return Some(Ref::new(unsafe { &unerased_ref.deref()._object }).cast::<()>()); |
893 | | } else { |
894 | 0 | None |
895 | | } |
896 | 0 | } Unexecuted instantiation: anyhow::error::object_downcast::<std::io::error::Error> Unexecuted instantiation: anyhow::error::object_downcast::<alloc::boxed::Box<dyn core::error::Error + core::marker::Sync + core::marker::Send>> Unexecuted instantiation: anyhow::error::object_downcast::<alloc::string::String> Unexecuted instantiation: anyhow::error::object_downcast::<&str> |
897 | | |
898 | | // Safety: requires layout of *e to match ErrorImpl<E>. |
899 | | #[cfg(anyhow_no_ptr_addr_of)] |
900 | | unsafe fn object_downcast_mut<E>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>> |
901 | | where |
902 | | E: 'static, |
903 | | { |
904 | | if TypeId::of::<E>() == target { |
905 | | // Caller is looking for an E pointer and e is ErrorImpl<E>, take a |
906 | | // pointer to its E field. |
907 | | let unerased_mut = e.cast::<ErrorImpl<E>>(); |
908 | | let unerased = unsafe { unerased_mut.deref_mut() }; |
909 | | Some(Mut::new(&mut unerased._object).cast::<()>()) |
910 | | } else { |
911 | | None |
912 | | } |
913 | | } |
914 | | |
915 | | #[cfg(all( |
916 | | not(error_generic_member_access), |
917 | | any(std_backtrace, feature = "backtrace") |
918 | | ))] |
919 | | fn no_backtrace(e: Ref<ErrorImpl>) -> Option<&Backtrace> { |
920 | | let _ = e; |
921 | | None |
922 | | } |
923 | | |
924 | | // Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>. |
925 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
926 | 0 | unsafe fn context_downcast<C, E>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>> |
927 | 0 | where |
928 | 0 | C: 'static, |
929 | 0 | E: 'static, |
930 | 0 | { |
931 | 0 | if TypeId::of::<C>() == target { |
932 | 0 | let unerased_ref = e.cast::<ErrorImpl<ContextError<C, E>>>(); |
933 | 0 | let unerased = unsafe { unerased_ref.deref() }; |
934 | 0 | Some(Ref::new(&unerased._object.context).cast::<()>()) |
935 | 0 | } else if TypeId::of::<E>() == target { |
936 | 0 | let unerased_ref = e.cast::<ErrorImpl<ContextError<C, E>>>(); |
937 | 0 | let unerased = unsafe { unerased_ref.deref() }; |
938 | 0 | Some(Ref::new(&unerased._object.error).cast::<()>()) |
939 | | } else { |
940 | 0 | None |
941 | | } |
942 | 0 | } |
943 | | |
944 | | // Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>. |
945 | | #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] |
946 | | unsafe fn context_downcast_mut<C, E>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>> |
947 | | where |
948 | | C: 'static, |
949 | | E: 'static, |
950 | | { |
951 | | if TypeId::of::<C>() == target { |
952 | | let unerased_mut = e.cast::<ErrorImpl<ContextError<C, E>>>(); |
953 | | let unerased = unsafe { unerased_mut.deref_mut() }; |
954 | | Some(Mut::new(&mut unerased._object.context).cast::<()>()) |
955 | | } else if TypeId::of::<E>() == target { |
956 | | let unerased_mut = e.cast::<ErrorImpl<ContextError<C, E>>>(); |
957 | | let unerased = unsafe { unerased_mut.deref_mut() }; |
958 | | Some(Mut::new(&mut unerased._object.error).cast::<()>()) |
959 | | } else { |
960 | | None |
961 | | } |
962 | | } |
963 | | |
964 | | // Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>. |
965 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
966 | 0 | unsafe fn context_drop_rest<C, E>(e: Own<ErrorImpl>, target: TypeId) |
967 | 0 | where |
968 | 0 | C: 'static, |
969 | 0 | E: 'static, |
970 | 0 | { |
971 | 0 | // Called after downcasting by value to either the C or the E and doing a |
972 | 0 | // ptr::read to take ownership of that value. |
973 | 0 | if TypeId::of::<C>() == target { |
974 | 0 | let unerased_own = e.cast::<ErrorImpl<ContextError<ManuallyDrop<C>, E>>>(); |
975 | 0 | drop(unsafe { unerased_own.boxed() }); |
976 | 0 | } else { |
977 | 0 | let unerased_own = e.cast::<ErrorImpl<ContextError<C, ManuallyDrop<E>>>>(); |
978 | 0 | drop(unsafe { unerased_own.boxed() }); |
979 | 0 | } |
980 | 0 | } |
981 | | |
982 | | // Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>. |
983 | 0 | unsafe fn context_chain_downcast<C>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>> |
984 | 0 | where |
985 | 0 | C: 'static, |
986 | 0 | { |
987 | 0 | let unerased_ref = e.cast::<ErrorImpl<ContextError<C, Error>>>(); |
988 | 0 | let unerased = unsafe { unerased_ref.deref() }; |
989 | 0 | if TypeId::of::<C>() == target { |
990 | 0 | Some(Ref::new(&unerased._object.context).cast::<()>()) |
991 | | } else { |
992 | | // Recurse down the context chain per the inner error's vtable. |
993 | 0 | let source = &unerased._object.error; |
994 | 0 | unsafe { (vtable(source.inner.ptr).object_downcast)(source.inner.by_ref(), target) } |
995 | | } |
996 | 0 | } |
997 | | |
998 | | // Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>. |
999 | | #[cfg(anyhow_no_ptr_addr_of)] |
1000 | | unsafe fn context_chain_downcast_mut<C>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>> |
1001 | | where |
1002 | | C: 'static, |
1003 | | { |
1004 | | let unerased_mut = e.cast::<ErrorImpl<ContextError<C, Error>>>(); |
1005 | | let unerased = unsafe { unerased_mut.deref_mut() }; |
1006 | | if TypeId::of::<C>() == target { |
1007 | | Some(Mut::new(&mut unerased._object.context).cast::<()>()) |
1008 | | } else { |
1009 | | // Recurse down the context chain per the inner error's vtable. |
1010 | | let source = &mut unerased._object.error; |
1011 | | unsafe { (vtable(source.inner.ptr).object_downcast_mut)(source.inner.by_mut(), target) } |
1012 | | } |
1013 | | } |
1014 | | |
1015 | | // Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>. |
1016 | 0 | unsafe fn context_chain_drop_rest<C>(e: Own<ErrorImpl>, target: TypeId) |
1017 | 0 | where |
1018 | 0 | C: 'static, |
1019 | 0 | { |
1020 | 0 | // Called after downcasting by value to either the C or one of the causes |
1021 | 0 | // and doing a ptr::read to take ownership of that value. |
1022 | 0 | if TypeId::of::<C>() == target { |
1023 | 0 | let unerased_own = e.cast::<ErrorImpl<ContextError<ManuallyDrop<C>, Error>>>(); |
1024 | 0 | // Drop the entire rest of the data structure rooted in the next Error. |
1025 | 0 | drop(unsafe { unerased_own.boxed() }); |
1026 | 0 | } else { |
1027 | 0 | let unerased_own = e.cast::<ErrorImpl<ContextError<C, ManuallyDrop<Error>>>>(); |
1028 | 0 | let unerased = unsafe { unerased_own.boxed() }; |
1029 | 0 | // Read the Own<ErrorImpl> from the next error. |
1030 | 0 | let inner = unerased._object.error.inner; |
1031 | 0 | drop(unerased); |
1032 | 0 | let vtable = unsafe { vtable(inner.ptr) }; |
1033 | 0 | // Recursively drop the next error using the same target typeid. |
1034 | 0 | unsafe { (vtable.object_drop_rest)(inner, target) }; |
1035 | 0 | } |
1036 | 0 | } |
1037 | | |
1038 | | // Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>. |
1039 | | #[cfg(all( |
1040 | | not(error_generic_member_access), |
1041 | | any(std_backtrace, feature = "backtrace") |
1042 | | ))] |
1043 | | #[allow(clippy::unnecessary_wraps)] |
1044 | | unsafe fn context_backtrace<C>(e: Ref<ErrorImpl>) -> Option<&Backtrace> |
1045 | | where |
1046 | | C: 'static, |
1047 | | { |
1048 | | let unerased_ref = e.cast::<ErrorImpl<ContextError<C, Error>>>(); |
1049 | | let unerased = unsafe { unerased_ref.deref() }; |
1050 | | let backtrace = unsafe { ErrorImpl::backtrace(unerased._object.error.inner.by_ref()) }; |
1051 | | Some(backtrace) |
1052 | | } |
1053 | | |
1054 | | // NOTE: If working with `ErrorImpl<()>`, references should be avoided in favor |
1055 | | // of raw pointers and `NonNull`. |
1056 | | // repr C to ensure that E remains in the final position. |
1057 | | #[repr(C)] |
1058 | | pub(crate) struct ErrorImpl<E = ()> { |
1059 | | vtable: &'static ErrorVTable, |
1060 | | backtrace: Option<Backtrace>, |
1061 | | // NOTE: Don't use directly. Use only through vtable. Erased type may have |
1062 | | // different alignment. |
1063 | | _object: E, |
1064 | | } |
1065 | | |
1066 | | // Reads the vtable out of `p`. This is the same as `p.as_ref().vtable`, but |
1067 | | // avoids converting `p` into a reference. |
1068 | 0 | unsafe fn vtable(p: NonNull<ErrorImpl>) -> &'static ErrorVTable { |
1069 | 0 | // NOTE: This assumes that `ErrorVTable` is the first field of ErrorImpl. |
1070 | 0 | unsafe { *(p.as_ptr() as *const &'static ErrorVTable) } |
1071 | 0 | } |
1072 | | |
1073 | | // repr C to ensure that ContextError<C, E> has the same layout as |
1074 | | // ContextError<ManuallyDrop<C>, E> and ContextError<C, ManuallyDrop<E>>. |
1075 | | #[repr(C)] |
1076 | | pub(crate) struct ContextError<C, E> { |
1077 | | pub context: C, |
1078 | | pub error: E, |
1079 | | } |
1080 | | |
1081 | | impl<E> ErrorImpl<E> { |
1082 | 0 | fn erase(&self) -> Ref<ErrorImpl> { |
1083 | 0 | // Erase the concrete type of E but preserve the vtable in self.vtable |
1084 | 0 | // for manipulating the resulting thin pointer. This is analogous to an |
1085 | 0 | // unsize coercion. |
1086 | 0 | Ref::new(self).cast::<ErrorImpl>() |
1087 | 0 | } Unexecuted instantiation: <anyhow::error::ErrorImpl<std::io::error::Error>>::erase Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<alloc::string::String>>>::erase Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<&str>>>::erase Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::BoxedError>>::erase |
1088 | | } |
1089 | | |
1090 | | impl ErrorImpl { |
1091 | 0 | pub(crate) unsafe fn error(this: Ref<Self>) -> &(dyn StdError + Send + Sync + 'static) { |
1092 | 0 | // Use vtable to attach E's native StdError vtable for the right |
1093 | 0 | // original type E. |
1094 | 0 | unsafe { (vtable(this.ptr).object_ref)(this).deref() } |
1095 | 0 | } |
1096 | | |
1097 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
1098 | 0 | pub(crate) unsafe fn error_mut(this: Mut<Self>) -> &mut (dyn StdError + Send + Sync + 'static) { |
1099 | 0 | // Use vtable to attach E's native StdError vtable for the right |
1100 | 0 | // original type E. |
1101 | 0 |
|
1102 | 0 | #[cfg(not(anyhow_no_ptr_addr_of))] |
1103 | 0 | return unsafe { |
1104 | 0 | (vtable(this.ptr).object_ref)(this.by_ref()) |
1105 | 0 | .by_mut() |
1106 | 0 | .deref_mut() |
1107 | 0 | }; |
1108 | 0 |
|
1109 | 0 | #[cfg(anyhow_no_ptr_addr_of)] |
1110 | 0 | return unsafe { (vtable(this.ptr).object_mut)(this) }; |
1111 | 0 | } |
1112 | | |
1113 | | #[cfg(any(std_backtrace, feature = "backtrace"))] |
1114 | 0 | pub(crate) unsafe fn backtrace(this: Ref<Self>) -> &Backtrace { |
1115 | 0 | // This unwrap can only panic if the underlying error's backtrace method |
1116 | 0 | // is nondeterministic, which would only happen in maliciously |
1117 | 0 | // constructed code. |
1118 | 0 | unsafe { this.deref() } |
1119 | 0 | .backtrace |
1120 | 0 | .as_ref() |
1121 | 0 | .or_else(|| { |
1122 | 0 | #[cfg(error_generic_member_access)] |
1123 | 0 | return nightly::request_ref_backtrace(unsafe { Self::error(this) }); |
1124 | 0 | #[cfg(not(error_generic_member_access))] |
1125 | 0 | return unsafe { (vtable(this.ptr).object_backtrace)(this) }; |
1126 | 0 | }) |
1127 | 0 | .expect("backtrace capture failed") |
1128 | 0 | } |
1129 | | |
1130 | | #[cfg(error_generic_member_access)] |
1131 | 0 | unsafe fn provide<'a>(this: Ref<'a, Self>, request: &mut Request<'a>) { |
1132 | 0 | if let Some(backtrace) = unsafe { &this.deref().backtrace } { |
1133 | 0 | nightly::provide_ref_backtrace(request, backtrace); |
1134 | 0 | } |
1135 | 0 | nightly::provide(unsafe { Self::error(this) }, request); |
1136 | 0 | } |
1137 | | |
1138 | | #[cold] |
1139 | 0 | pub(crate) unsafe fn chain(this: Ref<Self>) -> Chain { |
1140 | 0 | Chain::new(unsafe { Self::error(this) }) |
1141 | 0 | } |
1142 | | } |
1143 | | |
1144 | | impl<E> StdError for ErrorImpl<E> |
1145 | | where |
1146 | | E: StdError, |
1147 | | { |
1148 | 0 | fn source(&self) -> Option<&(dyn StdError + 'static)> { |
1149 | 0 | unsafe { ErrorImpl::error(self.erase()).source() } |
1150 | 0 | } Unexecuted instantiation: <anyhow::error::ErrorImpl<std::io::error::Error> as core::error::Error>::source Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<alloc::string::String>> as core::error::Error>::source Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<&str>> as core::error::Error>::source Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::BoxedError> as core::error::Error>::source |
1151 | | |
1152 | | #[cfg(error_generic_member_access)] |
1153 | 0 | fn provide<'a>(&'a self, request: &mut Request<'a>) { |
1154 | 0 | unsafe { ErrorImpl::provide(self.erase(), request) } |
1155 | 0 | } Unexecuted instantiation: <anyhow::error::ErrorImpl<std::io::error::Error> as core::error::Error>::provide Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<alloc::string::String>> as core::error::Error>::provide Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<&str>> as core::error::Error>::provide Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::BoxedError> as core::error::Error>::provide |
1156 | | } |
1157 | | |
1158 | | impl<E> Debug for ErrorImpl<E> |
1159 | | where |
1160 | | E: Debug, |
1161 | | { |
1162 | 0 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
1163 | 0 | unsafe { ErrorImpl::debug(self.erase(), formatter) } |
1164 | 0 | } Unexecuted instantiation: <anyhow::error::ErrorImpl<std::io::error::Error> as core::fmt::Debug>::fmt Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<alloc::string::String>> as core::fmt::Debug>::fmt Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<&str>> as core::fmt::Debug>::fmt Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::BoxedError> as core::fmt::Debug>::fmt |
1165 | | } |
1166 | | |
1167 | | impl<E> Display for ErrorImpl<E> |
1168 | | where |
1169 | | E: Display, |
1170 | | { |
1171 | 0 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
1172 | 0 | unsafe { Display::fmt(ErrorImpl::error(self.erase()), formatter) } |
1173 | 0 | } Unexecuted instantiation: <anyhow::error::ErrorImpl<std::io::error::Error> as core::fmt::Display>::fmt Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<alloc::string::String>> as core::fmt::Display>::fmt Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<&str>> as core::fmt::Display>::fmt Unexecuted instantiation: <anyhow::error::ErrorImpl<anyhow::wrapper::BoxedError> as core::fmt::Display>::fmt |
1174 | | } |
1175 | | |
1176 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
1177 | | impl From<Error> for Box<dyn StdError + Send + Sync + 'static> { |
1178 | | #[cold] |
1179 | 0 | fn from(error: Error) -> Self { |
1180 | 0 | error.into_boxed_dyn_error() |
1181 | 0 | } |
1182 | | } |
1183 | | |
1184 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
1185 | | impl From<Error> for Box<dyn StdError + Send + 'static> { |
1186 | | #[cold] |
1187 | 0 | fn from(error: Error) -> Self { |
1188 | 0 | error.into_boxed_dyn_error() |
1189 | 0 | } |
1190 | | } |
1191 | | |
1192 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
1193 | | impl From<Error> for Box<dyn StdError + 'static> { |
1194 | | #[cold] |
1195 | 0 | fn from(error: Error) -> Self { |
1196 | 0 | error.into_boxed_dyn_error() |
1197 | 0 | } |
1198 | | } |
1199 | | |
1200 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
1201 | | impl AsRef<dyn StdError + Send + Sync> for Error { |
1202 | 0 | fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) { |
1203 | 0 | &**self |
1204 | 0 | } |
1205 | | } |
1206 | | |
1207 | | #[cfg(any(feature = "std", not(anyhow_no_core_error)))] |
1208 | | impl AsRef<dyn StdError> for Error { |
1209 | 0 | fn as_ref(&self) -> &(dyn StdError + 'static) { |
1210 | 0 | &**self |
1211 | 0 | } |
1212 | | } |
1213 | | |
1214 | | #[cfg(any(feature = "std", not(anyhow_no_core_unwind_safe)))] |
1215 | | impl UnwindSafe for Error {} |
1216 | | |
1217 | | #[cfg(any(feature = "std", not(anyhow_no_core_unwind_safe)))] |
1218 | | impl RefUnwindSafe for Error {} |