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&lt;_, [anyhow::Error][crate::Error]&gt;</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&lt;_, [anyhow::Error][crate::Error]&gt;</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}