Remove redundant Clone, and Debug bounds (#607)

The balancer types derive `Debug` and `Clone` implementations, but
this unnecessarily requires that its type parameters implement these
traits.

This change provides manual implementations for `Clone` and `Debug`
to avoid this unintentional restriction.

Closes #606
This commit is contained in:
cppforliving 2021-10-28 07:33:39 +02:00 committed by GitHub
parent d4865641e7
commit 80c6e38f2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 139 additions and 14 deletions

View File

@ -7,7 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# Unreleased
- None.
### Fixed
- **balance**: Remove redundant `Req: Clone` bound from `Clone` impls
for `MakeBalance`, and `MakeBalanceLayer` ([#607])
- **balance**: Remove redundant `Req: Debug` bound from `Debug` impls
for `MakeBalance`, `MakeFuture`, `Balance`, and `Pool` ([#607])
- **ready-cache**: Remove redundant `Req: Debug` bound from `Debug` impl
for `ReadyCache` ([#607])
- **steer**: Remove redundant `Req: Debug` bound from `Debug` impl
for `Steer` ([#607])
- **util**: Remove redundant `F: Clone` bound
from `ServiceExt::map_request` ([#607])
[#607]: https://github.com/tower-rs/tower/pull/607
# 0.4.10 (October 19, 2021)
@ -19,7 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# 0.4.9 (October 13, 2021)
- Migrate to pin-project-lite ([#595])
- Migrate to [pin-project-lite] ([#595])
- **builder**: Implement `Layer` for `ServiceBuilder` ([#600])
- **builder**: Add `ServiceBuilder::and_then` analogous to
`ServiceExt::and_then` ([#601])

View File

@ -18,7 +18,6 @@ use tower_layer::Layer;
/// [`Discover`]: crate::discover::Discover
/// [`MakeService`]: crate::MakeService
/// [`Service`]: crate::Service
#[derive(Clone)]
pub struct MakeBalanceLayer<D, Req> {
_marker: PhantomData<fn(D, Req)>,
}
@ -38,6 +37,14 @@ impl<D, Req> Default for MakeBalanceLayer<D, Req> {
}
}
impl<D, Req> Clone for MakeBalanceLayer<D, Req> {
fn clone(&self) -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<S, Req> Layer<S> for MakeBalanceLayer<S, Req> {
type Service = MakeBalance<S, Req>;

View File

@ -5,6 +5,7 @@ use pin_project_lite::pin_project;
use std::hash::Hash;
use std::marker::PhantomData;
use std::{
fmt,
future::Future,
pin::Pin,
task::{Context, Poll},
@ -23,7 +24,6 @@ use tower_service::Service;
/// [`MakeService`]: crate::MakeService
/// [`Discover`]: crate::discover::Discover
/// [`Balance`]: crate::balance::p2c::Balance
#[derive(Clone, Debug)]
pub struct MakeBalance<S, Req> {
inner: S,
_marker: PhantomData<fn(Req)>,
@ -33,7 +33,6 @@ pin_project! {
/// A [`Balance`] in the making.
///
/// [`Balance`]: crate::balance::p2c::Balance
#[derive(Debug)]
pub struct MakeFuture<F, Req> {
#[pin]
inner: F,
@ -51,6 +50,18 @@ impl<S, Req> MakeBalance<S, Req> {
}
}
impl<S, Req> Clone for MakeBalance<S, Req>
where
S: Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
_marker: PhantomData,
}
}
}
impl<S, Target, Req> Service<Target> for MakeBalance<S, Req>
where
S: Service<Target>,
@ -75,6 +86,16 @@ where
}
}
impl<S, Req> fmt::Debug for MakeBalance<S, Req>
where
S: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self { inner, _marker } = self;
f.debug_struct("MakeBalance").field("inner", inner).finish()
}
}
impl<F, T, E, Req> Future for MakeFuture<F, Req>
where
F: Future<Output = Result<T, E>>,
@ -92,3 +113,13 @@ where
Poll::Ready(Ok(svc))
}
}
impl<F, Req> fmt::Debug for MakeFuture<F, Req>
where
F: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self { inner, _marker } = self;
f.debug_struct("MakeFuture").field("inner", inner).finish()
}
}

View File

@ -49,7 +49,6 @@ where
D: fmt::Debug,
D::Key: Hash + fmt::Debug,
D::Service: fmt::Debug,
Req: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Balance")
@ -63,7 +62,6 @@ pin_project! {
/// A Future that becomes satisfied when an `S`-typed service is ready.
///
/// May fail due to cancelation, i.e., if [`Discover`] removes the service from the service set.
#[derive(Debug)]
struct UnreadyService<K, S, Req> {
key: Option<K>,
#[pin]
@ -315,3 +313,23 @@ impl<K, S: Service<Req>, Req> Future for UnreadyService<K, S, Req> {
}
}
}
impl<K, S, Req> fmt::Debug for UnreadyService<K, S, Req>
where
K: fmt::Debug,
S: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self {
key,
cancel,
service,
_req,
} = self;
f.debug_struct("UnreadyService")
.field("key", key)
.field("cancel", cancel)
.field("service", service)
.finish()
}
}

View File

@ -318,7 +318,6 @@ where
MS::Error: Into<crate::BoxError>,
Target: Clone + fmt::Debug,
MS::Service: fmt::Debug,
Request: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Pool")

View File

@ -67,7 +67,7 @@ impl<Request> Clone for BufferLayer<Request> {
fn clone(&self) -> Self {
Self {
bound: self.bound,
_p: self._p,
_p: PhantomData,
}
}
}

View File

@ -5,6 +5,7 @@ use futures_core::Stream;
use futures_util::stream::FuturesUnordered;
pub use indexmap::Equivalent;
use indexmap::IndexMap;
use std::fmt;
use std::future::Future;
use std::hash::Hash;
use std::pin::Pin;
@ -53,7 +54,6 @@ use tracing::{debug, trace};
/// service. In such a case, it should be noted that calls to
/// [`ReadyCache::poll_pending`] and [`ReadyCache::evict`] may perturb the order of
/// the ready set, so any cached indexes should be discarded after such a call.
#[derive(Debug)]
pub struct ReadyCache<K, S, Req>
where
K: Eq + Hash,
@ -88,7 +88,6 @@ enum PendingError<K, E> {
/// A [`Future`] that becomes satisfied when an `S`-typed service is ready.
///
/// May fail due to cancelation, i.e. if the service is evicted from the balancer.
#[derive(Debug)]
struct Pending<K, S, Req> {
key: Option<K>,
cancel: Option<CancelRx>,
@ -112,6 +111,25 @@ where
}
}
impl<K, S, Req> fmt::Debug for ReadyCache<K, S, Req>
where
K: fmt::Debug + Eq + Hash,
S: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self {
pending,
pending_cancel_txs,
ready,
} = self;
f.debug_struct("ReadyCache")
.field("pending", pending)
.field("pending_cancel_txs", pending_cancel_txs)
.field("ready", ready)
.finish()
}
}
impl<K, S, Req> ReadyCache<K, S, Req>
where
K: Eq + Hash,
@ -418,3 +436,23 @@ where
}
}
}
impl<K, S, Req> fmt::Debug for Pending<K, S, Req>
where
K: fmt::Debug,
S: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self {
key,
cancel,
ready,
_pd,
} = self;
f.debug_struct("Pending")
.field("key", key)
.field("cancel", cancel)
.field("ready", ready)
.finish()
}
}

View File

@ -69,7 +69,7 @@
//! # }
//! ```
use std::task::{Context, Poll};
use std::{collections::VecDeque, marker::PhantomData};
use std::{collections::VecDeque, fmt, marker::PhantomData};
use tower_service::Service;
/// This is how callers of [`Steer`] tell it which `Service` a `Req` corresponds to.
@ -104,7 +104,6 @@ where
/// requests) will prevent head-of-line blocking in [`Steer`].
///
/// [`Buffer`]: crate::buffer::Buffer
#[derive(Debug)]
pub struct Steer<S, F, Req> {
router: F,
services: Vec<S>,
@ -180,3 +179,23 @@ where
}
}
}
impl<S, F, Req> fmt::Debug for Steer<S, F, Req>
where
S: fmt::Debug,
F: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self {
router,
services,
not_ready,
_phantom,
} = self;
f.debug_struct("Steer")
.field("router", router)
.field("services", services)
.field("not_ready", not_ready)
.finish()
}
}

View File

@ -604,7 +604,7 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
fn map_request<F, NewRequest>(self, f: F) -> MapRequest<Self, F>
where
Self: Sized,
F: FnMut(NewRequest) -> Request + Clone,
F: FnMut(NewRequest) -> Request,
{
MapRequest::new(self, f)
}