From c6f9a069a5ab62be746f428a618547097764b73d Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 23 Jan 2019 15:51:44 -0500 Subject: [PATCH] Explicit impl Clone for tx to avoid T: Clone (#865) `#[derive(Clone)]` on a type `struct Foo` adds an impl that requires that `T: Clone`: ```rust impl Clone for Foo ``` which is unfortunate in the case of senders, because we don't want to require that the items being sent are `Clone` for the channel sender to be `Clone`. This PR adds an explicit `impl Clone` for the bounded and unbounded sender types which does not have the `T: Clone` bound. Note that this is _also_ an issue with `#[derive(Debug)]`, but that one is harder to work around as `chan::Tx` _also_ has `#[derive(Debug)]`, as does `chan::Chan`, so we'd have to add explicit impls for all of them to make progress. --- tokio-sync/src/mpsc/bounded.rs | 8 +++++++- tokio-sync/src/mpsc/unbounded.rs | 8 +++++++- tokio-sync/tests/mpsc.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/tokio-sync/src/mpsc/bounded.rs b/tokio-sync/src/mpsc/bounded.rs index d74317316..879d063c8 100644 --- a/tokio-sync/src/mpsc/bounded.rs +++ b/tokio-sync/src/mpsc/bounded.rs @@ -7,11 +7,17 @@ use std::fmt; /// Send values to the associated `Receiver`. /// /// Instances are created by the [`channel`](fn.channel.html) function. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Sender { chan: chan::Tx, } +impl Clone for Sender { + fn clone(&self) -> Self { + Sender { chan: self.chan.clone() } + } +} + /// Receive values from the associated `Sender`. /// /// Instances are created by the [`channel`](fn.channel.html) function. diff --git a/tokio-sync/src/mpsc/unbounded.rs b/tokio-sync/src/mpsc/unbounded.rs index 957336517..16bb659e2 100644 --- a/tokio-sync/src/mpsc/unbounded.rs +++ b/tokio-sync/src/mpsc/unbounded.rs @@ -9,11 +9,17 @@ use std::fmt; /// /// Instances are created by the /// [`unbounded_channel`](fn.unbounded_channel.html) function. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct UnboundedSender { chan: chan::Tx, } +impl Clone for UnboundedSender { + fn clone(&self) -> Self { + UnboundedSender { chan: self.chan.clone() } + } +} + /// Receive values from the associated `UnboundedSender`. /// /// Instances are created by the diff --git a/tokio-sync/tests/mpsc.rs b/tokio-sync/tests/mpsc.rs index dca9b305b..4f2ea4f96 100644 --- a/tokio-sync/tests/mpsc.rs +++ b/tokio-sync/tests/mpsc.rs @@ -91,6 +91,36 @@ fn send_recv_unbounded() { assert!(val.is_none()); } +#[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)); +} + +#[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)); +} + #[test] fn send_recv_buffer_limited() { let (mut tx, mut rx) = mpsc::channel::(1);