From c6f8bdb249083ef5ca3c5f13466015a1cb600bce Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 23 Jan 2019 18:04:00 -0500 Subject: [PATCH] Remove T: Debug bound on mpsc Debug impls (#866) Following from https://github.com/tokio-rs/tokio/pull/865, this PR removes `#[derive(Debug)]` on `mpsc` sender and receiver types in favor of explicit `impl fmt::Debug` blocks that don't have a `T: fmt::Debug` bound. --- tokio-sync/src/mpsc/bounded.rs | 18 ++++++++++-- tokio-sync/src/mpsc/chan.rs | 50 +++++++++++++++++++++++++++++--- tokio-sync/src/mpsc/list.rs | 4 +-- tokio-sync/src/mpsc/unbounded.rs | 18 ++++++++++-- tokio-sync/tests/mpsc.rs | 46 ++++++++++++++--------------- 5 files changed, 102 insertions(+), 34 deletions(-) diff --git a/tokio-sync/src/mpsc/bounded.rs b/tokio-sync/src/mpsc/bounded.rs index 879d063c886..ad5d6eea4f4 100644 --- a/tokio-sync/src/mpsc/bounded.rs +++ b/tokio-sync/src/mpsc/bounded.rs @@ -7,7 +7,6 @@ use std::fmt; /// Send values to the associated `Receiver`. /// /// Instances are created by the [`channel`](fn.channel.html) function. -#[derive(Debug)] pub struct Sender { chan: chan::Tx, } @@ -18,15 +17,30 @@ impl Clone for Sender { } } +impl fmt::Debug for Sender { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Sender") + .field("chan", &self.chan) + .finish() + } +} + /// Receive values from the associated `Sender`. /// /// Instances are created by the [`channel`](fn.channel.html) function. -#[derive(Debug)] pub struct Receiver { /// The channel receiver chan: chan::Rx, } +impl fmt::Debug for Receiver { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Receiver") + .field("chan", &self.chan) + .finish() + } +} + /// Error returned by the `Sender`. #[derive(Debug)] pub struct SendError(()); diff --git a/tokio-sync/src/mpsc/chan.rs b/tokio-sync/src/mpsc/chan.rs index f78aadfc1a4..01d4bd75a1f 100644 --- a/tokio-sync/src/mpsc/chan.rs +++ b/tokio-sync/src/mpsc/chan.rs @@ -4,23 +4,44 @@ use futures::task::AtomicTask; use std::cell::UnsafeCell; use std::process; +use std::fmt; use std::sync::Arc; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::{AcqRel, Relaxed}; /// Channel sender -#[derive(Debug)] pub(crate) struct Tx { inner: Arc>, permit: S::Permit, } +impl fmt::Debug for Tx +where S::Permit: fmt::Debug, + S: fmt::Debug +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Tx") + .field("inner", &self.inner) + .field("permit", &self.permit) + .finish() + } +} + /// Channel receiver -#[derive(Debug)] pub(crate) struct Rx { inner: Arc>, } +impl fmt::Debug for Rx +where S: fmt::Debug +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Rx") + .field("inner", &self.inner) + .finish() + } +} + #[derive(Debug, Eq, PartialEq)] pub(crate) enum TrySendError { Closed, @@ -53,7 +74,6 @@ pub(crate) trait Semaphore: Sync { fn close(&self); } -#[derive(Debug)] struct Chan { /// Handle to the push half of the lock-free list. tx: list::Tx, @@ -73,8 +93,20 @@ struct Chan { rx_fields: UnsafeCell>, } +impl fmt::Debug for Chan where S: fmt::Debug +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Chan") + .field("tx", &self.tx) + .field("semaphore", &self.semaphore) + .field("rx_task", &self.rx_task) + .field("tx_count", &self.tx_count) + .field("rx_fields", &self.rx_fields) + .finish() + } +} + /// Fields only accessed by `Rx` handle. -#[derive(Debug)] struct RxFields { /// Channel receiver. This field is only accessed by the `Receiver` type. list: list::Rx, @@ -83,6 +115,16 @@ struct RxFields { rx_closed: bool, } +impl fmt::Debug for RxFields +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("RxFields") + .field("list", &self.list) + .field("rx_closed", &self.rx_closed) + .finish() + } +} + unsafe impl Send for Chan {} unsafe impl Sync for Chan {} diff --git a/tokio-sync/src/mpsc/list.rs b/tokio-sync/src/mpsc/list.rs index dde380bfcce..aedd99547aa 100644 --- a/tokio-sync/src/mpsc/list.rs +++ b/tokio-sync/src/mpsc/list.rs @@ -212,7 +212,7 @@ impl Tx { } } -impl fmt::Debug for Tx { +impl fmt::Debug for Tx { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { use std::sync::atomic::Ordering::Relaxed; @@ -318,7 +318,7 @@ impl Rx { } } -impl fmt::Debug for Rx { +impl fmt::Debug for Rx { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("Rx") .field("head", &self.head) diff --git a/tokio-sync/src/mpsc/unbounded.rs b/tokio-sync/src/mpsc/unbounded.rs index 16bb659e263..1473c1b93ab 100644 --- a/tokio-sync/src/mpsc/unbounded.rs +++ b/tokio-sync/src/mpsc/unbounded.rs @@ -9,7 +9,6 @@ use std::fmt; /// /// Instances are created by the /// [`unbounded_channel`](fn.unbounded_channel.html) function. -#[derive(Debug)] pub struct UnboundedSender { chan: chan::Tx, } @@ -20,16 +19,31 @@ impl Clone for UnboundedSender { } } +impl fmt::Debug for UnboundedSender { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("UnboundedSender") + .field("chan", &self.chan) + .finish() + } +} + /// Receive values from the associated `UnboundedSender`. /// /// Instances are created by the /// [`unbounded_channel`](fn.unbounded_channel.html) function. -#[derive(Debug)] pub struct UnboundedReceiver { /// The channel receiver chan: chan::Rx, } +impl fmt::Debug for UnboundedReceiver { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("UnboundedReceiver") + .field("chan", &self.chan) + .finish() + } +} + /// Error returned by the `UnboundedSender`. #[derive(Debug)] pub struct UnboundedSendError(()); diff --git a/tokio-sync/tests/mpsc.rs b/tokio-sync/tests/mpsc.rs index 4f2ea4f96e7..ce3fafc1dd8 100644 --- a/tokio-sync/tests/mpsc.rs +++ b/tokio-sync/tests/mpsc.rs @@ -92,33 +92,31 @@ fn send_recv_unbounded() { } #[test] -fn clone_sender_no_t_clone_buffer() { - #[derive(Debug, PartialEq, Eq)] - struct NotClone; - let (mut tx, mut rx) = mpsc::channel(100); - tx.try_send(NotClone).unwrap(); - tx.clone().try_send(NotClone).unwrap(); - - let val = assert_ready!(rx.poll()); - assert_eq!(val, Some(NotClone)); - - let val = assert_ready!(rx.poll()); - assert_eq!(val, Some(NotClone)); +fn no_t_bounds_buffer() { + struct NoImpls; + let (tx, mut rx) = mpsc::channel(100); + + // sender should be Debug even though T isn't Debug + println!("{:?}", tx); + // same with Receiver + println!("{:?}", rx); + // and sender should be Clone even though T isn't Clone + assert!(tx.clone().try_send(NoImpls).is_ok()); + assert!(assert_ready!(rx.poll()).is_some()); } #[test] -fn clone_sender_no_t_clone_unbounded() { - #[derive(Debug, PartialEq, Eq)] - struct NotClone; - let (mut tx, mut rx) = mpsc::unbounded_channel(); - tx.try_send(NotClone).unwrap(); - tx.clone().try_send(NotClone).unwrap(); - - let val = assert_ready!(rx.poll()); - assert_eq!(val, Some(NotClone)); - - let val = assert_ready!(rx.poll()); - assert_eq!(val, Some(NotClone)); +fn no_t_bounds_unbounded() { + struct NoImpls; + let (tx, mut rx) = mpsc::unbounded_channel(); + + // sender should be Debug even though T isn't Debug + println!("{:?}", tx); + // same with Receiver + println!("{:?}", rx); + // and sender should be Clone even though T isn't Clone + assert!(tx.clone().try_send(NoImpls).is_ok()); + assert!(assert_ready!(rx.poll()).is_some()); } #[test]