eyre/
macros.rs

1/// Return early with an error.
2///
3/// This macro is equivalent to `return Err(eyre!(<args>))`.
4///
5/// # Example
6///
7/// ```
8/// # use eyre::{bail, Result};
9/// #
10/// # fn has_permission(user: usize, resource: usize) -> bool {
11/// #     true
12/// # }
13/// #
14/// # fn main() -> Result<()> {
15/// #     let user = 0;
16/// #     let resource = 0;
17/// #
18/// if !has_permission(user, resource) {
19///     bail!("permission denied for accessing {}", resource);
20/// }
21/// #     Ok(())
22/// # }
23/// ```
24///
25/// ```
26/// # use eyre::{bail, Result};
27/// # use thiserror::Error;
28/// #
29/// # const MAX_DEPTH: usize = 1;
30/// #
31/// #[derive(Error, Debug)]
32/// enum ScienceError {
33///     #[error("recursion limit exceeded")]
34///     RecursionLimitExceeded,
35///     # #[error("...")]
36///     # More = (stringify! {
37///     ...
38///     # }, 1).1,
39/// }
40///
41/// # fn main() -> Result<()> {
42/// #     let depth = 0;
43/// #     let err: &'static dyn std::error::Error = &ScienceError::RecursionLimitExceeded;
44/// #
45/// if depth > MAX_DEPTH {
46///     bail!(ScienceError::RecursionLimitExceeded);
47/// }
48/// #     Ok(())
49/// # }
50/// ```
51#[macro_export]
52macro_rules! bail {
53    ($msg:literal $(,)?) => {
54        return $crate::private::Err($crate::eyre!($msg));
55    };
56    ($err:expr $(,)?) => {
57        return $crate::private::Err($crate::eyre!($err));
58    };
59    ($fmt:expr, $($arg:tt)*) => {
60        return $crate::private::Err($crate::eyre!($fmt, $($arg)*));
61    };
62}
63
64/// Return early with an error if a condition is not satisfied.
65///
66/// This macro is equivalent to `if !$cond { return Err(eyre!(<other args>)); }`.
67///
68/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
69/// if the condition fails. Unlike `assert!`, `ensure!` returns an `eyre::Result`
70/// rather than panicking.
71///
72/// # Example
73///
74/// ```
75/// # use eyre::{ensure, Result};
76/// #
77/// # fn main() -> Result<()> {
78/// #     let user = 0;
79/// #
80/// ensure!(user == 0, "only user 0 is allowed");
81/// #     Ok(())
82/// # }
83/// ```
84///
85/// ```
86/// # use eyre::{ensure, Result};
87/// # use thiserror::Error;
88/// #
89/// # const MAX_DEPTH: usize = 1;
90/// #
91/// #[derive(Error, Debug)]
92/// enum ScienceError {
93///     #[error("recursion limit exceeded")]
94///     RecursionLimitExceeded,
95///     # #[error("...")]
96///     # More = (stringify! {
97///     ...
98///     # }, 1).1,
99/// }
100///
101/// # fn main() -> Result<()> {
102/// #     let depth = 0;
103/// #
104/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
105/// #     Ok(())
106/// # }
107/// ```
108#[macro_export]
109macro_rules! ensure {
110    ($cond:expr $(,)?) => {
111        if !$cond {
112            $crate::ensure!($cond, concat!("Condition failed: `", stringify!($cond), "`"))
113        }
114    };
115    ($cond:expr, $msg:literal $(,)?) => {
116        if !$cond {
117            return $crate::private::Err($crate::eyre!($msg));
118        }
119    };
120    ($cond:expr, $err:expr $(,)?) => {
121        if !$cond {
122            return $crate::private::Err($crate::eyre!($err));
123        }
124    };
125    ($cond:expr, $fmt:expr, $($arg:tt)*) => {
126        if !$cond {
127            return $crate::private::Err($crate::eyre!($fmt, $($arg)*));
128        }
129    };
130}
131
132/// Construct an ad-hoc error from a string.
133///
134/// This evaluates to a `Report`. It can take either just a string, or a format
135/// string with arguments. It also can take any custom type which implements
136/// `Debug` and `Display`.
137///
138/// # Example
139///
140/// ```
141/// # type V = ();
142/// #
143/// use eyre::{eyre, Result};
144///
145/// fn lookup(key: &str) -> Result<V> {
146///     if key.len() != 16 {
147///         return Err(eyre!("key length must be 16 characters, got {:?}", key));
148///     }
149///
150///     // ...
151///     # Ok(())
152/// }
153/// ```
154#[macro_export]
155macro_rules! eyre {
156    ($msg:literal $(,)?) => ({
157        let error = $crate::private::format_err($crate::private::format_args!($msg));
158        error
159    });
160    ($err:expr $(,)?) => ({
161        use $crate::private::kind::*;
162        let error = match $err {
163            error => (&error).eyre_kind().new(error),
164        };
165        error
166    });
167    ($fmt:expr, $($arg:tt)*) => {
168        $crate::private::new_adhoc($crate::private::format!($fmt, $($arg)*))
169    };
170}