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