error_stack/
macros.rs

1/// Creates a [`Report`] from the given parameters.
2///
3/// The parameters may either be [`Error`] or a [`Report`]. The returned [`Report`] will use the
4/// the provided type as context.
5///
6/// [`Report`]: crate::Report
7/// [`Error`]: core::error::Error
8///
9/// # Examples
10///
11/// Create a [`Report`] from [`Error`]:
12///
13/// ```rust
14/// # #![expect(deprecated, reason = "`report!` is deprecated")]
15/// use std::fs;
16///
17/// use error_stack::report;
18///
19/// # fn wrapper() -> Result<(), error_stack::Report<impl core::fmt::Debug>> {
20/// match fs::read_to_string("/path/to/file") {
21///     Ok(content) => println!("file contents: {content}"),
22///     Err(err) => return Err(report!(err)),
23/// }
24/// # Ok(()) }
25/// # assert!(wrapper().unwrap_err().contains::<std::io::Error>());
26/// ```
27///
28/// ```rust
29/// # #![expect(deprecated, reason = "`report!` is deprecated")]
30/// # fn has_permission(_: &u32, _: &u32) -> bool { true }
31/// # type User = u32;
32/// # let user = 0;
33/// # type Resource = u32;
34/// # let resource = 0;
35/// use core::error::Error;
36/// use core::fmt;
37///
38/// use error_stack::report;
39///
40/// #[derive(Debug)]
41/// # #[allow(dead_code)]
42/// struct PermissionDenied(User, Resource);
43///
44/// impl fmt::Display for PermissionDenied {
45///     # #[allow(unused_variables)]
46///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
47///         # const _: &str = stringify! {
48///         ...
49///         # }; Ok(())}
50/// }
51///
52/// impl Error for PermissionDenied {}
53///
54/// if !has_permission(&user, &resource) {
55///     return Err(report!(PermissionDenied(user, resource)));
56/// }
57/// # Ok(())
58/// ```
59#[deprecated(since = "0.6.0", note = "use `IntoReport::into_report` instead")]
60#[macro_export]
61macro_rules! report {
62    ($err:expr $(,)?) => {{ $crate::IntoReport::into_report($err) }};
63}
64
65/// Creates a [`Report`] and returns it as [`Result`].
66///
67/// Shorthand for `return Err(report!(..))`.
68///
69/// [`Report`]: crate::Report
70/// [`report!(...)`]: report
71///
72/// # Examples
73///
74/// Create a [`Report`] from [`Error`]:
75///
76/// [`Error`]: core::error::Error
77///
78/// ```
79/// use std::fs;
80///
81/// use error_stack::bail;
82/// # fn wrapper() -> error_stack::Result<(), impl core::fmt::Debug> {
83/// match fs::read_to_string("/path/to/file") {
84///     Ok(content) => println!("file contents: {content}"),
85///     Err(err) => bail!(err),
86/// }
87/// # Ok(()) }
88/// # assert!(wrapper().unwrap_err().contains::<std::io::Error>());
89/// ```
90///
91/// Create a [`Report`] from [`Context`]:
92///
93/// [`Context`]: crate::Context
94///
95/// ```rust
96/// # fn has_permission(_: &u32, _: &u32) -> bool { true }
97/// # type User = u32;
98/// # let user = 0;
99/// # type Resource = u32;
100/// # let resource = 0;
101/// use core::fmt;
102///
103/// use error_stack::{bail, Context};
104///
105/// #[derive(Debug)]
106/// # #[allow(dead_code)]
107/// struct PermissionDenied(User, Resource);
108///
109/// impl fmt::Display for PermissionDenied {
110///     # #[allow(unused_variables)]
111///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
112///         # const _: &str = stringify! {
113///         ...
114///         # }; Ok(())}
115/// }
116///
117/// impl Context for PermissionDenied {}
118///
119/// if !has_permission(&user, &resource) {
120///     bail!(PermissionDenied(user, resource));
121/// }
122/// # Ok(())
123/// ```
124#[cfg(not(feature = "unstable"))]
125#[macro_export]
126macro_rules! bail {
127    ($err:expr) => {{
128        return ::core::result::Result::Err($crate::IntoReport::into_report($err));
129    }};
130}
131
132/// Creates a [`Report`] and returns it as [`Result`].
133///
134/// Shorthand for <code>return Err([report!(..)])</code>.
135///
136/// [`Report`]: crate::Report
137/// [report!(..)]: report
138///
139/// # `unstable`
140///
141/// The match arm: `[$($err:expr),+ $(,)?]` is considered unstable and can be used to construct a
142/// `Report<[C]>`.
143///
144/// # Examples
145///
146/// Create a [`Report`] from [`Error`]:
147///
148/// [`Error`]: core::error::Error
149///
150/// ```
151/// use std::fs;
152///
153/// use error_stack::bail;
154/// # fn wrapper() -> Result<(), error_stack::Report<impl core::fmt::Debug>> {
155/// match fs::read_to_string("/path/to/file") {
156///     Ok(content) => println!("file contents: {content}"),
157///     Err(err) => bail!(err),
158/// }
159/// # Ok(()) }
160/// # assert!(wrapper().unwrap_err().contains::<std::io::Error>());
161/// ```
162///
163/// Create a [`Report`] from [`Context`]:
164///
165/// [`Context`]: crate::Context
166///
167/// ```rust
168/// # fn has_permission(_: &u32, _: &u32) -> bool { true }
169/// # type User = u32;
170/// # let user = 0;
171/// # type Resource = u32;
172/// # let resource = 0;
173/// use core::error::Error;
174/// use core::fmt;
175///
176/// use error_stack::bail;
177///
178/// #[derive(Debug)]
179/// # #[allow(dead_code)]
180/// struct PermissionDenied(User, Resource);
181///
182/// impl fmt::Display for PermissionDenied {
183///     # #[allow(unused_variables)]
184///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
185///         # const _: &str = stringify! {
186///         ...
187///         # }; Ok(())
188///     }
189/// }
190///
191/// impl Error for PermissionDenied {}
192///
193/// if !has_permission(&user, &resource) {
194///     bail!(PermissionDenied(user, resource));
195/// }
196/// # Ok(())
197/// ```
198///
199/// Create a `Report<[C]>` from multiple errors (**unstable only**):
200///
201/// ```rust
202/// # fn has_permission(_: &u32, _: &u32) -> bool { true }
203/// # type User = u32;
204/// # let user = 0;
205/// # type Resource = u32;
206/// # let create_user = 0;
207/// # let create_resource = 0;
208/// use error_stack::bail;
209///
210/// #[derive(Debug)]
211/// # #[allow(dead_code)]
212/// struct PermissionDenied(User, Resource);
213///
214/// impl core::fmt::Display for PermissionDenied {
215///    # #[allow(unused_variables)]
216///     fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
217///         # const _: &str = stringify! {
218///         ...
219///         # }; Ok(())
220///     }
221/// }
222///
223/// impl core::error::Error for PermissionDenied {}
224///
225/// // You might want to look into `ReportSink` for a more incremental approach.
226/// if !has_permission(&user, &create_user) && !has_permission(&user, &create_resource) {
227///     bail![
228///         PermissionDenied(user, create_user),
229///         PermissionDenied(user, create_resource)
230///     ];
231/// }
232/// # Ok(())
233/// ```
234#[cfg(feature = "unstable")]
235#[cfg_attr(doc, doc(cfg(all())))]
236#[macro_export]
237macro_rules! bail {
238    ($err:expr) => {{
239        return ::core::result::Result::Err($crate::IntoReport::into_report($err));
240    }};
241
242    [$($err:expr),+ $(,)?] => {{
243        let mut sink = $crate::ReportSink::new();
244
245        $(
246            sink.capture($err);
247        )+
248
249        let error = match sink.finish() {
250            Ok(()) => unreachable!(),
251            Err(error) => error,
252        };
253
254        return ::core::result::Result::Err(error);
255    }};
256}
257
258/// Ensures `$cond` is met, otherwise return an error.
259///
260/// Shorthand for <code>if !$cond { [bail!(..)]) }</code>
261///
262/// [`Report`]: crate::Report
263/// [bail!(..)]: bail
264///
265/// # Examples
266///
267/// Create a [`Report`] from an [`Error`]:
268///
269/// [`Error`]: core::error::Error
270///
271/// ```rust
272/// # fn has_permission(_: &u32, _: &u32) -> bool { true }
273/// # type User = u32;
274/// # let user = 0;
275/// # type Resource = u32;
276/// # let resource = 0;
277/// use core::error::Error;
278/// use core::fmt;
279///
280/// use error_stack::ensure;
281///
282/// #[derive(Debug)]
283/// # #[allow(dead_code)]
284/// struct PermissionDenied(User, Resource);
285///
286/// impl fmt::Display for PermissionDenied {
287///     # #[allow(unused_variables)]
288///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
289///         # const _: &str = stringify! {
290///         ...
291///         # };
292///         Ok(())
293///     }
294/// }
295///
296/// impl Error for PermissionDenied {}
297///
298/// ensure!(
299///     has_permission(&user, &resource),
300///     PermissionDenied(user, resource)
301/// );
302/// # Ok(())
303/// ```
304#[macro_export]
305macro_rules! ensure {
306    ($cond:expr, $err:expr $(,)?) => {{
307        if !bool::from($cond) {
308            $crate::bail!($err)
309        }
310    }};
311}