From 50a726b6470bdd939528a9788434e0eafd0b3348 Mon Sep 17 00:00:00 2001 From: Lily Ballard Date: Mon, 11 Apr 2022 15:42:00 -0700 Subject: [PATCH] core: impl `Value` for `dyn Error + Send/Sync` (#2066) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Motivation `Value` was already implemented for `dyn Error + 'static`, but rust doesn't silently coerce trait objects. This means that passing an error of type `dyn Error + Send + Sync + 'static` would not work. This is related to #1308. ## Solution Add impls for `dyn Error + …` variants for `Send`, `Sync`, and `Send + Sync`. These extra impls just delegate to the existing `dyn Error + 'static` impl. Also update one of the examples to use `dyn Error + Send + Sync` to demonstrate that this works. Refs: #1308 --- examples/examples/fmt/yak_shave.rs | 2 +- tracing-core/src/field.rs | 33 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/examples/examples/fmt/yak_shave.rs b/examples/examples/fmt/yak_shave.rs index 9f6eb477b3..0c2ff87641 100644 --- a/examples/examples/fmt/yak_shave.rs +++ b/examples/examples/fmt/yak_shave.rs @@ -7,7 +7,7 @@ use tracing::{debug, error, info, span, trace, warn, Level}; // every time the instrumented function is called. The span is named after the // the function or method. Paramaters passed to the function are recorded as fields. #[tracing::instrument] -pub fn shave(yak: usize) -> Result<(), Box> { +pub fn shave(yak: usize) -> Result<(), Box> { // this creates an event at the TRACE log level with two fields: // - `excitement`, with the key "excitement" and the value "yay!" // - `message`, with the key "message" and the value "hello! I'm gonna shave a yak." diff --git a/tracing-core/src/field.rs b/tracing-core/src/field.rs index b621a94ae5..000f2822e7 100644 --- a/tracing-core/src/field.rs +++ b/tracing-core/src/field.rs @@ -523,6 +523,39 @@ impl Value for dyn std::error::Error + 'static { } } +#[cfg(feature = "std")] +impl crate::sealed::Sealed for dyn std::error::Error + Send + 'static {} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl Value for dyn std::error::Error + Send + 'static { + fn record(&self, key: &Field, visitor: &mut dyn Visit) { + (self as &dyn std::error::Error).record(key, visitor) + } +} + +#[cfg(feature = "std")] +impl crate::sealed::Sealed for dyn std::error::Error + Sync + 'static {} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl Value for dyn std::error::Error + Sync + 'static { + fn record(&self, key: &Field, visitor: &mut dyn Visit) { + (self as &dyn std::error::Error).record(key, visitor) + } +} + +#[cfg(feature = "std")] +impl crate::sealed::Sealed for dyn std::error::Error + Send + Sync + 'static {} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl Value for dyn std::error::Error + Send + Sync + 'static { + fn record(&self, key: &Field, visitor: &mut dyn Visit) { + (self as &dyn std::error::Error).record(key, visitor) + } +} + impl<'a, T: ?Sized> crate::sealed::Sealed for &'a T where T: Value + crate::sealed::Sealed + 'a {} impl<'a, T: ?Sized> Value for &'a T