From 06826d1d79d9eaef36bb84baec23f6d23329fb8b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Mar 2022 12:46:05 -0800 Subject: [PATCH 1/5] Add ui test for writing anyhow instead of bail Currently fails: Expected test case to fail to compile, but it succeeded. --- tests/ui/must-use.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/ui/must-use.rs 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(()) +} From 1af20cc4409a6eae6f07d2d29f8c802f81684752 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Mar 2022 12:42:26 -0800 Subject: [PATCH 2/5] Add must_use to Error constructors --- src/error.rs | 3 +++ 1 file changed, 3 insertions(+) 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, From ffa919c8aa0d563cedd975d95f0ed4a697bd6e8e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Mar 2022 12:41:58 -0800 Subject: [PATCH 3/5] Add must_use to value created by anyhow! macro --- src/lib.rs | 8 ++++++++ src/macros.rs | 26 +++++++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) 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..e92a264 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -206,17 +206,21 @@ macro_rules! ensure { /// ``` #[macro_export] macro_rules! anyhow { - ($msg:literal $(,)?) => ({ - let error = $crate::private::format_err($crate::private::format_args!($msg)); - error - }); - ($err:expr $(,)?) => ({ - use $crate::private::kind::*; - let error = match $err { - error => (&error).anyhow_kind().new(error), - }; - error - }); + ($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)*)) }; From 573689b5f4c66b7b3972e6501b29cf6099afc885 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Mar 2022 12:43:49 -0800 Subject: [PATCH 4/5] Remove must_use call from ensure! and bail! expansions --- src/ensure.rs | 6 +++--- src/macros.rs | 40 +++++++++++++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 12 deletions(-) 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/macros.rs b/src/macros.rs index e92a264..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)*)); } }; } @@ -225,3 +225,25 @@ macro_rules! anyhow { $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 + }); + ($err:expr $(,)?) => ({ + 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)*)) + }; +} From cf5d619822645a4e1e8b40bccf4b13368f5eab66 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Mar 2022 12:46:24 -0800 Subject: [PATCH 5/5] Update must-use test stderr --- tests/ui/must-use.stderr | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/ui/must-use.stderr 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)