#[doc(hidden)]
pub mod __private {
mod specialization {
#![allow(clippy::unused_self)]
pub trait ReportTag {
#[inline]
fn __kind(&self) -> Reporter {
Reporter
}
}
impl<T> ReportTag for Report<T> {}
pub trait ContextTag {
#[inline]
fn __kind(&self) -> ContextReporter {
ContextReporter
}
}
impl<T> ContextTag for &T where T: ?Sized + Context {}
use crate::{Context, Report};
pub struct Reporter;
impl Reporter {
#[inline]
pub const fn report<T>(self, report: Report<T>) -> Report<T> {
report
}
}
pub struct ContextReporter;
impl ContextReporter {
#[inline]
#[track_caller]
pub fn report<C: Context>(self, context: C) -> Report<C> {
Report::new(context)
}
}
}
pub use self::specialization::{ContextTag as _, ReportTag as _};
}
#[macro_export]
macro_rules! report {
($err:expr $(,)?) => {{
use $crate::__private::*;
let error = $err;
(&error).__kind().report(error)
}};
}
#[macro_export]
macro_rules! bail {
($err:expr $(,)?) => {{ return $crate::Result::Err($crate::report!($err)) }};
}
#[macro_export]
macro_rules! ensure {
($cond:expr, $err:expr $(,)?) => {{
if !$cond {
$crate::bail!($err)
}
}};
}
#[cfg(test)]
mod tests {
#[allow(clippy::wildcard_imports)]
use crate::test_helper::*;
#[test]
fn report() {
let err = capture_error(|| Err(report!(ContextA)));
let err = err.attach_printable("additional message");
assert!(err.contains::<ContextA>());
assert_eq!(err.current_context(), &ContextA);
assert_eq!(err.frames().count(), 2);
assert_eq!(messages(&err), ["additional message", "Context A"]);
let err = capture_error(|| Err(report!(err)));
let err = err.attach_printable(ContextB);
assert!(err.contains::<ContextA>());
assert_eq!(err.current_context(), &ContextA);
assert!(err.contains::<ContextB>());
assert_eq!(err.current_context(), &ContextA);
#[cfg(nightly)]
assert!(err.request_ref::<ContextB>().next().is_some());
assert_eq!(err.frames().count(), 3);
assert_eq!(messages(&err), [
"Context B",
"additional message",
"Context A"
]);
#[cfg(feature = "std")]
{
let err = capture_error(|| Err(report!(ContextB)));
let err = err.attach_printable("additional message");
assert_eq!(err.current_context(), &ContextB);
assert!(err.contains::<ContextB>());
assert_eq!(err.frames().count(), 2);
assert_eq!(messages(&err), ["additional message", "Context B"]);
}
}
#[test]
fn bail() {
let err = capture_error(|| bail!(ContextA));
let err = err.attach_printable("additional message");
assert!(err.contains::<ContextA>());
assert_eq!(err.frames().count(), 2);
assert_eq!(messages(&err), ["additional message", "Context A"]);
let err = capture_error(|| bail!(err));
assert!(err.contains::<ContextA>());
assert_eq!(err.frames().count(), 2);
assert_eq!(messages(&err), ["additional message", "Context A"]);
#[cfg(feature = "std")]
{
let err = capture_error(|| bail!(ContextB));
let err = err.attach_printable("additional message");
assert!(err.contains::<ContextB>());
assert_eq!(err.frames().count(), 2);
assert_eq!(messages(&err), ["additional message", "Context B"]);
}
}
#[test]
fn ensure() {
let err = capture_error(|| {
ensure!(false, ContextA);
Ok(())
});
let err = err.attach_printable("additional message");
assert!(err.contains::<ContextA>());
assert_eq!(err.frames().count(), 2);
assert_eq!(messages(&err), ["additional message", "Context A"]);
let err = capture_error(|| {
ensure!(false, err);
Ok(())
});
assert!(err.contains::<ContextA>());
assert_eq!(err.frames().count(), 2);
assert_eq!(messages(&err), ["additional message", "Context A"]);
#[cfg(feature = "std")]
{
let err = capture_error(|| {
ensure!(false, ContextB);
Ok(())
});
let err = err.attach_printable("additional message");
assert!(err.contains::<ContextB>());
assert_eq!(err.frames().count(), 2);
assert_eq!(messages(&err), ["additional message", "Context B"]);
}
}
}