Skip to main content

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        $crate::ensure!($cond, concat!("Condition failed: `", stringify!($cond), "`"))
112    };
113    ($cond:expr, $msg:literal $(,)?) => {
114        if !$cond {
115            return $crate::private::Err($crate::eyre!($msg));
116        }
117    };
118    ($cond:expr, $err:expr $(,)?) => {
119        if !$cond {
120            return $crate::private::Err($crate::eyre!($err));
121        }
122    };
123    ($cond:expr, $fmt:expr, $($arg:tt)*) => {
124        if !$cond {
125            return $crate::private::Err($crate::eyre!($fmt, $($arg)*));
126        }
127    };
128}
129
130/// Construct an ad-hoc error from a string.
131///
132/// This evaluates to a `Report`. It can take either just a string, or a format
133/// string with arguments. It also can take any custom type which implements
134/// `Debug` and `Display`.
135///
136/// # Example
137///
138/// ```
139/// # type V = ();
140/// #
141/// use eyre::{eyre, Result};
142///
143/// fn lookup(key: &str) -> Result<V> {
144///     if key.len() != 16 {
145///         return Err(eyre!("key length must be 16 characters, got {:?}", key));
146///     }
147///
148///     // ...
149///     # Ok(())
150/// }
151/// ```
152#[macro_export]
153macro_rules! eyre {
154    ($msg:literal $(,)?) => ({
155        let error = $crate::private::format_err($crate::private::format_args!($msg));
156        error
157    });
158    ($err:expr $(,)?) => ({
159        use $crate::private::kind::*;
160        let error = match $err {
161            error => (&error).eyre_kind().new(error),
162        };
163        error
164    });
165    ($fmt:expr, $($arg:tt)*) => {
166        $crate::private::new_adhoc($crate::private::format!($fmt, $($arg)*))
167    };
168}