diff --git a/src/ensure.rs b/src/ensure.rs index 96a810a..80bdab7 100644 --- a/src/ensure.rs +++ b/src/ensure.rs @@ -818,17 +818,17 @@ macro_rules! __fallback_ensure { }; ($cond:expr, $msg:literal $(,)?) => { if !$cond { - return $crate::private::Err($crate::anyhow!($msg)); + return $crate::private::Err($crate::__anyhow!($msg)); } }; ($cond:expr, $err:expr $(,)?) => { if !$cond { - return $crate::private::Err($crate::anyhow!($err)); + return $crate::private::Err($crate::__anyhow!($err)); } }; ($cond:expr, $fmt:expr, $($arg:tt)*) => { if !$cond { - return $crate::private::Err($crate::anyhow!($fmt, $($arg)*)); + return $crate::private::Err($crate::__anyhow!($fmt, $($arg)*)); } }; } diff --git a/src/error.rs b/src/error.rs index 441b61c..0971146 100644 --- a/src/error.rs +++ b/src/error.rs @@ -26,6 +26,7 @@ impl Error { #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] #[cold] + #[must_use] pub fn new(error: E) -> Self where E: StdError + Send + Sync + 'static, @@ -72,6 +73,7 @@ impl Error { /// } /// ``` #[cold] + #[must_use] pub fn msg(message: M) -> Self where M: Display + Debug + Send + Sync + 'static, @@ -293,6 +295,7 @@ impl Error { /// } /// ``` #[cold] + #[must_use] pub fn context(self, context: C) -> Self where C: Display + Send + Sync + 'static, diff --git a/src/lib.rs b/src/lib.rs index 0cb1ed6..b595300 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -668,4 +668,12 @@ pub mod private { Error::msg(fmt::format(args)) } } + + #[doc(hidden)] + #[inline] + #[cold] + #[must_use] + pub fn must_use(error: Error) -> Error { + error + } } diff --git a/src/macros.rs b/src/macros.rs index 89dc4d2..bbd61d4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -54,13 +54,13 @@ #[macro_export] macro_rules! bail { ($msg:literal $(,)?) => { - return $crate::private::Err($crate::anyhow!($msg)) + return $crate::private::Err($crate::__anyhow!($msg)) }; ($err:expr $(,)?) => { - return $crate::private::Err($crate::anyhow!($err)) + return $crate::private::Err($crate::__anyhow!($err)) }; ($fmt:expr, $($arg:tt)*) => { - return $crate::private::Err($crate::anyhow!($fmt, $($arg)*)) + return $crate::private::Err($crate::__anyhow!($fmt, $($arg)*)) }; } @@ -75,13 +75,13 @@ macro_rules! bail { return $crate::private::Err($crate::Error::msg("pattern does not contain `{}`")) }; ($msg:literal $(,)?) => { - return $crate::private::Err($crate::anyhow!($msg)) + return $crate::private::Err($crate::__anyhow!($msg)) }; ($err:expr $(,)?) => { - return $crate::private::Err($crate::anyhow!($err)) + return $crate::private::Err($crate::__anyhow!($err)) }; ($fmt:expr, $($arg:tt)*) => { - return $crate::private::Err($crate::anyhow!($fmt, $($arg)*)) + return $crate::private::Err($crate::__anyhow!($fmt, $($arg)*)) }; } @@ -145,17 +145,17 @@ macro_rules! ensure { }; ($cond:expr, $msg:literal $(,)?) => { if !$cond { - return $crate::private::Err($crate::anyhow!($msg)); + return $crate::private::Err($crate::__anyhow!($msg)); } }; ($cond:expr, $err:expr $(,)?) => { if !$cond { - return $crate::private::Err($crate::anyhow!($err)); + return $crate::private::Err($crate::__anyhow!($err)); } }; ($cond:expr, $fmt:expr, $($arg:tt)*) => { if !$cond { - return $crate::private::Err($crate::anyhow!($fmt, $($arg)*)); + return $crate::private::Err($crate::__anyhow!($fmt, $($arg)*)); } }; } @@ -206,6 +206,32 @@ macro_rules! ensure { /// ``` #[macro_export] macro_rules! anyhow { + ($msg:literal $(,)?) => { + $crate::private::must_use({ + let error = $crate::private::format_err($crate::private::format_args!($msg)); + error + }) + }; + ($err:expr $(,)?) => { + $crate::private::must_use({ + use $crate::private::kind::*; + let error = match $err { + error => (&error).anyhow_kind().new(error), + }; + error + }) + }; + ($fmt:expr, $($arg:tt)*) => { + $crate::Error::msg($crate::private::format!($fmt, $($arg)*)) + }; +} + +// Not public API. This is used in the implementation of some of the other +// macros, in which the must_use call is not needed because the value is known +// to be used. +#[doc(hidden)] +#[macro_export] +macro_rules! __anyhow { ($msg:literal $(,)?) => ({ let error = $crate::private::format_err($crate::private::format_args!($msg)); error diff --git a/tests/ui/must-use.rs b/tests/ui/must-use.rs new file mode 100644 index 0000000..ea4e58f --- /dev/null +++ b/tests/ui/must-use.rs @@ -0,0 +1,11 @@ +#![deny(unused_must_use)] + +use anyhow::anyhow; + +fn main() -> anyhow::Result<()> { + if true { + // meant to write bail! + anyhow!("it failed"); + } + Ok(()) +} diff --git a/tests/ui/must-use.stderr b/tests/ui/must-use.stderr new file mode 100644 index 0000000..a11a808 --- /dev/null +++ b/tests/ui/must-use.stderr @@ -0,0 +1,12 @@ +error: unused return value of `must_use` that must be used + --> tests/ui/must-use.rs:8:9 + | +8 | anyhow!("it failed"); + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/must-use.rs:1:9 + | +1 | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + = note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info)