anyhow/macros.rs
1/// Return early with an error.
2///
3/// This macro is equivalent to
4/// <code>return Err([anyhow!($args\...)][anyhow!])</code>.
5///
6/// The surrounding function's or closure's return value is required to be
7/// <code>Result<_, [anyhow::Error][crate::Error]></code>.
8///
9/// [anyhow!]: crate::anyhow
10///
11/// # Example
12///
13/// ```
14/// # use anyhow::{bail, Result};
15/// #
16/// # fn has_permission(user: usize, resource: usize) -> bool {
17/// # true
18/// # }
19/// #
20/// # fn main() -> Result<()> {
21/// # let user = 0;
22/// # let resource = 0;
23/// #
24/// if !has_permission(user, resource) {
25/// bail!("permission denied for accessing {}", resource);
26/// }
27/// # Ok(())
28/// # }
29/// ```
30///
31/// ```
32/// # use anyhow::{bail, Result};
33/// # use thiserror::Error;
34/// #
35/// # const MAX_DEPTH: usize = 1;
36/// #
37/// #[derive(Error, Debug)]
38/// enum ScienceError {
39/// #[error("recursion limit exceeded")]
40/// RecursionLimitExceeded,
41/// # #[error("...")]
42/// # More = (stringify! {
43/// ...
44/// # }, 1).1,
45/// }
46///
47/// # fn main() -> Result<()> {
48/// # let depth = 0;
49/// #
50/// if depth > MAX_DEPTH {
51/// bail!(ScienceError::RecursionLimitExceeded);
52/// }
53/// # Ok(())
54/// # }
55/// ```
56#[macro_export]
57#[cfg_attr(not(anyhow_no_clippy_format_args), clippy::format_args)]
58macro_rules! bail {
59 ($msg:literal $(,)?) => {
60 return $crate::__private::Err($crate::__anyhow!($msg))
61 };
62 ($err:expr $(,)?) => {
63 return $crate::__private::Err($crate::__anyhow!($err))
64 };
65 ($fmt:expr, $($arg:tt)*) => {
66 return $crate::__private::Err($crate::__anyhow!($fmt, $($arg)*))
67 };
68}
69
70macro_rules! __ensure {
71 ($ensure:item) => {
72 /// Return early with an error if a condition is not satisfied.
73 ///
74 /// This macro is equivalent to
75 /// <code>if !$cond { return Err([anyhow!($args\...)][anyhow!]); }</code>.
76 ///
77 /// The surrounding function's or closure's return value is required to be
78 /// <code>Result<_, [anyhow::Error][crate::Error]></code>.
79 ///
80 /// Analogously to `assert!`, `ensure!` takes a condition and exits the function
81 /// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
82 /// rather than panicking.
83 ///
84 /// [anyhow!]: crate::anyhow
85 ///
86 /// # Example
87 ///
88 /// ```
89 /// # use anyhow::{ensure, Result};
90 /// #
91 /// # fn main() -> Result<()> {
92 /// # let user = 0;
93 /// #
94 /// ensure!(user == 0, "only user 0 is allowed");
95 /// # Ok(())
96 /// # }
97 /// ```
98 ///
99 /// ```
100 /// # use anyhow::{ensure, Result};
101 /// # use thiserror::Error;
102 /// #
103 /// # const MAX_DEPTH: usize = 1;
104 /// #
105 /// #[derive(Error, Debug)]
106 /// enum ScienceError {
107 /// #[error("recursion limit exceeded")]
108 /// RecursionLimitExceeded,
109 /// # #[error("...")]
110 /// # More = (stringify! {
111 /// ...
112 /// # }, 1).1,
113 /// }
114 ///
115 /// # fn main() -> Result<()> {
116 /// # let depth = 0;
117 /// #
118 /// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
119 /// # Ok(())
120 /// # }
121 /// ```
122 $ensure
123 };
124}
125
126#[cfg(doc)]
127__ensure![
128 #[macro_export]
129 macro_rules! ensure {
130 ($cond:expr $(,)?) => {
131 if !$cond {
132 return $crate::__private::Err($crate::Error::msg(
133 $crate::__private::concat!("Condition failed: `", $crate::__private::stringify!($cond), "`")
134 ));
135 }
136 };
137 ($cond:expr, $msg:literal $(,)?) => {
138 if !$cond {
139 return $crate::__private::Err($crate::__anyhow!($msg));
140 }
141 };
142 ($cond:expr, $err:expr $(,)?) => {
143 if !$cond {
144 return $crate::__private::Err($crate::__anyhow!($err));
145 }
146 };
147 ($cond:expr, $fmt:expr, $($arg:tt)*) => {
148 if !$cond {
149 return $crate::__private::Err($crate::__anyhow!($fmt, $($arg)*));
150 }
151 };
152 }
153];
154
155#[cfg(not(doc))]
156__ensure![
157 #[macro_export]
158 #[cfg_attr(not(anyhow_no_clippy_format_args), clippy::format_args)]
159 macro_rules! ensure {
160 ($($tt:tt)*) => {
161 $crate::__parse_ensure!(
162 /* state */ 0
163 /* stack */ ()
164 /* bail */ ($($tt)*)
165 /* fuel */ (~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~)
166 /* parse */ {()}
167 /* dup */ ($($tt)*)
168 /* rest */ $($tt)*
169 )
170 };
171 }
172];
173
174/// Construct an ad-hoc error from a string or existing non-`anyhow` error
175/// value.
176///
177/// This evaluates to an [`Error`][crate::Error]. It can take either just a
178/// string, or a format string with arguments. It also can take any custom type
179/// which implements `Debug` and `Display`.
180///
181/// If called with a single argument whose type implements `std::error::Error`
182/// (in addition to `Debug` and `Display`, which are always required), then that
183/// Error impl's `source` is preserved as the `source` of the resulting
184/// `anyhow::Error`.
185///
186/// # Example
187///
188/// ```
189/// # type V = ();
190/// #
191/// use anyhow::{anyhow, Result};
192///
193/// fn lookup(key: &str) -> Result<V> {
194/// if key.len() != 16 {
195/// return Err(anyhow!("key length must be 16 characters, got {:?}", key));
196/// }
197///
198/// // ...
199/// # Ok(())
200/// }
201/// ```
202#[macro_export]
203#[cfg_attr(not(anyhow_no_clippy_format_args), clippy::format_args)]
204macro_rules! anyhow {
205 ($msg:literal $(,)?) => {
206 $crate::__private::must_use({
207 let error = $crate::__private::format_err($crate::__private::format_args!($msg));
208 error
209 })
210 };
211 ($err:expr $(,)?) => {
212 $crate::__private::must_use({
213 use $crate::__private::kind::*;
214 let error = match $err {
215 error => (&error).anyhow_kind().new(error),
216 };
217 error
218 })
219 };
220 ($fmt:expr, $($arg:tt)*) => {
221 $crate::Error::msg($crate::__private::format!($fmt, $($arg)*))
222 };
223}
224
225// Not public API. This is used in the implementation of some of the other
226// macros, in which the must_use call is not needed because the value is known
227// to be used.
228#[doc(hidden)]
229#[macro_export]
230macro_rules! __anyhow {
231 ($msg:literal $(,)?) => ({
232 let error = $crate::__private::format_err($crate::__private::format_args!($msg));
233 error
234 });
235 ($err:expr $(,)?) => ({
236 use $crate::__private::kind::*;
237 let error = match $err {
238 error => (&error).anyhow_kind().new(error),
239 };
240 error
241 });
242 ($fmt:expr, $($arg:tt)*) => {
243 $crate::Error::msg($crate::__private::format!($fmt, $($arg)*))
244 };
245}