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}