Coverage Report

Created: 2025-06-24 06:17

/rust/registry/src/index.crates.io-6f17d22bba15001f/anyhow-1.0.75/src/kind.rs
Line
Count
Source (jump to first uncovered line)
1
// Tagged dispatch mechanism for resolving the behavior of `anyhow!($expr)`.
2
//
3
// When anyhow! is given a single expr argument to turn into anyhow::Error, we
4
// want the resulting Error to pick up the input's implementation of source()
5
// and backtrace() if it has a std::error::Error impl, otherwise require nothing
6
// more than Display and Debug.
7
//
8
// Expressed in terms of specialization, we want something like:
9
//
10
//     trait AnyhowNew {
11
//         fn new(self) -> Error;
12
//     }
13
//
14
//     impl<T> AnyhowNew for T
15
//     where
16
//         T: Display + Debug + Send + Sync + 'static,
17
//     {
18
//         default fn new(self) -> Error {
19
//             /* no std error impl */
20
//         }
21
//     }
22
//
23
//     impl<T> AnyhowNew for T
24
//     where
25
//         T: std::error::Error + Send + Sync + 'static,
26
//     {
27
//         fn new(self) -> Error {
28
//             /* use std error's source() and backtrace() */
29
//         }
30
//     }
31
//
32
// Since specialization is not stable yet, instead we rely on autoref behavior
33
// of method resolution to perform tagged dispatch. Here we have two traits
34
// AdhocKind and TraitKind that both have an anyhow_kind() method. AdhocKind is
35
// implemented whether or not the caller's type has a std error impl, while
36
// TraitKind is implemented only when a std error impl does exist. The ambiguity
37
// is resolved by AdhocKind requiring an extra autoref so that it has lower
38
// precedence.
39
//
40
// The anyhow! macro will set up the call in this form:
41
//
42
//     #[allow(unused_imports)]
43
//     use $crate::__private::{AdhocKind, TraitKind};
44
//     let error = $msg;
45
//     (&error).anyhow_kind().new(error)
46
47
use crate::Error;
48
use core::fmt::{Debug, Display};
49
50
#[cfg(feature = "std")]
51
use crate::StdError;
52
53
pub struct Adhoc;
54
55
#[doc(hidden)]
56
pub trait AdhocKind: Sized {
57
    #[inline]
58
0
    fn anyhow_kind(&self) -> Adhoc {
59
0
        Adhoc
60
0
    }
61
}
62
63
impl<T> AdhocKind for &T where T: ?Sized + Display + Debug + Send + Sync + 'static {}
64
65
impl Adhoc {
66
    #[cold]
67
0
    pub fn new<M>(self, message: M) -> Error
68
0
    where
69
0
        M: Display + Debug + Send + Sync + 'static,
70
0
    {
71
0
        Error::from_adhoc(message, backtrace!())
72
0
    }
73
}
74
75
pub struct Trait;
76
77
#[doc(hidden)]
78
pub trait TraitKind: Sized {
79
    #[inline]
80
0
    fn anyhow_kind(&self) -> Trait {
81
0
        Trait
82
0
    }
83
}
84
85
impl<E> TraitKind for E where E: Into<Error> {}
86
87
impl Trait {
88
    #[cold]
89
0
    pub fn new<E>(self, error: E) -> Error
90
0
    where
91
0
        E: Into<Error>,
92
0
    {
93
0
        error.into()
94
0
    }
95
}
96
97
#[cfg(feature = "std")]
98
pub struct Boxed;
99
100
#[cfg(feature = "std")]
101
#[doc(hidden)]
102
pub trait BoxedKind: Sized {
103
    #[inline]
104
0
    fn anyhow_kind(&self) -> Boxed {
105
0
        Boxed
106
0
    }
107
}
108
109
#[cfg(feature = "std")]
110
impl BoxedKind for Box<dyn StdError + Send + Sync> {}
111
112
#[cfg(feature = "std")]
113
impl Boxed {
114
    #[cold]
115
0
    pub fn new(self, error: Box<dyn StdError + Send + Sync>) -> Error {
116
0
        let backtrace = backtrace_if_absent!(&*error);
117
0
        Error::from_boxed(error, backtrace)
118
0
    }
119
}