From 4a1d48867f9266a641ba09f3cf2c9ea012a0ecf7 Mon Sep 17 00:00:00 2001 From: piegames Date: Mon, 15 Nov 2021 23:53:54 +0100 Subject: [PATCH 1/2] Add Log implementation on foreign types Closes #458. Implements Log for references to loggers, as well as loggers wrapped in `Arc` or `Pin`. More may be added in the future. Especially, we probably will want to add a blanket implementation (bounded on `Borrow`) once we have impl specialization. (Technically, we could probably already do this now, but at the risk of painting ourselves into a corner.) --- src/lib.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index bfd0819e9..5dfb91479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -269,7 +269,7 @@ html_root_url = "https://docs.rs/log/0.4.14" )] #![warn(missing_docs)] -#![deny(missing_debug_implementations)] +#![deny(missing_debug_implementations, unconditional_recursion)] #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] // When compiled for the rustc compiler itself we want to make sure that this is // an unstable crate @@ -1250,6 +1250,22 @@ impl Log for NopLogger { fn flush(&self) {} } +impl Log for &'_ T +where + T: ?Sized + Log, +{ + fn enabled(&self, metadata: &Metadata) -> bool { + (**self).enabled(metadata) + } + + fn log(&self, record: &Record) { + (**self).log(record) + } + fn flush(&self) { + (**self).flush() + } +} + #[cfg(feature = "std")] impl Log for std::boxed::Box where @@ -1267,6 +1283,41 @@ where } } +#[cfg(feature = "std")] +impl Log for std::pin::Pin

+where + P: std::ops::Deref + std::marker::Send + std::marker::Sync, + T: Log + ?Sized, +{ + fn enabled(&self, metadata: &Metadata) -> bool { + (**self).enabled(metadata) + } + + fn log(&self, record: &Record) { + (**self).log(record) + } + fn flush(&self) { + (**self).flush() + } +} + +#[cfg(feature = "std")] +impl Log for std::sync::Arc +where + T: ?Sized + Log, +{ + fn enabled(&self, metadata: &Metadata) -> bool { + self.as_ref().enabled(metadata) + } + + fn log(&self, record: &Record) { + self.as_ref().log(record) + } + fn flush(&self) { + self.as_ref().flush() + } +} + /// Sets the global maximum log level. /// /// Generally, this should only be called by the active logging implementation. @@ -1842,4 +1893,41 @@ mod tests { .expect("invalid value") ); } + + // Test that the `impl Log for Foo` blocks work + // This test mostly operates on a type level, so failures will be compile errors + #[test] + fn test_foreign_impl() { + use super::Log; + #[cfg(feature = "std")] + use std::{pin::Pin, sync::Arc}; + + fn assert_is_log() {} + + assert_is_log::<&dyn Log>(); + + #[cfg(feature = "std")] + assert_is_log::>(); + + #[cfg(feature = "std")] + assert_is_log::>>(); + + #[cfg(feature = "std")] + assert_is_log::>(); + + // Assert these statements for all T: Log + ?Sized + #[allow(unused)] + fn forall() { + #[cfg(feature = "std")] + assert_is_log::>(); + + #[cfg(feature = "std")] + assert_is_log::>>(); + + assert_is_log::<&T>(); + + #[cfg(feature = "std")] + assert_is_log::>(); + } + } } From 084624a0973beecae1dd949541e28c1e20a91e20 Mon Sep 17 00:00:00 2001 From: piegames Date: Wed, 17 Nov 2021 18:18:53 +0100 Subject: [PATCH 2/2] fixup! Add Log implementation on foreign types Removes the Pin implementation again, because of the MSRV of the crate beeing too low --- src/lib.rs | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5dfb91479..1dbae3bcf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1283,24 +1283,6 @@ where } } -#[cfg(feature = "std")] -impl Log for std::pin::Pin

-where - P: std::ops::Deref + std::marker::Send + std::marker::Sync, - T: Log + ?Sized, -{ - fn enabled(&self, metadata: &Metadata) -> bool { - (**self).enabled(metadata) - } - - fn log(&self, record: &Record) { - (**self).log(record) - } - fn flush(&self) { - (**self).flush() - } -} - #[cfg(feature = "std")] impl Log for std::sync::Arc where @@ -1900,7 +1882,7 @@ mod tests { fn test_foreign_impl() { use super::Log; #[cfg(feature = "std")] - use std::{pin::Pin, sync::Arc}; + use std::sync::Arc; fn assert_is_log() {} @@ -1909,9 +1891,6 @@ mod tests { #[cfg(feature = "std")] assert_is_log::>(); - #[cfg(feature = "std")] - assert_is_log::>>(); - #[cfg(feature = "std")] assert_is_log::>(); @@ -1921,9 +1900,6 @@ mod tests { #[cfg(feature = "std")] assert_is_log::>(); - #[cfg(feature = "std")] - assert_is_log::>>(); - assert_is_log::<&T>(); #[cfg(feature = "std")]