Repository: tower-rs/tower
Pull request #805 (2024-12-19 21:23:52)

chore: Replace type related to future with standard library
Replaces the types from futures crates with ones from the standard library.

jplatte: Looks like (fortunately) none of these are part of the public API. `cargo semver-checks` doesn't complain and I looked over the changes as well.
jplatte: @Darksonn @seanmonstar gentle bump :)
Darksonn: This looks okay to me, but I'm not a tower maintainer.

Patch:
diff --git a/tower/Cargo.toml b/tower/Cargo.toml
index a04e182..da7a0fb 100644
--- a/tower/Cargo.toml
+++ b/tower/Cargo.toml
@@ -20,10 +20,6 @@ edition = "2018"
 rust-version = "1.64.0"
 
 [features]
-
-# Internal
-__common = ["futures-core", "pin-project-lite"]
-
 full = [
   "balance",
   "buffer",
@@ -45,21 +41,21 @@ full = [
 # FIXME: Use weak dependency once available (https://github.com/rust-lang/cargo/issues/8832)
 log = ["tracing/log"]
 balance = ["discover", "load", "ready-cache", "make", "slab", "util"]
-buffer = ["__common", "tokio/sync", "tokio/rt", "tokio-util", "tracing"]
-discover = ["__common"]
-filter = ["__common", "futures-util"]
+buffer = ["tokio/sync", "tokio/rt", "tokio-util", "tracing", "pin-project-lite"]
+discover = ["futures-core", "pin-project-lite"]
+filter = ["futures-util", "pin-project-lite"]
 hedge = ["util", "filter", "futures-util", "hdrhistogram", "tokio/time", "tracing"]
-limit = ["__common", "tokio/time", "tokio/sync", "tokio-util", "tracing"]
-load = ["__common", "tokio/time", "tracing"]
-load-shed = ["__common"]
-make = ["futures-util", "pin-project-lite", "tokio/io-std"]
+limit = ["tokio/time", "tokio/sync", "tokio-util", "tracing", "pin-project-lite"]
+load = ["tokio/time", "tracing", "pin-project-lite"]
+load-shed = ["pin-project-lite"]
+make = ["pin-project-lite", "tokio/io-std"]
 ready-cache = ["futures-core", "futures-util", "indexmap", "tokio/sync", "tracing", "pin-project-lite"]
 reconnect = ["make", "tokio/io-std", "tracing"]
-retry = ["__common", "tokio/time", "util"]
-spawn-ready = ["__common", "futures-util", "tokio/sync", "tokio/rt", "util", "tracing"]
+retry = ["tokio/time", "util"]
+spawn-ready = ["futures-util", "tokio/sync", "tokio/rt", "util", "tracing"]
 steer = []
 timeout = ["pin-project-lite", "tokio/time"]
-util = ["__common", "futures-util", "pin-project-lite", "sync_wrapper"]
+util = ["futures-core", "futures-util", "pin-project-lite", "sync_wrapper"]
 
 [dependencies]
 tower-layer = { version = "0.3.3", path = "../tower-layer" }
diff --git a/tower/src/balance/p2c/make.rs b/tower/src/balance/p2c/make.rs
index 45a35d1..da4601c 100644
--- a/tower/src/balance/p2c/make.rs
+++ b/tower/src/balance/p2c/make.rs
@@ -1,6 +1,5 @@
 use super::Balance;
 use crate::discover::Discover;
-use futures_core::ready;
 use pin_project_lite::pin_project;
 use std::hash::Hash;
 use std::marker::PhantomData;
@@ -8,7 +7,7 @@ use std::{
     fmt,
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tower_service::Service;
 
diff --git a/tower/src/balance/p2c/service.rs b/tower/src/balance/p2c/service.rs
index 30572fc..6a8f46a 100644
--- a/tower/src/balance/p2c/service.rs
+++ b/tower/src/balance/p2c/service.rs
@@ -3,14 +3,13 @@ use crate::discover::{Change, Discover};
 use crate::load::Load;
 use crate::ready_cache::{error::Failed, ReadyCache};
 use crate::util::rng::{sample_floyd2, HasherRng, Rng};
-use futures_core::ready;
 use futures_util::future::{self, TryFutureExt};
 use std::hash::Hash;
 use std::marker::PhantomData;
 use std::{
     fmt,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tower_service::Service;
 use tracing::{debug, trace};
diff --git a/tower/src/buffer/future.rs b/tower/src/buffer/future.rs
index 4117890..3de94c2 100644
--- a/tower/src/buffer/future.rs
+++ b/tower/src/buffer/future.rs
@@ -3,12 +3,11 @@
 //! [`Buffer`]: crate::buffer::Buffer
 
 use super::{error::Closed, message};
-use futures_core::ready;
 use pin_project_lite::pin_project;
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 
 pin_project! {
diff --git a/tower/src/buffer/worker.rs b/tower/src/buffer/worker.rs
index 7f4416d..b0a7978 100644
--- a/tower/src/buffer/worker.rs
+++ b/tower/src/buffer/worker.rs
@@ -2,12 +2,11 @@ use super::{
     error::{Closed, ServiceError},
     message::Message,
 };
-use futures_core::ready;
 use std::sync::{Arc, Mutex};
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tokio::sync::mpsc;
 use tower_service::Service;
diff --git a/tower/src/builder/mod.rs b/tower/src/builder/mod.rs
index 6c749c3..b99de12 100644
--- a/tower/src/builder/mod.rs
+++ b/tower/src/builder/mod.rs
@@ -635,7 +635,7 @@ impl<L> ServiceBuilder<L> {
     /// impl Service<Request> for MyService {
     ///   type Response = Response;
     ///   type Error = Error;
-    ///   type Future = futures_util::future::Ready<Result<Response, Error>>;
+    ///   type Future = std::future::Ready<Result<Response, Error>>;
     ///
     ///   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     ///       // ...
diff --git a/tower/src/discover/mod.rs b/tower/src/discover/mod.rs
index fc137da..6506e95 100644
--- a/tower/src/discover/mod.rs
+++ b/tower/src/discover/mod.rs
@@ -12,7 +12,8 @@
 //! # Examples
 //!
 //! ```rust
-//! use futures_util::{future::poll_fn, pin_mut};
+//! use std::future::poll_fn;
+//! use futures_util::pin_mut;
 //! use tower::discover::{Change, Discover};
 //! async fn services_monitor<D: Discover>(services: D) {
 //!     pin_mut!(services);
diff --git a/tower/src/filter/future.rs b/tower/src/filter/future.rs
index 67772bb..6803d32 100644
--- a/tower/src/filter/future.rs
+++ b/tower/src/filter/future.rs
@@ -2,12 +2,11 @@
 
 use super::AsyncPredicate;
 use crate::BoxError;
-use futures_core::ready;
 use pin_project_lite::pin_project;
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tower_service::Service;
 
@@ -35,7 +34,7 @@ opaque_future! {
     /// [`Filter`]: crate::filter::Filter
     pub type ResponseFuture<R, F> =
         futures_util::future::Either<
-            futures_util::future::Ready<Result<R, crate::BoxError>>,
+            std::future::Ready<Result<R, crate::BoxError>>,
             futures_util::future::ErrInto<F, crate::BoxError>
         >;
 }
diff --git a/tower/src/filter/mod.rs b/tower/src/filter/mod.rs
index c53ba40..185fa83 100644
--- a/tower/src/filter/mod.rs
+++ b/tower/src/filter/mod.rs
@@ -114,7 +114,7 @@ where
     fn call(&mut self, request: Request) -> Self::Future {
         ResponseFuture::new(match self.predicate.check(request) {
             Ok(request) => Either::Right(self.inner.call(request).err_into()),
-            Err(e) => Either::Left(futures_util::future::ready(Err(e))),
+            Err(e) => Either::Left(std::future::ready(Err(e))),
         })
     }
 }
diff --git a/tower/src/hedge/delay.rs b/tower/src/hedge/delay.rs
index 7b45c0e..41b90c1 100644
--- a/tower/src/hedge/delay.rs
+++ b/tower/src/hedge/delay.rs
@@ -1,10 +1,9 @@
-use futures_util::ready;
 use pin_project_lite::pin_project;
 use std::time::Duration;
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tower_service::Service;
 
diff --git a/tower/src/hedge/latency.rs b/tower/src/hedge/latency.rs
index 723652a..f0a5e1f 100644
--- a/tower/src/hedge/latency.rs
+++ b/tower/src/hedge/latency.rs
@@ -1,10 +1,9 @@
-use futures_util::ready;
 use pin_project_lite::pin_project;
 use std::time::Duration;
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tokio::time::Instant;
 use tower_service::Service;
diff --git a/tower/src/hedge/mod.rs b/tower/src/hedge/mod.rs
index 3cd152e..9698a9b 100644
--- a/tower/src/hedge/mod.rs
+++ b/tower/src/hedge/mod.rs
@@ -4,11 +4,12 @@
 #![warn(missing_debug_implementations, missing_docs, unreachable_pub)]
 
 use crate::filter::AsyncFilter;
-use futures_util::future;
+use futures_util::future::Either;
 use pin_project_lite::pin_project;
 use std::sync::{Arc, Mutex};
 use std::time::Duration;
 use std::{
+    future,
     pin::Pin,
     task::{Context, Poll},
 };
@@ -222,7 +223,7 @@ impl<P, Request> crate::filter::AsyncPredicate<Request> for PolicyPredicate<P>
 where
     P: Policy<Request>,
 {
-    type Future = future::Either<
+    type Future = Either<
         future::Ready<Result<Request, crate::BoxError>>,
         future::Pending<Result<Request, crate::BoxError>>,
     >;
@@ -230,13 +231,13 @@ where
 
     fn check(&mut self, request: Request) -> Self::Future {
         if self.0.can_retry(&request) {
-            future::Either::Left(future::ready(Ok(request)))
+            Either::Left(future::ready(Ok(request)))
         } else {
             // If the hedge retry should not be issued, we simply want to wait
             // for the result of the original request.  Therefore we don't want
             // to return an error here.  Instead, we use future::pending to ensure
             // that the original request wins the select.
-            future::Either::Right(future::pending())
+            Either::Right(future::pending())
         }
     }
 }
diff --git a/tower/src/limit/concurrency/future.rs b/tower/src/limit/concurrency/future.rs
index 6eb0100..9506ecb 100644
--- a/tower/src/limit/concurrency/future.rs
+++ b/tower/src/limit/concurrency/future.rs
@@ -1,12 +1,11 @@
 //! [`Future`] types
 //!
 //! [`Future`]: std::future::Future
-use futures_core::ready;
 use pin_project_lite::pin_project;
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tokio::sync::OwnedSemaphorePermit;
 
diff --git a/tower/src/limit/concurrency/service.rs b/tower/src/limit/concurrency/service.rs
index bb9cf5e..3b52e5d 100644
--- a/tower/src/limit/concurrency/service.rs
+++ b/tower/src/limit/concurrency/service.rs
@@ -3,10 +3,9 @@ use tokio::sync::{OwnedSemaphorePermit, Semaphore};
 use tokio_util::sync::PollSemaphore;
 use tower_service::Service;
 
-use futures_core::ready;
 use std::{
     sync::Arc,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 
 /// Enforces a limit on the concurrent number of requests the underlying
diff --git a/tower/src/limit/rate/service.rs b/tower/src/limit/rate/service.rs
index 0aa1d69..6c476ad 100644
--- a/tower/src/limit/rate/service.rs
+++ b/tower/src/limit/rate/service.rs
@@ -1,9 +1,8 @@
 use super::Rate;
-use futures_core::ready;
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tokio::time::{Instant, Sleep};
 use tower_service::Service;
diff --git a/tower/src/load/completion.rs b/tower/src/load/completion.rs
index 857e055..50c4411 100644
--- a/tower/src/load/completion.rs
+++ b/tower/src/load/completion.rs
@@ -1,11 +1,10 @@
 //! Application-specific request completion semantics.
 
-use futures_core::ready;
 use pin_project_lite::pin_project;
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 
 /// Attaches `H`-typed completion tracker to `V` typed values.
diff --git a/tower/src/load/constant.rs b/tower/src/load/constant.rs
index b53a10b..a9ff89c 100644
--- a/tower/src/load/constant.rs
+++ b/tower/src/load/constant.rs
@@ -3,9 +3,9 @@
 #[cfg(feature = "discover")]
 use crate::discover::{Change, Discover};
 #[cfg(feature = "discover")]
-use futures_core::{ready, Stream};
+use futures_core::Stream;
 #[cfg(feature = "discover")]
-use std::pin::Pin;
+use std::{pin::Pin, task::ready};
 
 use super::Load;
 use pin_project_lite::pin_project;
diff --git a/tower/src/load/peak_ewma.rs b/tower/src/load/peak_ewma.rs
index c145ab6..4bc4250 100644
--- a/tower/src/load/peak_ewma.rs
+++ b/tower/src/load/peak_ewma.rs
@@ -3,11 +3,11 @@
 #[cfg(feature = "discover")]
 use crate::discover::{Change, Discover};
 #[cfg(feature = "discover")]
-use futures_core::{ready, Stream};
+use futures_core::Stream;
 #[cfg(feature = "discover")]
 use pin_project_lite::pin_project;
 #[cfg(feature = "discover")]
-use std::pin::Pin;
+use std::{pin::Pin, task::ready};
 
 use super::completion::{CompleteOnResponse, TrackCompletion, TrackCompletionFuture};
 use super::Load;
@@ -309,8 +309,7 @@ fn nanos(d: Duration) -> f64 {
 
 #[cfg(test)]
 mod tests {
-    use futures_util::future;
-    use std::time::Duration;
+    use std::{future, time::Duration};
     use tokio::time;
     use tokio_test::{assert_ready, assert_ready_ok, task};
 
@@ -327,7 +326,7 @@ mod tests {
         }
 
         fn call(&mut self, (): ()) -> Self::Future {
-            future::ok(())
+            future::ready(Ok(()))
         }
     }
 
diff --git a/tower/src/load/pending_requests.rs b/tower/src/load/pending_requests.rs
index 2721633..d11f62c 100644
--- a/tower/src/load/pending_requests.rs
+++ b/tower/src/load/pending_requests.rs
@@ -3,11 +3,11 @@
 #[cfg(feature = "discover")]
 use crate::discover::{Change, Discover};
 #[cfg(feature = "discover")]
-use futures_core::{ready, Stream};
+use futures_core::Stream;
 #[cfg(feature = "discover")]
 use pin_project_lite::pin_project;
 #[cfg(feature = "discover")]
-use std::pin::Pin;
+use std::{pin::Pin, task::ready};
 
 use super::completion::{CompleteOnResponse, TrackCompletion, TrackCompletionFuture};
 use super::Load;
@@ -148,8 +148,10 @@ impl RefCount {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use futures_util::future;
-    use std::task::{Context, Poll};
+    use std::{
+        future,
+        task::{Context, Poll},
+    };
 
     struct Svc;
     impl Service<()> for Svc {
@@ -162,7 +164,7 @@ mod tests {
         }
 
         fn call(&mut self, (): ()) -> Self::Future {
-            future::ok(())
+            future::ready(Ok(()))
         }
     }
 
diff --git a/tower/src/load_shed/future.rs b/tower/src/load_shed/future.rs
index 64f394c..4ad115b 100644
--- a/tower/src/load_shed/future.rs
+++ b/tower/src/load_shed/future.rs
@@ -3,9 +3,8 @@
 use std::fmt;
 use std::future::Future;
 use std::pin::Pin;
-use std::task::{Context, Poll};
+use std::task::{ready, Context, Poll};
 
-use futures_core::ready;
 use pin_project_lite::pin_project;
 
 use super::error::Overloaded;
diff --git a/tower/src/make/make_service/shared.rs b/tower/src/make/make_service/shared.rs
index 2b2bc02..8855937 100644
--- a/tower/src/make/make_service/shared.rs
+++ b/tower/src/make/make_service/shared.rs
@@ -12,10 +12,10 @@ use tower_service::Service;
 /// # use std::task::{Context, Poll};
 /// # use std::pin::Pin;
 /// # use std::convert::Infallible;
+/// use std::future::{Ready, ready};
 /// use tower::make::{MakeService, Shared};
 /// use tower::buffer::Buffer;
 /// use tower::Service;
-/// use futures::future::{Ready, ready};
 ///
 /// // An example connection type
 /// struct Connection {}
@@ -93,13 +93,13 @@ where
     }
 
     fn call(&mut self, _target: T) -> Self::Future {
-        SharedFuture::new(futures_util::future::ready(Ok(self.service.clone())))
+        SharedFuture::new(std::future::ready(Ok(self.service.clone())))
     }
 }
 
 opaque_future! {
     /// Response future from [`Shared`] services.
-    pub type SharedFuture<S> = futures_util::future::Ready<Result<S, Infallible>>;
+    pub type SharedFuture<S> = std::future::Ready<Result<S, Infallible>>;
 }
 
 #[cfg(test)]
@@ -107,7 +107,7 @@ mod tests {
     use super::*;
     use crate::make::MakeService;
     use crate::service_fn;
-    use futures::future::poll_fn;
+    use std::future::poll_fn;
 
     async fn echo<R>(req: R) -> Result<R, Infallible> {
         Ok(req)
diff --git a/tower/src/retry/budget/mod.rs b/tower/src/retry/budget/mod.rs
index 3d1d2b8..c30cc1a 100644
--- a/tower/src/retry/budget/mod.rs
+++ b/tower/src/retry/budget/mod.rs
@@ -27,9 +27,8 @@
 //! # Examples
 //!
 //! ```rust
-//! use std::sync::Arc;
+//! use std::{future, sync::Arc};
 //!
-//! use futures_util::future;
 //! use tower::retry::{budget::{Budget, TpsBudget}, Policy};
 //!
 //! type Req = String;
diff --git a/tower/src/retry/future.rs b/tower/src/retry/future.rs
index 7e22184..2c78a62 100644
--- a/tower/src/retry/future.rs
+++ b/tower/src/retry/future.rs
@@ -1,11 +1,10 @@
 //! Future types
 
 use super::{Policy, Retry};
-use futures_core::ready;
 use pin_project_lite::pin_project;
 use std::future::Future;
 use std::pin::Pin;
-use std::task::{Context, Poll};
+use std::task::{ready, Context, Poll};
 use tower_service::Service;
 
 pin_project! {
diff --git a/tower/src/retry/policy.rs b/tower/src/retry/policy.rs
index 57b80a7..683bd60 100644
--- a/tower/src/retry/policy.rs
+++ b/tower/src/retry/policy.rs
@@ -6,7 +6,7 @@ use std::future::Future;
 ///
 /// ```
 /// use tower::retry::Policy;
-/// use futures_util::future;
+/// use std::future;
 ///
 /// type Req = String;
 /// type Res = String;
@@ -91,4 +91,4 @@ pub trait Policy<Req, Res, E> {
 
 // Ensure `Policy` is object safe
 #[cfg(test)]
-fn _obj_safe(_: Box<dyn Policy<(), (), (), Future = futures::future::Ready<()>>>) {}
+fn _obj_safe(_: Box<dyn Policy<(), (), (), Future = std::future::Ready<()>>>) {}
diff --git a/tower/src/spawn_ready/service.rs b/tower/src/spawn_ready/service.rs
index d9573f5..3d5990f 100644
--- a/tower/src/spawn_ready/service.rs
+++ b/tower/src/spawn_ready/service.rs
@@ -1,11 +1,10 @@
 use super::{future::ResponseFuture, SpawnReadyLayer};
 use crate::{util::ServiceExt, BoxError};
-use futures_core::ready;
 use futures_util::future::TryFutureExt;
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tower_service::Service;
 use tracing::Instrument;
diff --git a/tower/src/steer/mod.rs b/tower/src/steer/mod.rs
index d614196..00b3311 100644
--- a/tower/src/steer/mod.rs
+++ b/tower/src/steer/mod.rs
@@ -8,9 +8,8 @@
 //! Here, `GET /` will be sent to the `root` service, while all other requests go to `not_found`.
 //!
 //! ```rust
-//! # use std::task::{Context, Poll};
+//! # use std::task::{Context, Poll, ready};
 //! # use tower_service::Service;
-//! # use futures_util::future::{ready, Ready, poll_fn};
 //! # use tower::steer::Steer;
 //! # use tower::service_fn;
 //! # use tower::util::BoxService;
diff --git a/tower/src/util/boxed/sync.rs b/tower/src/util/boxed/sync.rs
index 57dcfec..23765fc 100644
--- a/tower/src/util/boxed/sync.rs
+++ b/tower/src/util/boxed/sync.rs
@@ -28,7 +28,7 @@ use std::{
 /// # Examples
 ///
 /// ```
-/// use futures_util::future::ready;
+/// use std::future::ready;
 /// # use tower_service::Service;
 /// # use tower::util::{BoxService, service_fn};
 /// // Respond to requests using a closure, but closures cannot be named...
diff --git a/tower/src/util/call_all/common.rs b/tower/src/util/call_all/common.rs
index 9f2490b..55fcc72 100644
--- a/tower/src/util/call_all/common.rs
+++ b/tower/src/util/call_all/common.rs
@@ -1,10 +1,10 @@
-use futures_core::{ready, Stream};
+use futures_core::Stream;
 use pin_project_lite::pin_project;
 use std::{
     fmt,
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tower_service::Service;
 
diff --git a/tower/src/util/call_all/ordered.rs b/tower/src/util/call_all/ordered.rs
index 9a28391..7ab00f7 100644
--- a/tower/src/util/call_all/ordered.rs
+++ b/tower/src/util/call_all/ordered.rs
@@ -24,7 +24,7 @@ pin_project! {
     /// # use std::error::Error;
     /// # use std::rc::Rc;
     /// #
-    /// use futures::future::{ready, Ready};
+    /// use std::future::{ready, Ready};
     /// use futures::StreamExt;
     /// use futures::channel::mpsc;
     /// use tower_service::Service;
diff --git a/tower/src/util/future_service.rs b/tower/src/util/future_service.rs
index c0a36df..cec1720 100644
--- a/tower/src/util/future_service.rs
+++ b/tower/src/util/future_service.rs
@@ -154,7 +154,7 @@ where
             self.state = match &mut self.state {
                 State::Future(fut) => {
                     let fut = Pin::new(fut);
-                    let svc = futures_core::ready!(fut.poll(cx)?);
+                    let svc = std::task::ready!(fut.poll(cx)?);
                     State::Service(svc)
                 }
                 State::Service(svc) => return svc.poll_ready(cx),
@@ -176,8 +176,10 @@ mod tests {
     use super::*;
     use crate::util::{future_service, ServiceExt};
     use crate::Service;
-    use futures::future::{ready, Ready};
-    use std::convert::Infallible;
+    use std::{
+        convert::Infallible,
+        future::{ready, Ready},
+    };
 
     #[tokio::test]
     async fn pending_service_debug_impl() {
@@ -185,7 +187,7 @@ mod tests {
 
         assert_eq!(
             format!("{:?}", pending_svc),
-            "FutureService { state: State::Future(<futures_util::future::ready::Ready<core::result::Result<tower::util::future_service::tests::DebugService, core::convert::Infallible>>>) }"
+            "FutureService { state: State::Future(<core::future::ready::Ready<core::result::Result<tower::util::future_service::tests::DebugService, core::convert::Infallible>>>) }"
         );
 
         pending_svc.ready().await.unwrap();
diff --git a/tower/src/util/mod.rs b/tower/src/util/mod.rs
index 4c56de8..a8d2fc6 100644
--- a/tower/src/util/mod.rs
+++ b/tower/src/util/mod.rs
@@ -139,14 +139,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<u32> for DatabaseService {
     /// #   type Response = Record;
     /// #   type Error = u8;
-    /// #   type Future = futures_util::future::Ready<Result<Record, u8>>;
+    /// #   type Future = std::future::Ready<Result<Record, u8>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: u32) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(Record { name: "Jack".into(), age: 32 }))
+    /// #       std::future::ready(Ok(Record { name: "Jack".into(), age: 32 }))
     /// #   }
     /// # }
     /// #
@@ -208,14 +208,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<u32> for DatabaseService {
     /// #   type Response = Record;
     /// #   type Error = u8;
-    /// #   type Future = futures_util::future::Ready<Result<Record, u8>>;
+    /// #   type Future = std::future::Ready<Result<Record, u8>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: u32) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(Record { name: "Jack".into(), age: 32 }))
+    /// #       std::future::ready(Ok(Record { name: "Jack".into(), age: 32 }))
     /// #   }
     /// # }
     /// #
@@ -275,14 +275,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<u32> for DatabaseService {
     /// #   type Response = String;
     /// #   type Error = Error;
-    /// #   type Future = futures_util::future::Ready<Result<String, Error>>;
+    /// #   type Future = std::future::Ready<Result<String, Error>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: u32) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(String::new()))
+    /// #       std::future::ready(Ok(String::new()))
     /// #   }
     /// # }
     /// #
@@ -370,14 +370,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<u32> for DatabaseService {
     /// #   type Response = Vec<Record>;
     /// #   type Error = DbError;
-    /// #   type Future = futures_util::future::Ready<Result<Vec<Record>, DbError>>;
+    /// #   type Future = std::future::Ready<Result<Vec<Record>, DbError>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: u32) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(vec![Record { name: "Jack".into(), age: 32 }]))
+    /// #       std::future::ready(Ok(vec![Record { name: "Jack".into(), age: 32 }]))
     /// #   }
     /// # }
     /// #
@@ -430,14 +430,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<u32> for DatabaseService {
     /// #   type Response = Record;
     /// #   type Error = DbError;
-    /// #   type Future = futures_util::future::Ready<Result<Record, DbError>>;
+    /// #   type Future = std::future::Ready<Result<Record, DbError>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: u32) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(Record { name: "Jack".into(), age: 32 }))
+    /// #       std::future::ready(Ok(Record { name: "Jack".into(), age: 32 }))
     /// #   }
     /// # }
     /// #
@@ -494,14 +494,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<u32> for DatabaseService {
     /// #   type Response = String;
     /// #   type Error = u8;
-    /// #   type Future = futures_util::future::Ready<Result<String, u8>>;
+    /// #   type Future = std::future::Ready<Result<String, u8>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: u32) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(String::new()))
+    /// #       std::future::ready(Ok(String::new()))
     /// #   }
     /// # }
     /// #
@@ -565,14 +565,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<String> for DatabaseService {
     /// #   type Response = String;
     /// #   type Error = u8;
-    /// #   type Future = futures_util::future::Ready<Result<String, u8>>;
+    /// #   type Future = std::future::Ready<Result<String, u8>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: String) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(String::new()))
+    /// #       std::future::ready(Ok(String::new()))
     /// #   }
     /// # }
     /// #
@@ -633,14 +633,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<u32> for DatabaseService {
     /// #   type Response = String;
     /// #   type Error = DbError;
-    /// #   type Future = futures_util::future::Ready<Result<String, DbError>>;
+    /// #   type Future = std::future::Ready<Result<String, DbError>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: u32) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(String::new()))
+    /// #       std::future::ready(Ok(String::new()))
     /// #   }
     /// # }
     /// #
@@ -706,14 +706,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<u32> for DatabaseService {
     /// #   type Response = String;
     /// #   type Error = DbError;
-    /// #   type Future = futures_util::future::Ready<Result<String, DbError>>;
+    /// #   type Future = std::future::Ready<Result<String, DbError>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: u32) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(String::new()))
+    /// #       std::future::ready(Ok(String::new()))
     /// #   }
     /// # }
     /// #
@@ -808,14 +808,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<u32> for DatabaseService {
     /// #   type Response = Record;
     /// #   type Error = DbError;
-    /// #   type Future = futures_util::future::Ready<Result<Record, DbError>>;
+    /// #   type Future = std::future::Ready<Result<Record, DbError>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: u32) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(()))
+    /// #       std::future::ready(Ok(()))
     /// #   }
     /// # }
     /// #
@@ -894,14 +894,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// # impl Service<u32> for DatabaseService {
     /// #   type Response = Record;
     /// #   type Error = DbError;
-    /// #   type Future = futures_util::future::Ready<Result<Record, DbError>>;
+    /// #   type Future = std::future::Ready<Result<Record, DbError>>;
     /// #
     /// #   fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
     /// #       Poll::Ready(Ok(()))
     /// #   }
     /// #
     /// #   fn call(&mut self, request: u32) -> Self::Future {
-    /// #       futures_util::future::ready(Ok(()))
+    /// #       std::future::ready(Ok(()))
     /// #   }
     /// # }
     /// #
diff --git a/tower/src/util/oneshot.rs b/tower/src/util/oneshot.rs
index 114b2f8..ad4b4f1 100644
--- a/tower/src/util/oneshot.rs
+++ b/tower/src/util/oneshot.rs
@@ -1,10 +1,9 @@
-use futures_core::ready;
 use pin_project_lite::pin_project;
 use std::{
     fmt,
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tower_service::Service;
 
diff --git a/tower/src/util/optional/future.rs b/tower/src/util/optional/future.rs
index 7d289b7..2912945 100644
--- a/tower/src/util/optional/future.rs
+++ b/tower/src/util/optional/future.rs
@@ -1,10 +1,9 @@
 use super::error;
-use futures_core::ready;
 use pin_project_lite::pin_project;
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 
 pin_project! {
diff --git a/tower/src/util/ready.rs b/tower/src/util/ready.rs
index 750db87..2f67f3f 100644
--- a/tower/src/util/ready.rs
+++ b/tower/src/util/ready.rs
@@ -1,10 +1,9 @@
 use std::{fmt, marker::PhantomData};
 
-use futures_core::ready;
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 use tower_service::Service;
 


Test patch:
diff --git a/tower-test/Cargo.toml b/tower-test/Cargo.toml
index 24c7d7e..72af1ae 100644
--- a/tower-test/Cargo.toml
+++ b/tower-test/Cargo.toml
@@ -20,7 +20,6 @@ categories = ["asynchronous", "network-programming"]
 edition = "2018"
 
 [dependencies]
-futures-util = { workspace = true }
 tokio = { workspace = true, features = ["sync"] }
 tokio-test = { workspace = true }
 tower-layer = { version = "0.3", path = "../tower-layer" }
diff --git a/tower-test/src/mock/future.rs b/tower-test/src/mock/future.rs
index cda4518..ec466c6 100644
--- a/tower-test/src/mock/future.rs
+++ b/tower-test/src/mock/future.rs
@@ -1,14 +1,13 @@
 //! Future types
 
 use crate::mock::error::{self, Error};
-use futures_util::ready;
 use pin_project_lite::pin_project;
 use tokio::sync::oneshot;
 
 use std::{
     future::Future,
     pin::Pin,
-    task::{Context, Poll},
+    task::{ready, Context, Poll},
 };
 
 pin_project! {
diff --git a/tower/tests/builder.rs b/tower/tests/builder.rs
index 574766b..9f67b03 100644
--- a/tower/tests/builder.rs
+++ b/tower/tests/builder.rs
@@ -1,7 +1,7 @@
 #![cfg(all(feature = "buffer", feature = "limit", feature = "retry"))]
 mod support;
-use futures_util::{future::Ready, pin_mut};
-use std::time::Duration;
+use futures_util::pin_mut;
+use std::{future::Ready, time::Duration};
 use tower::builder::ServiceBuilder;
 use tower::retry::Policy;
 use tower::util::ServiceExt;
diff --git a/tower/tests/filter/async_filter.rs b/tower/tests/filter/async_filter.rs
index 4a0a5a9..5657c53 100644
--- a/tower/tests/filter/async_filter.rs
+++ b/tower/tests/filter/async_filter.rs
@@ -1,8 +1,8 @@
 #![cfg(feature = "filter")]
 #[path = "../support.rs"]
 mod support;
-use futures_util::{future::poll_fn, pin_mut};
-use std::future::Future;
+use futures_util::future::pin_mut;
+use std::future::{poll_fn, Future};
 use tower::filter::{error::Error, AsyncFilter};
 use tower_service::Service;
 use tower_test::{assert_request_eq, mock};
diff --git a/tower/tests/retry/main.rs b/tower/tests/retry/main.rs
index 7ce220b..722e3dd 100644
--- a/tower/tests/retry/main.rs
+++ b/tower/tests/retry/main.rs
@@ -2,7 +2,8 @@
 #[path = "../support.rs"]
 mod support;
 
-use futures_util::future;
+use std::future;
+
 use tokio_test::{assert_pending, assert_ready_err, assert_ready_ok, task};
 use tower::retry::Policy;
 use tower_test::{assert_request_eq, mock};
diff --git a/tower/tests/steer/main.rs b/tower/tests/steer/main.rs
index 1ff08d3..e3b51ef 100644
--- a/tower/tests/steer/main.rs
+++ b/tower/tests/steer/main.rs
@@ -2,8 +2,10 @@
 #[path = "../support.rs"]
 mod support;
 
-use futures_util::future::{ready, Ready};
-use std::task::{Context, Poll};
+use std::{
+    future::{ready, Ready},
+    task::{Context, Poll},
+};
 use tower::steer::Steer;
 use tower_service::Service;
 
@@ -35,9 +37,7 @@ async fn pick_correctly() {
     let srvs = vec![MyService(42, true), MyService(57, true)];
     let mut st = Steer::new(srvs, |_: &_, _: &[_]| 1);
 
-    futures_util::future::poll_fn(|cx| st.poll_ready(cx))
-        .await
-        .unwrap();
+    std::future::poll_fn(|cx| st.poll_ready(cx)).await.unwrap();
     let r = st.call(String::from("foo")).await.unwrap();
     assert_eq!(r, 57);
 }
@@ -49,7 +49,7 @@ async fn pending_all_ready() {
     let srvs = vec![MyService(42, true), MyService(57, false)];
     let mut st = Steer::new(srvs, |_: &_, _: &[_]| 0);
 
-    let p = futures_util::poll!(futures_util::future::poll_fn(|cx| st.poll_ready(cx)));
+    let p = futures_util::poll!(std::future::poll_fn(|cx| st.poll_ready(cx)));
     match p {
         Poll::Pending => (),
         _ => panic!(
diff --git a/tower/tests/support.rs b/tower/tests/support.rs
index b547082..9ff8d37 100644
--- a/tower/tests/support.rs
+++ b/tower/tests/support.rs
@@ -1,7 +1,7 @@
 #![allow(dead_code)]
 
-use futures::future;
 use std::fmt;
+use std::future;
 use std::pin::Pin;
 use std::task::{Context, Poll};
 use tokio::sync::mpsc;
diff --git a/tower/tests/util/call_all.rs b/tower/tests/util/call_all.rs
index 6c3b195..7389ed7 100644
--- a/tower/tests/util/call_all.rs
+++ b/tower/tests/util/call_all.rs
@@ -1,11 +1,8 @@
 use super::support;
 use futures_core::Stream;
-use futures_util::{
-    future::{ready, Ready},
-    pin_mut,
-};
+use futures_util::pin_mut;
 use std::fmt;
-use std::future::Future;
+use std::future::{ready, Future, Ready};
 use std::task::{Context, Poll};
 use std::{cell::Cell, rc::Rc};
 use tokio_test::{assert_pending, assert_ready, task};
diff --git a/tower/tests/util/service_fn.rs b/tower/tests/util/service_fn.rs
index ac6bf06..d978756 100644
--- a/tower/tests/util/service_fn.rs
+++ b/tower/tests/util/service_fn.rs
@@ -1,4 +1,4 @@
-use futures_util::future::ready;
+use std::future::ready;
 use tower::util::service_fn;
 use tower_service::Service;