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}