diff --git a/build.rs b/build.rs index a12b550..cd79927 100644 --- a/build.rs +++ b/build.rs @@ -58,6 +58,10 @@ fn main() { if rustc < 51 { println!("cargo:rustc-cfg=anyhow_no_ptr_addr_of"); } + + if rustc < 52 { + println!("cargo:rustc-cfg=anyhow_no_fmt_arguments_as_str"); + } } fn compile_probe() -> Option { diff --git a/src/lib.rs b/src/lib.rs index c19d704..b227eef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -604,9 +604,13 @@ pub trait Context: context::private::Sealed { // Not public API. Referenced by macro-generated code. #[doc(hidden)] pub mod private { + use crate::Error; + use alloc::fmt; + use core::fmt::{Arguments, Debug, Display}; + pub use alloc::format; pub use core::result::Result::Err; - pub use core::{concat, stringify}; + pub use core::{concat, format_args, stringify}; #[doc(hidden)] pub mod kind { @@ -615,4 +619,24 @@ pub mod private { #[cfg(feature = "std")] pub use crate::kind::BoxedKind; } + + #[doc(hidden)] + #[cold] + pub fn format_err(message: M, args: Arguments) -> Error + where + M: Display + Debug + Send + Sync + 'static, + { + #[cfg(anyhow_no_fmt_arguments_as_str)] + let has_interpolated_format_args = false; + #[cfg(not(anyhow_no_fmt_arguments_as_str))] + let has_interpolated_format_args = args.as_str().is_none(); + + if has_interpolated_format_args { + // anyhow!("interpolate {var}"), can downcast to String + Error::msg(fmt::format(args)) + } else { + // anyhow!("literal"), can downcast to &'static str + Error::msg(message) + } + } } diff --git a/src/macros.rs b/src/macros.rs index 495caa9..91e433b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -168,9 +168,7 @@ macro_rules! ensure { #[macro_export] macro_rules! anyhow { ($msg:literal $(,)?) => { - // Handle $:literal as a special case to make cargo-expanded code more - // concise in the common case. - $crate::Error::msg($msg) + $crate::private::format_err($msg, $crate::private::format_args!($msg)) }; ($err:expr $(,)?) => ({ use $crate::private::kind::*;