Repository: tower-rs/tower
Pull request #515 (2021-01-09 16:03:26)

Fix all the docs links
This goes through all the files and adds/fixes docs links. Also fixes typos and wordings in a few places.

davidpdrsn: I've added `#![deny(broken_intra_doc_links)]` to all crates now.

Patch:
diff --git a/tower-layer/src/identity.rs b/tower-layer/src/identity.rs
index 62a781a..5ce805b 100644
--- a/tower-layer/src/identity.rs
+++ b/tower-layer/src/identity.rs
@@ -3,21 +3,25 @@ use std::fmt;
 
 /// A no-op middleware.
 ///
-/// When wrapping a `Service`, the `Identity` layer returns the provided
+/// When wrapping a [`Service`], the [`Identity`] layer returns the provided
 /// service without modifying it.
+///
+/// [`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html
 #[derive(Default, Clone)]
 pub struct Identity {
     _p: (),
 }
 
 impl Identity {
-    /// Create a new `Identity` value
+    /// Create a new [`Identity`] value
     pub fn new() -> Identity {
         Identity { _p: () }
     }
 }
 
-/// Decorates a `Service`, transforming either the request or the response.
+/// Decorates a [`Service`], transforming either the request or the response.
+///
+/// [`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html
 impl<S> Layer<S> for Identity {
     type Service = S;
 
diff --git a/tower-layer/src/lib.rs b/tower-layer/src/lib.rs
index f69c6c5..0455903 100644
--- a/tower-layer/src/lib.rs
+++ b/tower-layer/src/lib.rs
@@ -5,6 +5,7 @@
     rust_2018_idioms,
     unreachable_pub
 )]
+#![deny(broken_intra_doc_links)]
 
 //! Layer traits and extensions.
 //!
diff --git a/tower-service/src/lib.rs b/tower-service/src/lib.rs
index ba90c0d..64e5515 100644
--- a/tower-service/src/lib.rs
+++ b/tower-service/src/lib.rs
@@ -5,6 +5,7 @@
     rust_2018_idioms,
     unreachable_pub
 )]
+#![deny(broken_intra_doc_links)]
 
 //! Definition of the core `Service` trait to Tower
 //!
diff --git a/tower/src/balance/error.rs b/tower/src/balance/error.rs
index 59ddbf5..4d47630 100644
--- a/tower/src/balance/error.rs
+++ b/tower/src/balance/error.rs
@@ -1,4 +1,6 @@
-//! Error types for the `tower::balance` middleware.
+//! Error types for the [`tower::balance`] middleware.
+//!
+//! [`tower::balance`]: crate::balance
 
 use std::fmt;
 
diff --git a/tower/src/balance/mod.rs b/tower/src/balance/mod.rs
index bc01208..4e27f4a 100644
--- a/tower/src/balance/mod.rs
+++ b/tower/src/balance/mod.rs
@@ -15,7 +15,7 @@
 //! [Power of Two Random Choices]: http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf
 //!
 //! Second, [`pool`] implements a dynamically sized pool of services. It estimates the overall
-//! current load by tracking successful and unsuccessful calls to `poll_ready`, and uses an
+//! current load by tracking successful and unsuccessful calls to [`poll_ready`], and uses an
 //! exponentially weighted moving average to add (using [`MakeService`]) or remove (by dropping)
 //! services in response to increases or decreases in load. Use this if you are able to
 //! dynamically add more service endpoints to the system to handle added load.
@@ -52,7 +52,9 @@
 //! }
 //! # }
 //! ```
+//!
 //! [`MakeService`]: crate::MakeService
+//! [`poll_ready`]: crate::Service::poll_ready
 
 pub mod error;
 pub mod p2c;
diff --git a/tower/src/balance/p2c/layer.rs b/tower/src/balance/p2c/layer.rs
index 6dbfd97..90ff8cf 100644
--- a/tower/src/balance/p2c/layer.rs
+++ b/tower/src/balance/p2c/layer.rs
@@ -7,7 +7,7 @@ use tower_layer::Layer;
 ///
 /// This construction may seem a little odd at first glance. This is not a layer that takes
 /// requests and produces responses in the traditional sense. Instead, it is more like
-/// [`MakeService`] in that it takes service _descriptors_ (see `Target` on `MakeService`)
+/// [`MakeService`] in that it takes service _descriptors_ (see `Target` on [`MakeService`])
 /// and produces _services_. Since [`Balance`] spreads requests across a _set_ of services,
 /// the inner service should produce a [`Discover`], not just a single
 /// [`Service`], given a service descriptor.
diff --git a/tower/src/balance/p2c/mod.rs b/tower/src/balance/p2c/mod.rs
index 41d8280..0d4203c 100644
--- a/tower/src/balance/p2c/mod.rs
+++ b/tower/src/balance/p2c/mod.rs
@@ -16,7 +16,7 @@
 //!
 //! The balance service and layer implementations rely on _service discovery_ to provide the
 //! underlying set of services to balance requests across. This happens through the
-//! [`Discover`](crate::discover::Discover) trait, which is essentially a `Stream` that indicates
+//! [`Discover`](crate::discover::Discover) trait, which is essentially a [`Stream`] that indicates
 //! when services become available or go away. If you have a fixed set of services, consider using
 //! [`ServiceList`](crate::discover::ServiceList).
 //!
@@ -27,6 +27,7 @@
 //!
 //! [Power of Two Random Choices]: http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf
 //! [finagle]: https://twitter.github.io/finagle/guide/Clients.html#power-of-two-choices-p2c-least-loaded
+//! [`Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html
 
 mod layer;
 mod make;
diff --git a/tower/src/balance/p2c/service.rs b/tower/src/balance/p2c/service.rs
index 8554d2d..06476aa 100644
--- a/tower/src/balance/p2c/service.rs
+++ b/tower/src/balance/p2c/service.rs
@@ -22,10 +22,10 @@ use tracing::{debug, trace};
 ///
 /// See the [module-level documentation](..) for details.
 ///
-/// Note that `Balance` requires that the `Discover` you use is `Unpin` in order to implement
-/// `Service`. This is because it needs to be accessed from `Service::poll_ready`, which takes
-/// `&mut self`. You can achieve this easily by wrapping your `Discover` in [`Box::pin`] before you
-/// construct the `Balance` instance. For more details, see [#319].
+/// Note that [`Balance`] requires that the [`Discover`] you use is [`Unpin`] in order to implement
+/// [`Service`]. This is because it needs to be accessed from [`Service::poll_ready`], which takes
+/// `&mut self`. You can achieve this easily by wrapping your [`Discover`] in [`Box::pin`] before you
+/// construct the [`Balance`] instance. For more details, see [#319].
 ///
 /// [`Box::pin`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.pin
 /// [#319]: https://github.com/tower-rs/tower/issues/319
diff --git a/tower/src/buffer/error.rs b/tower/src/buffer/error.rs
index f875390..f046cbc 100644
--- a/tower/src/buffer/error.rs
+++ b/tower/src/buffer/error.rs
@@ -3,7 +3,10 @@
 use crate::BoxError;
 use std::{fmt, sync::Arc};
 
-/// An error produced by a `Service` wrapped by a `Buffer`
+/// An error produced by a [`Service`] wrapped by a [`Buffer`]
+///
+/// [`Service`]: crate::Service
+/// [`Buffer`]: crate::buffer::Buffer
 #[derive(Debug)]
 pub struct ServiceError {
     inner: Arc<BoxError>,
diff --git a/tower/src/buffer/future.rs b/tower/src/buffer/future.rs
index 6aeff36..40774fc 100644
--- a/tower/src/buffer/future.rs
+++ b/tower/src/buffer/future.rs
@@ -1,4 +1,6 @@
-//! Future types for the `Buffer` middleware.
+//! Future types for the [`Buffer`] middleware.
+//!
+//! [`Buffer`]: crate::buffer::Buffer
 
 use super::{error::Closed, message};
 use futures_core::ready;
diff --git a/tower/src/buffer/layer.rs b/tower/src/buffer/layer.rs
index f20631e..d68d3e0 100644
--- a/tower/src/buffer/layer.rs
+++ b/tower/src/buffer/layer.rs
@@ -15,20 +15,24 @@ pub struct BufferLayer<Request> {
 }
 
 impl<Request> BufferLayer<Request> {
-    /// Creates a new `BufferLayer` with the provided `bound`.
+    /// Creates a new [`BufferLayer`] with the provided `bound`.
     ///
     /// `bound` gives the maximal number of requests that can be queued for the service before
     /// backpressure is applied to callers.
     ///
     /// # A note on choosing a `bound`
     ///
-    /// When `Buffer`'s implementation of `poll_ready` returns `Poll::Ready`, it reserves a
-    /// slot in the channel for the forthcoming `call()`. However, if this call doesn't arrive,
+    /// When [`Buffer`]'s implementation of [`poll_ready`] returns [`Poll::Ready`], it reserves a
+    /// slot in the channel for the forthcoming [`call`]. However, if this call doesn't arrive,
     /// this reserved slot may be held up for a long time. As a result, it's advisable to set
-    /// `bound` to be at least the maximum number of concurrent requests the `Buffer` will see.
+    /// `bound` to be at least the maximum number of concurrent requests the [`Buffer`] will see.
     /// If you do not, all the slots in the buffer may be held up by futures that have just called
-    /// `poll_ready` but will not issue a `call`, which prevents other senders from issuing new
+    /// [`poll_ready`] but will not issue a [`call`], which prevents other senders from issuing new
     /// requests.
+    ///
+    /// [`Poll::Ready`]: std::task::Poll::Ready
+    /// [`call`]: crate::Service::call
+    /// [`poll_ready`]: crate::Service::poll_ready
     pub fn new(bound: usize) -> Self {
         BufferLayer {
             bound,
diff --git a/tower/src/buffer/mod.rs b/tower/src/buffer/mod.rs
index 6feb61a..6255164 100644
--- a/tower/src/buffer/mod.rs
+++ b/tower/src/buffer/mod.rs
@@ -1,7 +1,7 @@
 //! Middleware that provides a buffered mpsc channel to a service.
 //!
 //! Sometimes you want to give out multiple handles to a single service, and allow each handle to
-//! enqueue requests. That is, you want a `Service` to be `Clone`. This module allows you to do
+//! enqueue requests. That is, you want a [`Service`] to be [`Clone`]. This module allows you to do
 //! that by placing the service behind a multi-producer, single-consumer buffering channel. Clients
 //! enqueue requests by sending on the channel from any of the handles ([`Buffer`]), and the single
 //! service running elsewhere (usually spawned) receives and services the requests one by one. Each
@@ -33,6 +33,8 @@
 //!     }
 //! }
 //! ```
+//!
+//! [`Service`]: crate::Service
 
 pub mod error;
 pub mod future;
diff --git a/tower/src/buffer/service.rs b/tower/src/buffer/service.rs
index ff414bf..36b8f2f 100644
--- a/tower/src/buffer/service.rs
+++ b/tower/src/buffer/service.rs
@@ -38,7 +38,7 @@ where
     T: Service<Request>,
     T::Error: Into<crate::BoxError>,
 {
-    /// Creates a new `Buffer` wrapping `service`.
+    /// Creates a new [`Buffer`] wrapping `service`.
     ///
     /// `bound` gives the maximal number of requests that can be queued for the service before
     /// backpressure is applied to callers.
@@ -48,13 +48,17 @@ where
     ///
     /// # A note on choosing a `bound`
     ///
-    /// When `Buffer`'s implementation of `poll_ready` returns `Poll::Ready`, it reserves a
-    /// slot in the channel for the forthcoming `call()`. However, if this call doesn't arrive,
+    /// When [`Buffer`]'s implementation of [`poll_ready`] returns [`Poll::Ready`], it reserves a
+    /// slot in the channel for the forthcoming [`call`]. However, if this call doesn't arrive,
     /// this reserved slot may be held up for a long time. As a result, it's advisable to set
-    /// `bound` to be at least the maximum number of concurrent requests the `Buffer` will see.
+    /// `bound` to be at least the maximum number of concurrent requests the [`Buffer`] will see.
     /// If you do not, all the slots in the buffer may be held up by futures that have just called
-    /// `poll_ready` but will not issue a `call`, which prevents other senders from issuing new
+    /// [`poll_ready`] but will not issue a [`call`], which prevents other senders from issuing new
     /// requests.
+    ///
+    /// [`Poll::Ready`]: std::task::Poll::Ready
+    /// [`call`]: crate::Service::call
+    /// [`poll_ready`]: crate::Service::poll_ready
     pub fn new(service: T, bound: usize) -> Self
     where
         T: Send + 'static,
@@ -67,10 +71,10 @@ where
         service
     }
 
-    /// Creates a new `Buffer` wrapping `service`, but returns the background worker.
+    /// Creates a new [`Buffer`] wrapping `service`, but returns the background worker.
     ///
-    /// This is useful if you do not want to spawn directly onto the `tokio` runtime
-    /// but instead want to use your own executor. This will return the `Buffer` and
+    /// This is useful if you do not want to spawn directly onto the tokio runtime
+    /// but instead want to use your own executor. This will return the [`Buffer`] and
     /// the background `Worker` that you can then spawn.
     pub fn pair(service: T, bound: usize) -> (Buffer<T, Request>, Worker<T, Request>)
     where
diff --git a/tower/src/builder/mod.rs b/tower/src/builder/mod.rs
index 03ea919..f54fd7c 100644
--- a/tower/src/builder/mod.rs
+++ b/tower/src/builder/mod.rs
@@ -6,7 +6,7 @@ use std::fmt;
 
 /// Declaratively construct [`Service`] values.
 ///
-/// `ServiceBuilder` provides a [builder-like interface][builder] for composing
+/// [`ServiceBuilder`] provides a [builder-like interface][builder] for composing
 /// layers to be applied to a [`Service`].
 ///
 /// # Service
@@ -14,11 +14,10 @@ use std::fmt;
 /// A [`Service`] is a trait representing an asynchronous function of a request
 /// to a response. It is similar to `async fn(Request) -> Result<Response, Error>`.
 ///
-/// A `Service` is typically bound to a single transport, such as a TCP
+/// A [`Service`] is typically bound to a single transport, such as a TCP
 /// connection.  It defines how _all_ inbound or outbound requests are handled
 /// by that connection.
 ///
-///
 /// [builder]: https://doc.rust-lang.org/1.0.0/style/ownership/builders.html
 ///
 /// # Order
@@ -67,7 +66,7 @@ use std::fmt;
 ///
 /// # Examples
 ///
-/// A `Service` stack with a single layer:
+/// A [`Service`] stack with a single layer:
 ///
 /// ```
 /// # use tower::Service;
@@ -83,8 +82,8 @@ use std::fmt;
 /// # }
 /// ```
 ///
-/// A `Service` stack with _multiple_ layers that contain rate limiting,
-/// in-flight request limits, and a channel-backed, clonable `Service`:
+/// A [`Service`] stack with _multiple_ layers that contain rate limiting,
+/// in-flight request limits, and a channel-backed, clonable [`Service`]:
 ///
 /// ```
 /// # use tower::Service;
@@ -100,6 +99,7 @@ use std::fmt;
 /// # ;
 /// # }
 /// ```
+///
 /// [`Service`]: crate::Service
 #[derive(Clone)]
 pub struct ServiceBuilder<L> {
@@ -113,7 +113,7 @@ impl Default for ServiceBuilder<Identity> {
 }
 
 impl ServiceBuilder<Identity> {
-    /// Create a new `ServiceBuilder`.
+    /// Create a new [`ServiceBuilder`].
     pub fn new() -> Self {
         ServiceBuilder {
             layer: Identity::new(),
@@ -122,7 +122,7 @@ impl ServiceBuilder<Identity> {
 }
 
 impl<L> ServiceBuilder<L> {
-    /// Add a new layer `T` into the `ServiceBuilder`.
+    /// Add a new layer `T` into the [`ServiceBuilder`].
     ///
     /// This wraps the inner service with the service provided by a user-defined
     /// [`Layer`]. The provided layer must implement the [`Layer`] trait.
@@ -386,11 +386,11 @@ impl<L> ServiceBuilder<L> {
     /// This wraps the inner service with an instance of the [`Then`]
     /// middleware.
     ///
-    /// This is similar to the [`map_response`] and [`map_err] functions,
+    /// This is similar to the [`map_response`] and [`map_err`] functions,
     /// except that the *same* function is invoked when the service's future
     /// completes, whether it completes successfully or fails. This function
-    /// takes the `Result` returned by the service's future, and returns a
-    /// `Result`.
+    /// takes the [`Result`] returned by the service's future, and returns a
+    /// [`Result`].
     ///
     /// See the documentation for the [`then` combinator] for details.
     ///
@@ -410,9 +410,10 @@ impl<L> ServiceBuilder<L> {
     }
 
     /// Wrap the service `S` with the middleware provided by this
-    /// `ServiceBuilder`'s [`Layer`]s, returning a new `Service`.
+    /// [`ServiceBuilder`]'s [`Layer`]'s, returning a new [`Service`].
     ///
     /// [`Layer`]: crate::Layer
+    /// [`Service`]: crate::Service
     pub fn service<S>(&self, service: S) -> L::Service
     where
         L: Layer<S>,
diff --git a/tower/src/discover/list.rs b/tower/src/discover/list.rs
index c848d53..768eb54 100644
--- a/tower/src/discover/list.rs
+++ b/tower/src/discover/list.rs
@@ -10,7 +10,7 @@ use tower_service::Service;
 
 /// Static service discovery based on a predetermined list of services.
 ///
-/// `ServiceList` is created with an initial list of services. The discovery
+/// [`ServiceList`] is created with an initial list of services. The discovery
 /// process will yield this list once and do nothing after.
 #[pin_project]
 #[derive(Debug)]
diff --git a/tower/src/discover/mod.rs b/tower/src/discover/mod.rs
index 683b914..3b3ba21 100644
--- a/tower/src/discover/mod.rs
+++ b/tower/src/discover/mod.rs
@@ -2,11 +2,11 @@
 //!
 //! This module provides the [`Change`] enum, which indicates the arrival or departure of a service
 //! from a collection of similar services. Most implementations should use the [`Discover`] trait
-//! in their bounds to indicate that they can handle services coming and going. `Discover` itself
-//! is primarily a convenience wrapper around `TryStream<Ok = Change>`.
+//! in their bounds to indicate that they can handle services coming and going. [`Discover`] itself
+//! is primarily a convenience wrapper around [`TryStream<Ok = Change>`][`TryStream`].
 //!
 //! Every discovered service is assigned an identifier that is distinct among the currently active
-//! services. If that service later goes away, a `Change::Remove` is yielded with that service's
+//! services. If that service later goes away, a [`Change::Remove`] is yielded with that service's
 //! identifier. From that point forward, the identifier may be re-used.
 //!
 //! # Examples
@@ -30,6 +30,8 @@
 //!     }
 //! }
 //! ```
+//!
+//! [`TryStream`]: https://docs.rs/futures/latest/futures/stream/trait.TryStream.html
 
 mod error;
 mod list;
@@ -53,10 +55,12 @@ use std::{
 pub trait Discover: Sealed<Change<(), ()>> {
     /// A unique identifier for each active service.
     ///
-    /// An identifier can be re-used once a `Change::Remove` has been yielded for its service.
+    /// An identifier can be re-used once a [`Change::Remove`] has been yielded for its service.
     type Key: Eq;
 
-    /// The type of `Service` yielded by this `Discover`.
+    /// The type of [`Service`] yielded by this [`Discover`].
+    ///
+    /// [`Service`]: crate::Service
     type Service;
 
     /// Error produced during discovery
diff --git a/tower/src/filter/mod.rs b/tower/src/filter/mod.rs
index 2b7230a..e6b0491 100644
--- a/tower/src/filter/mod.rs
+++ b/tower/src/filter/mod.rs
@@ -2,13 +2,13 @@
 //! a predicate.
 //!
 //! A predicate takes some request type and returns a `Result<Request, Error>`.
-//! If the predicate returns `Ok`, the inner service is called with the request
+//! If the predicate returns [`Ok`], the inner service is called with the request
 //! returned by the predicate &mdash; which may be the original request or a
-//! modified one. If the predicate returns `Err`, the request is rejected and
+//! modified one. If the predicate returns [`Err`], the request is rejected and
 //! the inner service is not called.
 //!
 //! Predicates may either be synchronous (simple functions from a `Request` to
-//! a `Result`) or asynchronous (functions returning `Future`s). Separate
+//! a [`Result`]) or asynchronous (functions returning [`Future`]s). Separate
 //! traits, [`Predicate`] and [`AsyncPredicate`], represent these two types of
 //! predicate. Note that when it is not necessary to await some other
 //! asynchronous operation in the predicate, the synchronous predicate should be
@@ -17,11 +17,12 @@
 //! The predicate traits are implemented for closures and function pointers.
 //! However, users may also implement them for other types, such as when the
 //! predicate requires some state carried between requests. For example,
-//! `Predicate` could be implemented for a type that rejects a fixed set of
+//! [`Predicate`] could be implemented for a type that rejects a fixed set of
 //! requests by checking if they are contained by a a [`HashSet`] or other
 //! collection.
 //!
-//! [`HashSet`]: std::sync::HashSet
+//! [`Future`]: std::future::Future
+//! [`HashSet`]: std::collections::HashSet
 pub mod future;
 mod layer;
 mod predicate;
@@ -59,12 +60,12 @@ pub struct AsyncFilter<T, U> {
 // ==== impl Filter ====
 
 impl<T, U> Filter<T, U> {
-    /// Returns a new `Filter` service wrapping `inner`.
+    /// Returns a new [`Filter`] service wrapping `inner`.
     pub fn new(inner: T, predicate: U) -> Self {
         Self { inner, predicate }
     }
 
-    /// Returns a new [`Layer`] that wraps services with a `Filter` service
+    /// Returns a new [`Layer`] that wraps services with a [`Filter`] service
     /// with the given [`Predicate`].
     ///
     /// [`Layer`]: crate::Layer
@@ -98,12 +99,12 @@ where
 // ==== impl AsyncFilter ====
 
 impl<T, U> AsyncFilter<T, U> {
-    /// Returns a new `AsyncFilter` service wrapping `inner`.
+    /// Returns a new [`AsyncFilter`] service wrapping `inner`.
     pub fn new(inner: T, predicate: U) -> Self {
         Self { inner, predicate }
     }
 
-    /// Returns a new [`Layer`] that wraps services with an `AsyncFilter`
+    /// Returns a new [`Layer`] that wraps services with an [`AsyncFilter`]
     /// service with the given [`AsyncPredicate`].
     ///
     /// [`Layer`]: crate::Layer
diff --git a/tower/src/filter/predicate.rs b/tower/src/filter/predicate.rs
index e1f5c22..181bc96 100644
--- a/tower/src/filter/predicate.rs
+++ b/tower/src/filter/predicate.rs
@@ -3,31 +3,37 @@ use std::future::Future;
 
 /// Checks a request asynchronously.
 pub trait AsyncPredicate<Request> {
-    /// The future returned by `check`.
+    /// The future returned by [`check`].
+    ///
+    /// [`check`]: crate::filter::AsyncPredicate::check
     type Future: Future<Output = Result<Self::Request, BoxError>>;
 
-    /// The type of requests returned by `check`.
+    /// The type of requests returned by [`check`].
     ///
     /// This request is forwarded to the inner service if the predicate
     /// succeeds.
+    ///
+    /// [`check`]: crate::filter::AsyncPredicate::check
     type Request;
 
     /// Check whether the given request should be forwarded.
     ///
-    /// If the future resolves with `Ok`, the request is forwarded to the inner service.
+    /// If the future resolves with [`Ok`], the request is forwarded to the inner service.
     fn check(&mut self, request: Request) -> Self::Future;
 }
 /// Checks a request synchronously.
 pub trait Predicate<Request> {
-    /// The type of requests returned by `check`.
+    /// The type of requests returned by [`check`].
     ///
     /// This request is forwarded to the inner service if the predicate
     /// succeeds.
+    ///
+    /// [`check`]: crate::filter::Predicate::check
     type Request;
 
     /// Check whether the given request should be forwarded.
     ///
-    /// If the future resolves with `Ok`, the request is forwarded to the inner service.
+    /// If the future resolves with [`Ok`], the request is forwarded to the inner service.
     fn check(&mut self, request: Request) -> Result<Self::Request, BoxError>;
 }
 
diff --git a/tower/src/hedge/mod.rs b/tower/src/hedge/mod.rs
index e4d1347..f2fc650 100644
--- a/tower/src/hedge/mod.rs
+++ b/tower/src/hedge/mod.rs
@@ -30,13 +30,16 @@ type Service<S, P> = select::Select<
     Latency<Histo, S>,
     Delay<DelayPolicy, AsyncFilter<Latency<Histo, S>, PolicyPredicate<P>>>,
 >;
+
 /// A middleware that pre-emptively retries requests which have been outstanding
 /// for longer than a given latency percentile.  If either of the original
 /// future or the retry future completes, that value is used.
 #[derive(Debug)]
 pub struct Hedge<S, P>(Service<S, P>);
 
-/// The Future returned by the hedge Service.
+/// The [`Future`] returned by the [`Hedge`] service.
+///
+/// [`Future`]: std::future::Future
 #[pin_project]
 #[derive(Debug)]
 pub struct Future<S, Request>
@@ -50,11 +53,10 @@ where
 /// A policy which describes which requests can be cloned and then whether those
 /// requests should be retried.
 pub trait Policy<Request> {
-    /// clone_request is called when the request is first received to determine
-    /// if the request is retryable.
+    /// Called when the request is first received to determine if the request is retryable.
     fn clone_request(&self, req: &Request) -> Option<Request>;
-    /// can_retry is called after the hedge timeout to determine if the hedge
-    /// retry should be issued.
+
+    /// Called after the hedge timeout to determine if the hedge retry should be issued.
     fn can_retry(&self, req: &Request) -> bool;
 }
 
@@ -63,12 +65,14 @@ pub trait Policy<Request> {
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct PolicyPredicate<P>(P);
+
 #[doc(hidden)]
 #[derive(Debug)]
 pub struct DelayPolicy {
     histo: Histo,
     latency_percentile: f32,
 }
+
 #[doc(hidden)]
 #[derive(Debug)]
 pub struct SelectPolicy<P> {
diff --git a/tower/src/layer.rs b/tower/src/layer.rs
index 8aa27ee..5d91ff7 100644
--- a/tower/src/layer.rs
+++ b/tower/src/layer.rs
@@ -1,8 +1,14 @@
-//! A collection of `Layer` based tower services
+//! A collection of [`Layer`] based tower services
+//!
+//! [`Layer`]: crate::Layer
 
 pub use tower_layer::Layer;
 
-/// `util` exports an Identity Layer and Chain, a mechanism for chaining them.
+/// Utilities for combining layers
+///
+/// [`Identity`]: crate::layer::util::Identity
+/// [`Layer`]: crate::Layer
+/// [`Stack`]: crate::layer::util::Stack
 pub mod util {
     pub use tower_layer::{Identity, Stack};
 }
diff --git a/tower/src/lib.rs b/tower/src/lib.rs
index c8aafd7..4780d04 100644
--- a/tower/src/lib.rs
+++ b/tower/src/lib.rs
@@ -5,6 +5,7 @@
     rust_2018_idioms,
     unreachable_pub
 )]
+#![deny(broken_intra_doc_links)]
 #![allow(elided_lifetimes_in_paths, clippy::type_complexity)]
 #![cfg_attr(test, allow(clippy::float_cmp))]
 #![cfg_attr(docsrs, feature(doc_cfg))]
diff --git a/tower/src/limit/concurrency/future.rs b/tower/src/limit/concurrency/future.rs
index eda2b3f..103aa11 100644
--- a/tower/src/limit/concurrency/future.rs
+++ b/tower/src/limit/concurrency/future.rs
@@ -1,5 +1,6 @@
-//! Future types
+//! [`Future`] types
 //!
+//! [`Future`]: std::future::Future
 use crate::semaphore::Permit;
 use futures_core::ready;
 use pin_project::pin_project;
@@ -9,7 +10,9 @@ use std::{
     task::{Context, Poll},
 };
 
-/// Future for the `ConcurrencyLimit` service.
+/// Future for the [`ConcurrencyLimit`] service.
+///
+/// [`ConcurrencyLimit`]: crate::limit::ConcurrencyLimit
 #[pin_project]
 #[derive(Debug)]
 pub struct ResponseFuture<T> {
diff --git a/tower/src/load/completion.rs b/tower/src/load/completion.rs
index d938d7a..5040a4a 100644
--- a/tower/src/load/completion.rs
+++ b/tower/src/load/completion.rs
@@ -10,7 +10,7 @@ use std::{
 
 /// Attaches `H`-typed completion tracker to `V` typed values.
 ///
-/// Handles (of type `H`) are intended to be RAII guards that primarily implement `Drop` and update
+/// Handles (of type `H`) are intended to be RAII guards that primarily implement [`Drop`] and update
 /// load metric state as they are dropped. This trait allows implementors to "forward" the handle
 /// to later parts of the request-handling pipeline, so that the handle is only dropped when the
 /// request has truly completed.
@@ -24,10 +24,12 @@ use std::{
 /// once the response future is resolved. This is appropriate when a response is discrete and
 /// cannot comprise multiple messages.
 ///
-/// In many cases, the `Output` type is simply `V`. However, `TrackCompletion` may alter the type
-/// in order to instrument it appropriately. For example, an HTTP `TrackCompletion` may modify the
-/// body type: so a `TrackCompletion` that takes values of type `http::Response<A>` may output
-/// values of type `http::Response<B>`.
+/// In many cases, the `Output` type is simply `V`. However, [`TrackCompletion`] may alter the type
+/// in order to instrument it appropriately. For example, an HTTP [`TrackCompletion`] may modify
+/// the body type: so a [`TrackCompletion`] that takes values of type
+/// [`http::Response<A>`][response] may output values of type [`http::Response<B>`][response].
+///
+/// [response]: https://docs.rs/http/latest/http/response/struct.Response.html
 pub trait TrackCompletion<H, V>: Clone {
     /// The instrumented value type.
     type Output;
@@ -36,13 +38,13 @@ pub trait TrackCompletion<H, V>: Clone {
     fn track_completion(&self, handle: H, value: V) -> Self::Output;
 }
 
-/// A `TrackCompletion` implementation that considers the request completed when the response
+/// A [`TrackCompletion`] implementation that considers the request completed when the response
 /// future is resolved.
 #[derive(Clone, Copy, Debug, Default)]
 #[non_exhaustive]
 pub struct CompleteOnResponse;
 
-/// Attaches a `C`-typed completion tracker to the result of an `F`-typed `Future`.
+/// Attaches a `C`-typed completion tracker to the result of an `F`-typed [`Future`].
 #[pin_project]
 #[derive(Debug)]
 pub struct TrackCompletionFuture<F, C, H> {
diff --git a/tower/src/load/constant.rs b/tower/src/load/constant.rs
index bf985b2..a116d43 100644
--- a/tower/src/load/constant.rs
+++ b/tower/src/load/constant.rs
@@ -1,4 +1,4 @@
-//! A constant `Load` implementation.
+//! A constant [`Load`] implementation.
 
 #[cfg(feature = "discover")]
 use crate::discover::{Change, Discover};
@@ -12,7 +12,7 @@ use pin_project::pin_project;
 use std::task::{Context, Poll};
 use tower_service::Service;
 
-/// Wraps a type so that it implements `Load` and returns a constant load metric.
+/// Wraps a type so that it implements [`Load`] and returns a constant load metric.
 ///
 /// This load estimator is primarily useful for testing.
 #[pin_project]
@@ -57,7 +57,7 @@ where
     }
 }
 
-/// Proxies `Discover` such that all changes are wrapped with a constant load.
+/// Proxies [`Discover`] such that all changes are wrapped with a constant load.
 #[cfg(feature = "discover")]
 #[cfg_attr(docsrs, doc(cfg(feature = "discover")))]
 impl<D: Discover + Unpin, M: Copy> Stream for Constant<D, M> {
diff --git a/tower/src/load/mod.rs b/tower/src/load/mod.rs
index 2ede8c5..2960868 100644
--- a/tower/src/load/mod.rs
+++ b/tower/src/load/mod.rs
@@ -3,9 +3,9 @@
 //! This module provides the [`Load`] trait, which allows measuring how loaded a service is.
 //! It also provides several wrapper types that measure load in different ways:
 //!
-//!  - [`Constant`] — Always returns the same constant load value for a service.
-//!  - [`PendingRequests`] — Measures load by tracking the number of in-flight requests.
-//!  - [`PeakEwma`] — Measures load using a moving average of the peak latency for the service.
+//! - [`Constant`] — Always returns the same constant load value for a service.
+//! - [`PendingRequests`] — Measures load by tracking the number of in-flight requests.
+//! - [`PeakEwma`] — Measures load using a moving average of the peak latency for the service.
 //!
 //! In general, you will want to use one of these when using the types in [`tower::balance`] which
 //! balance services depending on their load. Which load metric to use depends on your exact
@@ -24,7 +24,7 @@
 //!
 //! To support these use-cases, the load estimators in this module are parameterized by the
 //! [`TrackCompletion`] trait, with [`CompleteOnResponse`] as the default type. The behavior of
-//! `CompleteOnOnResponse` is what you would normally expect for a request-response cycle: when the
+//! [`CompleteOnResponse`] is what you would normally expect for a request-response cycle: when the
 //! response is produced, the request is considered "finished", and load goes down. This can be
 //! overriden by your own user-defined type to track more complex request completion semantics. See
 //! the documentation for [`completion`] for more details.
@@ -53,8 +53,10 @@
 //!     }
 //! }
 //! ```
+//!
 //! [`tower::balance`]: crate::balance
 //! [`Discover`]: crate::discover::Discover
+//! [`CompleteOnResponse`]: crate::load::completion::CompleteOnResponse
 // TODO: a custom completion example would be good here
 
 pub mod completion;
diff --git a/tower/src/load/peak_ewma.rs b/tower/src/load/peak_ewma.rs
index 97ec813..4219aa0 100644
--- a/tower/src/load/peak_ewma.rs
+++ b/tower/src/load/peak_ewma.rs
@@ -22,7 +22,7 @@ use tracing::trace;
 
 /// Measures the load of the underlying service using Peak-EWMA load measurement.
 ///
-/// `PeakEwma` implements `Load` with the `Cost` metric that estimates the amount of
+/// [`PeakEwma`] implements [`Load`] with the [`Cost`] metric that estimates the amount of
 /// pending work to an endpoint. Work is calculated by multiplying the
 /// exponentially-weighted moving average (EWMA) of response latencies by the number of
 /// pending requests. The Peak-EWMA algorithm is designed to be especially sensitive to
@@ -161,7 +161,7 @@ impl<S, C> PeakEwma<S, C> {
 
 #[cfg(feature = "discover")]
 impl<D, C> PeakEwmaDiscover<D, C> {
-    /// Wraps a `D`-typed `Discover` so that services have a `PeakEwma` load metric.
+    /// Wraps a `D`-typed [`Discover`] so that services have a [`PeakEwma`] load metric.
     ///
     /// The provided `default_rtt` is used as the default RTT estimate for newly
     /// added services.
@@ -354,8 +354,8 @@ mod tests {
         assert!(8.0 * NANOS_PER_MILLI < load && load < 9.0 * NANOS_PER_MILLI);
     }
 
-    // /// The default RTT estimate decays, so that new nodes are considered if the
-    // /// default RTT is too high.
+    // The default RTT estimate decays, so that new nodes are considered if the default RTT is too
+    // high.
     #[tokio::test]
     async fn compound_decay() {
         time::pause();
diff --git a/tower/src/load/pending_requests.rs b/tower/src/load/pending_requests.rs
index 4b3a350..b1769e9 100644
--- a/tower/src/load/pending_requests.rs
+++ b/tower/src/load/pending_requests.rs
@@ -1,4 +1,4 @@
-//! A `Load` implementation that measures load using the number of in-flight requests.
+//! A [`Load`] implementation that measures load using the number of in-flight requests.
 
 #[cfg(feature = "discover")]
 use crate::discover::{Change, Discover};
@@ -23,11 +23,11 @@ pub struct PendingRequests<S, C = CompleteOnResponse> {
     completion: C,
 }
 
-/// Shared between instances of `PendingRequests` and `Handle` to track active references.
+/// Shared between instances of [`PendingRequests`] and [`Handle`] to track active references.
 #[derive(Clone, Debug, Default)]
 struct RefCount(Arc<()>);
 
-/// Wraps a `D`-typed stream of discovered services with `PendingRequests`.
+/// Wraps a `D`-typed stream of discovered services with [`PendingRequests`].
 #[pin_project]
 #[derive(Debug)]
 #[cfg(feature = "discover")]
@@ -98,7 +98,7 @@ where
 
 #[cfg(feature = "discover")]
 impl<D, C> PendingRequestsDiscover<D, C> {
-    /// Wraps a `Discover``, wrapping all of its services with `PendingRequests`.
+    /// Wraps a [`Discover`], wrapping all of its services with [`PendingRequests`].
     pub fn new<Request>(discover: D, completion: C) -> Self
     where
         D: Discover,
diff --git a/tower/src/load_shed/error.rs b/tower/src/load_shed/error.rs
index dd153fd..ef401f0 100644
--- a/tower/src/load_shed/error.rs
+++ b/tower/src/load_shed/error.rs
@@ -2,9 +2,11 @@
 
 use std::fmt;
 
-/// An error returned by `Overload` when the underlying service
+/// An error returned by [`LoadShed`] when the underlying service
 /// is not ready to handle any requests at the time of being
 /// called.
+///
+/// [`LoadShed`]: crate::load_shed::LoadShed
 pub struct Overloaded {
     _p: (),
 }
diff --git a/tower/src/load_shed/future.rs b/tower/src/load_shed/future.rs
index 3ab27a5..045c197 100644
--- a/tower/src/load_shed/future.rs
+++ b/tower/src/load_shed/future.rs
@@ -10,7 +10,9 @@ use pin_project::pin_project;
 
 use super::error::Overloaded;
 
-/// Future for the `LoadShed` service.
+/// Future for the [`LoadShed`] service.
+///
+/// [`LoadShed`]: crate::load_shed::LoadShed
 #[pin_project]
 pub struct ResponseFuture<F> {
     #[pin]
diff --git a/tower/src/load_shed/layer.rs b/tower/src/load_shed/layer.rs
index 72af6a5..65ab29f 100644
--- a/tower/src/load_shed/layer.rs
+++ b/tower/src/load_shed/layer.rs
@@ -3,7 +3,9 @@ use tower_layer::Layer;
 
 use super::LoadShed;
 
-/// A `tower-layer` to wrap services in `LoadShed` middleware.
+/// A [`Layer`] to wrap services in [`LoadShed`] middleware.
+///
+/// [`Layer`]: crate::Layer
 #[derive(Clone, Default)]
 pub struct LoadShedLayer {
     _p: (),
diff --git a/tower/src/load_shed/mod.rs b/tower/src/load_shed/mod.rs
index 8ba65c5..deadf0f 100644
--- a/tower/src/load_shed/mod.rs
+++ b/tower/src/load_shed/mod.rs
@@ -1,4 +1,4 @@
-//! Tower middleware for shedding load when inner services aren't ready.
+//! Middleware for shedding load when inner services aren't ready.
 
 use std::task::{Context, Poll};
 use tower_service::Service;
@@ -10,7 +10,9 @@ mod layer;
 use self::future::ResponseFuture;
 pub use self::layer::LoadShedLayer;
 
-/// A `Service` that sheds load when the inner service isn't ready.
+/// A [`Service`] that sheds load when the inner service isn't ready.
+///
+/// [`Service`]: crate::Service
 #[derive(Debug)]
 pub struct LoadShed<S> {
     inner: S,
@@ -20,7 +22,7 @@ pub struct LoadShed<S> {
 // ===== impl LoadShed =====
 
 impl<S> LoadShed<S> {
-    /// Wraps a service in `LoadShed` middleware.
+    /// Wraps a service in [`LoadShed`] middleware.
     pub fn new(inner: S) -> Self {
         LoadShed {
             inner,
diff --git a/tower/src/make/make_connection.rs b/tower/src/make/make_connection.rs
index bc0757f..9566cc6 100644
--- a/tower/src/make/make_connection.rs
+++ b/tower/src/make/make_connection.rs
@@ -4,7 +4,7 @@ use std::task::{Context, Poll};
 use tokio::io::{AsyncRead, AsyncWrite};
 use tower_service::Service;
 
-/// The `MakeConnection` trait is used to create transports.
+/// The [`MakeConnection`] trait is used to create transports.
 ///
 /// The goal of this service is to allow composable methods for creating
 /// `AsyncRead + AsyncWrite` transports. This could mean creating a TLS
diff --git a/tower/src/make/make_service.rs b/tower/src/make/make_service.rs
index 7f05acc..213a481 100644
--- a/tower/src/make/make_service.rs
+++ b/tower/src/make/make_service.rs
@@ -1,4 +1,4 @@
-//! Contains `MakeService` which is a trait alias for a `Service` of `Service`s.
+//! Contains [`MakeService`] which is a trait alias for a [`Service`] of [`Service`]s.
 
 use crate::sealed::Sealed;
 use std::fmt;
@@ -7,15 +7,15 @@ use std::marker::PhantomData;
 use std::task::{Context, Poll};
 use tower_service::Service;
 
-/// Creates new `Service` values.
+/// Creates new [`Service`] values.
 ///
-/// Acts as a service factory. This is useful for cases where new `Service`
+/// Acts as a service factory. This is useful for cases where new [`Service`]
 /// values must be produced. One case is a TCP server listener. The listener
-/// accepts new TCP streams, obtains a new `Service` value using the
-/// `MakeService` trait, and uses that new `Service` value to process inbound
+/// accepts new TCP streams, obtains a new [`Service`] value using the
+/// [`MakeService`] trait, and uses that new [`Service`] value to process inbound
 /// requests on that new TCP stream.
 ///
-/// This is essentially a trait alias for a `Service` of `Service`s.
+/// This is essentially a trait alias for a [`Service`] of [`Service`]s.
 pub trait MakeService<Target, Request>: Sealed<(Target, Request)> {
     /// Responses given by the service
     type Response;
@@ -23,26 +23,29 @@ pub trait MakeService<Target, Request>: Sealed<(Target, Request)> {
     /// Errors produced by the service
     type Error;
 
-    /// The `Service` value created by this factory
+    /// The [`Service`] value created by this factory
     type Service: Service<Request, Response = Self::Response, Error = Self::Error>;
 
     /// Errors produced while building a service.
     type MakeError;
 
-    /// The future of the `Service` instance.
+    /// The future of the [`Service`] instance.
     type Future: Future<Output = Result<Self::Service, Self::MakeError>>;
 
-    /// Returns `Ready` when the factory is able to create more services.
+    /// Returns [`Poll::Ready`] when the factory is able to create more services.
     ///
-    /// If the service is at capacity, then `Poll::Pending` is returned and the task
+    /// If the service is at capacity, then [`Poll::Pending`] is returned and the task
     /// is notified when the service becomes ready again. This function is
     /// expected to be called while on a task.
+    ///
+    /// [`Poll::Ready`]: std::task::Poll::Ready
+    /// [`Poll::Pending`]: std::task::Poll::Pending
     fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>>;
 
     /// Create and return a new service value asynchronously.
     fn make_service(&mut self, target: Target) -> Self::Future;
 
-    /// Consume this `MakeService` and convert it into a `Service`.
+    /// Consume this [`MakeService`] and convert it into a [`Service`].
     ///
     /// # Example
     /// ```
@@ -81,7 +84,7 @@ pub trait MakeService<Target, Request>: Sealed<(Target, Request)> {
         }
     }
 
-    /// Convert this `MakeService` into a `Service` without consuming the original `MakeService`.
+    /// Convert this [`MakeService`] into a [`Service`] without consuming the original [`MakeService`].
     ///
     /// # Example
     /// ```
diff --git a/tower/src/ready_cache/cache.rs b/tower/src/ready_cache/cache.rs
index 33b0a04..6cdaca8 100644
--- a/tower/src/ready_cache/cache.rs
+++ b/tower/src/ready_cache/cache.rs
@@ -17,14 +17,14 @@ use tracing::{debug, trace};
 ///
 /// The cache maintains two internal data structures:
 ///
-/// * a set of  _pending_ services that have not yet become ready; and
+/// * a set of _pending_ services that have not yet become ready; and
 /// * a set of _ready_ services that have previously polled ready.
 ///
-/// As each `S` typed `Service` is added to the cache via `ReadyCache::push`, it
-/// is added to the _pending set_. As `ReadyCache::poll_pending` is invoked,
+/// As each `S` typed [`Service`] is added to the cache via [`ReadyCache::push`], it
+/// is added to the _pending set_. As [`ReadyCache::poll_pending`] is invoked,
 /// pending services are polled and added to the _ready set_.
 ///
-/// `ReadyCache::call_ready` (or `ReadyCache::call_ready_index`) dispatches a
+/// [`ReadyCache::call_ready`] (or [`ReadyCache::call_ready_index`]) dispatches a
 /// request to the specified service, but panics if the specified service is not
 /// in the ready set. The `ReadyCache::check_*` functions can be used to ensure
 /// that a service is ready before dispatching a request.
@@ -32,7 +32,7 @@ use tracing::{debug, trace};
 /// The ready set can hold services for an abitrarily long time. During this
 /// time, the runtime may process events that invalidate that ready state (for
 /// instance, if a keepalive detects a lost connection). In such cases, callers
-/// should use `ReadyCache::check_ready` (or `ReadyCache::check_ready_index`)
+/// should use [`ReadyCache::check_ready`] (or [`ReadyCache::check_ready_index`])
 /// immediately before dispatching a request to ensure that the service has not
 /// become unavailable.
 ///
@@ -43,15 +43,15 @@ use tracing::{debug, trace};
 /// specified service is _not_ ready. If an error is returned, this indicats that
 /// the server failed and has been removed from the cache entirely.
 ///
-/// `ReadyCache::evict` can be used to remove a service from the cache (by key),
+/// [`ReadyCache::evict`] can be used to remove a service from the cache (by key),
 /// though the service may not be dropped (if it is currently pending) until
-/// `ReadyCache::poll_pending` is invoked.
+/// [`ReadyCache::poll_pending`] is invoked.
 ///
 /// Note that the by-index accessors are provided to support use cases (like
 /// power-of-two-choices load balancing) where the caller does not care to keep
 /// track of each service's key. Instead, it needs only to access _some_ ready
 /// service. In such a case, it should be noted that calls to
-/// `ReadyCache::poll_pending` and `ReadyCache::evict` may perturb the order of
+/// [`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>
@@ -85,7 +85,7 @@ enum PendingError<K, E> {
     Inner(K, E),
 }
 
-/// A Future that becomes satisfied when an `S`-typed service is ready.
+/// 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)]
@@ -171,7 +171,7 @@ where
     /// Returns true if a service was marked for eviction.
     ///
     /// Services are dropped from the ready set immediately. Services in the
-    /// pending set are marked for cancellation, but `ReadyCache::poll_pending`
+    /// pending set are marked for cancellation, but [`ReadyCache::poll_pending`]
     /// must be called to cause the service to be dropped.
     pub fn evict<Q: Hash + Equivalent<K>>(&mut self, key: &Q) -> bool {
         let canceled = if let Some(c) = self.pending_cancel_txs.swap_remove(key) {
@@ -197,12 +197,14 @@ where
 {
     /// Pushes a new service onto the pending set.
     ///
-    /// The service will be promoted to the ready set as `poll_pending` is invoked.
+    /// The service will be promoted to the ready set as [`poll_pending`] is invoked.
     ///
     /// Note that this does **not** remove services from the ready set. Once the
     /// old service is used, it will be dropped instead of being added back to
     /// the pending set; OR, when the new service becomes ready, it will replace
     /// the prior service in the ready set.
+    ///
+    /// [`poll_pending`]: crate::ready_cache::cache::ReadyCache::poll_pending
     pub fn push(&mut self, key: K, svc: S) {
         let cancel = oneshot::channel();
         self.push_pending(key, svc, cancel);
@@ -223,14 +225,18 @@ where
 
     /// Polls services pending readiness, adding ready services to the ready set.
     ///
-    /// Returns `Async::Ready` when there are no remaining unready services.
-    /// `poll_pending` should be called again after `push_service` or
-    /// `call_ready_index` are invoked.
+    /// Returns [`Poll::Ready`] when there are no remaining unready services.
+    /// [`poll_pending`] should be called again after [`push`] or
+    /// [`call_ready_index`] are invoked.
     ///
     /// Failures indicate that an individual pending service failed to become
     /// ready (and has been removed from the cache). In such a case,
-    /// `poll_pending` should typically be called again to continue driving
+    /// [`poll_pending`] should typically be called again to continue driving
     /// pending services to readiness.
+    ///
+    /// [`poll_pending`]: crate::ready_cache::cache::ReadyCache::poll_pending
+    /// [`push`]: crate::ready_cache::cache::ReadyCache::push
+    /// [`call_ready_index`]: crate::ready_cache::cache::ReadyCache::call_ready_index
     pub fn poll_pending(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), error::Failed<K>>> {
         loop {
             match Pin::new(&mut self.pending).poll_next(cx) {
diff --git a/tower/src/reconnect/mod.rs b/tower/src/reconnect/mod.rs
index f477e88..44dc540 100644
--- a/tower/src/reconnect/mod.rs
+++ b/tower/src/reconnect/mod.rs
@@ -48,7 +48,7 @@ impl<M, Target> Reconnect<M, Target>
 where
     M: Service<Target>,
 {
-    /// Lazily connect and reconnect to a Service.
+    /// Lazily connect and reconnect to a [`Service`].
     pub fn new<S, Request>(mk_service: M, target: Target) -> Self {
         Reconnect {
             mk_service,
@@ -58,7 +58,7 @@ where
         }
     }
 
-    /// Reconnect to a already connected Service.
+    /// Reconnect to a already connected [`Service`].
     pub fn with_connection(init_conn: M::Response, mk_service: M, target: Target) -> Self {
         Reconnect {
             mk_service,
diff --git a/tower/src/retry/budget.rs b/tower/src/retry/budget.rs
index 7507fb5..ccecce0 100644
--- a/tower/src/retry/budget.rs
+++ b/tower/src/retry/budget.rs
@@ -21,7 +21,7 @@ pub struct Budget {
 }
 
 /// Indicates that it is not currently allowed to "withdraw" another retry
-/// from the [`Budget`](Budget).
+/// from the [`Budget`].
 #[derive(Debug)]
 pub struct Overdrawn {
     _inner: (),
@@ -52,7 +52,7 @@ struct Generation {
 // ===== impl Budget =====
 
 impl Budget {
-    /// Create a `Budget` that allows for a certain percent of the total
+    /// Create a [`Budget`] that allows for a certain percent of the total
     /// requests to be retried.
     ///
     /// - The `ttl` is the duration of how long a single `deposit` should be
diff --git a/tower/src/retry/future.rs b/tower/src/retry/future.rs
index 5db0ea9..d6988ec 100644
--- a/tower/src/retry/future.rs
+++ b/tower/src/retry/future.rs
@@ -8,7 +8,7 @@ use std::pin::Pin;
 use std::task::{Context, Poll};
 use tower_service::Service;
 
-/// The `Future` returned by a `Retry` service.
+/// The [`Future`] returned by a [`Retry`] service.
 #[pin_project]
 #[derive(Debug)]
 pub struct ResponseFuture<P, S, Request>
@@ -26,11 +26,11 @@ where
 #[pin_project(project = StateProj)]
 #[derive(Debug)]
 enum State<F, P> {
-    /// Polling the future from `Service::call`
+    /// Polling the future from [`Service::call`]
     Called(#[pin] F),
-    /// Polling the future from `Policy::retry`
+    /// Polling the future from [`Policy::retry`]
     Checking(#[pin] P),
-    /// Polling `Service::poll_ready` after `Checking` was OK.
+    /// Polling [`Service::poll_ready`] after [`Checking`] was OK.
     Retrying,
 }
 
diff --git a/tower/src/retry/layer.rs b/tower/src/retry/layer.rs
index a5be368..ea03c78 100644
--- a/tower/src/retry/layer.rs
+++ b/tower/src/retry/layer.rs
@@ -8,7 +8,7 @@ pub struct RetryLayer<P> {
 }
 
 impl<P> RetryLayer<P> {
-    /// Create a new `RetryLayer` from a retry policy
+    /// Create a new [`RetryLayer`] from a retry policy
     pub fn new(policy: P) -> Self {
         RetryLayer { policy }
     }
diff --git a/tower/src/retry/mod.rs b/tower/src/retry/mod.rs
index bbbc64e..98fb084 100644
--- a/tower/src/retry/mod.rs
+++ b/tower/src/retry/mod.rs
@@ -1,4 +1,4 @@
-//! Tower middleware for retrying "failed" requests.
+//! Middleware for retrying "failed" requests.
 
 pub mod budget;
 pub mod future;
@@ -15,7 +15,7 @@ use tower_service::Service;
 
 /// Configure retrying requests of "failed" responses.
 ///
-/// A `Policy` classifies what is a "failed" response.
+/// A [`Policy`] classifies what is a "failed" response.
 #[pin_project]
 #[derive(Clone, Debug)]
 pub struct Retry<P, S> {
@@ -27,7 +27,7 @@ pub struct Retry<P, S> {
 // ===== impl Retry =====
 
 impl<P, S> Retry<P, S> {
-    /// Retry the inner service depending on this `Policy`.
+    /// Retry the inner service depending on this [`Policy`].
     pub fn new(policy: P, service: S) -> Self {
         Retry { policy, service }
     }
diff --git a/tower/src/retry/never.rs b/tower/src/retry/never.rs
index 3bb12aa..af7264b 100644
--- a/tower/src/retry/never.rs
+++ b/tower/src/retry/never.rs
@@ -1,4 +1,5 @@
 use std::fmt;
+
 #[derive(Debug)]
 /// An error that can never occur.
 pub enum Never {}
diff --git a/tower/src/retry/policy.rs b/tower/src/retry/policy.rs
index cedf880..6f8a5b7 100644
--- a/tower/src/retry/policy.rs
+++ b/tower/src/retry/policy.rs
@@ -43,20 +43,25 @@ use std::future::Future;
 /// }
 /// ```
 pub trait Policy<Req, Res, E>: Sized {
-    /// The `Future` type returned by `Policy::retry()`.
+    /// The [`Future`] type returned by [`Policy::retry`].
     type Future: Future<Output = Self>;
+
     /// Check the policy if a certain request should be retried.
     ///
     /// This method is passed a reference to the original request, and either
-    /// the `Service::Response` or `Service::Error` from the inner service.
+    /// the [`Service::Response`] or [`Service::Error`] from the inner service.
     ///
     /// If the request should **not** be retried, return `None`.
     ///
     /// If the request *should* be retried, return `Some` future of a new
     /// policy that would apply for the next request attempt.
+    ///
+    /// [`Service::Response`]: crate::Service::Response
+    /// [`Service::Error`]: crate::Service::Error
     fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option<Self::Future>;
+
     /// Tries to clone a request before being passed to the inner service.
     ///
-    /// If the request cannot be cloned, return `None`.
+    /// If the request cannot be cloned, return [`None`].
     fn clone_request(&self, req: &Req) -> Option<Req>;
 }
diff --git a/tower/src/spawn_ready/layer.rs b/tower/src/spawn_ready/layer.rs
index 3907081..1151ea1 100644
--- a/tower/src/spawn_ready/layer.rs
+++ b/tower/src/spawn_ready/layer.rs
@@ -6,7 +6,7 @@ use tower_layer::Layer;
 pub struct SpawnReadyLayer;
 
 impl SpawnReadyLayer {
-    /// Builds a SpawnReady layer with the default executor.
+    /// Builds a [`SpawnReadyLayer`] with the default executor.
     pub fn new() -> Self {
         Self
     }
diff --git a/tower/src/spawn_ready/make.rs b/tower/src/spawn_ready/make.rs
index 0a413ef..e2c1f2a 100644
--- a/tower/src/spawn_ready/make.rs
+++ b/tower/src/spawn_ready/make.rs
@@ -8,20 +8,20 @@ use std::{
 };
 use tower_service::Service;
 
-/// Builds SpawnReady instances with the result of an inner Service.
+/// Builds [`SpawnReady`] instances with the result of an inner [`Service`].
 #[derive(Clone, Debug)]
 pub struct MakeSpawnReady<S> {
     inner: S,
 }
 
 impl<S> MakeSpawnReady<S> {
-    /// Creates a new `MakeSpawnReady` wrapping `service`.
+    /// Creates a new [`MakeSpawnReady`] wrapping `service`.
     pub fn new(service: S) -> Self {
         Self { inner: service }
     }
 }
 
-/// Builds a SpawnReady with the result of an inner Future.
+/// Builds a [`SpawnReady`] with the result of an inner [`Future`].
 #[pin_project]
 #[derive(Debug)]
 pub struct MakeFuture<F> {
diff --git a/tower/src/spawn_ready/service.rs b/tower/src/spawn_ready/service.rs
index 62be6a9..4e598e4 100644
--- a/tower/src/spawn_ready/service.rs
+++ b/tower/src/spawn_ready/service.rs
@@ -24,7 +24,7 @@ enum Inner<T> {
 }
 
 impl<T> SpawnReady<T> {
-    /// Creates a new `SpawnReady` wrapping `service`.
+    /// Creates a new [`SpawnReady`] wrapping `service`.
     pub fn new(service: T) -> Self {
         Self {
             inner: Inner::Service(Some(service)),
diff --git a/tower/src/steer/mod.rs b/tower/src/steer/mod.rs
index 63fefa2..6311169 100644
--- a/tower/src/steer/mod.rs
+++ b/tower/src/steer/mod.rs
@@ -1,8 +1,8 @@
-//! This module provides functionality to aid managing routing requests between Tower [`Service`]s.
+//! This module provides functionality to aid managing routing requests between [`Service`]s.
 //!
 //! # Example
 //!
-//! `Steer` can for example be used to create a router, akin to what you might find in web
+//! [`Steer`] can for example be used to create a router, akin to what you might find in web
 //! frameworks.
 //!
 //! Here, `GET /` will be sent to the `root` service, while all other requests go to `not_found`.
@@ -87,21 +87,23 @@ where
     }
 }
 
-/// `Steer` manages a list of `Service`s which all handle the same type of request.
+/// [`Steer`] manages a list of [`Service`]s which all handle the same type of request.
 ///
 /// An example use case is a sharded service.
 /// It accepts new requests, then:
-/// 1. Determines, via the provided [`Picker`], which `Service` the request coresponds to.
-/// 2. Waits (in `poll_ready`) for *all* services to be ready.
-/// 3. Calls the correct `Service` with the request, and returns a future corresponding to the
+/// 1. Determines, via the provided [`Picker`], which [`Service`] the request coresponds to.
+/// 2. Waits (in [`Service::poll_ready`]) for *all* services to be ready.
+/// 3. Calls the correct [`Service`] with the request, and returns a future corresponding to the
 ///    call.
 ///
-/// Note that `Steer` must wait for all services to be ready since it can't know ahead of time
-/// which `Service` the next message will arrive for, and is unwilling to buffer items
-/// indefinitely. This will cause head-of-line blocking unless paired with a `Service` that does
-/// buffer items indefinitely, and thus always returns `Poll::Ready`. For example, wrapping each
-/// component service with a `tower-buffer` with a high enough limit (the maximum number of
-/// concurrent requests) will prevent head-of-line blocking in `Steer`.
+/// Note that [`Steer`] must wait for all services to be ready since it can't know ahead of time
+/// which [`Service`] the next message will arrive for, and is unwilling to buffer items
+/// indefinitely. This will cause head-of-line blocking unless paired with a [`Service`] that does
+/// buffer items indefinitely, and thus always returns [`Poll::Ready`]. For example, wrapping each
+/// component service with a [`Buffer`] with a high enough limit (the maximum number of concurrent
+/// requests) will prevent head-of-line blocking in [`Steer`].
+///
+/// [`Buffer`]: crate::buffer::Buffer
 #[derive(Debug)]
 pub struct Steer<S, F, Req> {
     router: F,
@@ -111,9 +113,9 @@ pub struct Steer<S, F, Req> {
 }
 
 impl<S, F, Req> Steer<S, F, Req> {
-    /// Make a new [`Steer`] with a list of `Service`s and a `Picker`.
+    /// Make a new [`Steer`] with a list of [`Service`]'s and a [`Picker`].
     ///
-    /// Note: the order of the `Service`s is significant for [`Picker::pick`]'s return value.
+    /// Note: the order of the [`Service`]'s is significant for [`Picker::pick`]'s return value.
     pub fn new(services: impl IntoIterator<Item = S>, router: F) -> Self {
         let services: Vec<_> = services.into_iter().collect();
         let not_ready: VecDeque<_> = services.iter().enumerate().map(|(i, _)| i).collect();
diff --git a/tower/src/timeout/future.rs b/tower/src/timeout/future.rs
index 661c259..a14ad59 100644
--- a/tower/src/timeout/future.rs
+++ b/tower/src/timeout/future.rs
@@ -9,7 +9,9 @@ use std::{
 };
 use tokio::time::Sleep;
 
-/// `Timeout` response future
+/// [`Timeout`] response future
+///
+/// [`Timeout`]: crate::timeout::Timeout
 #[pin_project]
 #[derive(Debug)]
 pub struct ResponseFuture<T> {
diff --git a/tower/src/timeout/mod.rs b/tower/src/timeout/mod.rs
index 2407078..0e65a3f 100644
--- a/tower/src/timeout/mod.rs
+++ b/tower/src/timeout/mod.rs
@@ -1,4 +1,4 @@
-//! Tower middleware that applies a timeout to requests.
+//! Middleware that applies a timeout to requests.
 //!
 //! If the response does not complete within the specified timeout, the response
 //! will be aborted.
@@ -24,7 +24,7 @@ pub struct Timeout<T> {
 // ===== impl Timeout =====
 
 impl<T> Timeout<T> {
-    /// Creates a new Timeout
+    /// Creates a new [`Timeout`]
     pub fn new(inner: T, timeout: Duration) -> Self {
         Timeout { inner, timeout }
     }
diff --git a/tower/src/timeout/never.rs b/tower/src/timeout/never.rs
deleted file mode 100644
index e69de29..0000000
diff --git a/tower/src/util/boxed/mod.rs b/tower/src/util/boxed/mod.rs
index dc339b3..de6fbff 100644
--- a/tower/src/util/boxed/mod.rs
+++ b/tower/src/util/boxed/mod.rs
@@ -1,15 +1,15 @@
-//! Trait object `Service` instances
+//! Trait object [`Service`] instances
 //!
-//! Dynamically dispatched `Service` objects allow for erasing the underlying
-//! `Service` type and using the `Service` instances as opaque handles. This can
+//! Dynamically dispatched [`Service`] objects allow for erasing the underlying
+//! [`Service`] type and using the `Service` instances as opaque handles. This can
 //! be useful when the service instance cannot be explicitly named for whatever
 //! reason.
 //!
-//! There are two variants of service objects. `BoxService` requires both the
-//! service and the response future to be `Send`. These values can move freely
-//! across threads. `UnsyncBoxService` requires both the service and the
+//! There are two variants of service objects. [`BoxService`] requires both the
+//! service and the response future to be [`Send`]. These values can move freely
+//! across threads. [`UnsyncBoxService`] requires both the service and the
 //! response future to remain on the current thread. This is useful for
-//! representing services that are backed by `Rc` or other non-`Send` types.
+//! representing services that are backed by [`Rc`] or other non-[`Send`] types.
 //!
 //! # Examples
 //!
@@ -28,6 +28,9 @@
 //! # drop(service);
 //! }
 //! ```
+//!
+//! [`Service`]: crate::Service
+//! [`Rc`]: std::rc::Rc
 
 mod sync;
 mod unsync;
diff --git a/tower/src/util/boxed/sync.rs b/tower/src/util/boxed/sync.rs
index 6d483bb..10f8864 100644
--- a/tower/src/util/boxed/sync.rs
+++ b/tower/src/util/boxed/sync.rs
@@ -10,9 +10,9 @@ use std::{
 
 /// A boxed `Service + Send` trait object.
 ///
-/// `BoxService` turns a service into a trait object, allowing the response
+/// [`BoxService`] turns a service into a trait object, allowing the response
 /// future type to be dynamic. This type requires both the service and the
-/// response future to be `Send`.
+/// response future to be [`Send`].
 ///
 /// See module level documentation for more details.
 pub struct BoxService<T, U, E> {
@@ -21,7 +21,7 @@ pub struct BoxService<T, U, E> {
 
 /// A boxed `Future + Send` trait object.
 ///
-/// This type alias represents a boxed future that is `Send` and can be moved
+/// This type alias represents a boxed future that is [`Send`] and can be moved
 /// across threads.
 type BoxFuture<T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + Send>>;
 
@@ -41,7 +41,7 @@ impl<T, U, E> BoxService<T, U, E> {
         BoxService { inner }
     }
 
-    /// Returns a [`Layer`] for wrapping a [`Service`] in a `BoxService`
+    /// Returns a [`Layer`] for wrapping a [`Service`] in a [`BoxService`]
     /// middleware.
     ///
     /// [`Layer`]: crate::Layer
diff --git a/tower/src/util/boxed/unsync.rs b/tower/src/util/boxed/unsync.rs
index 66be7d1..b5a792d 100644
--- a/tower/src/util/boxed/unsync.rs
+++ b/tower/src/util/boxed/unsync.rs
@@ -8,14 +8,14 @@ use std::{
     task::{Context, Poll},
 };
 
-/// A boxed `Service` trait object.
+/// A boxed [`Service`] trait object.
 pub struct UnsyncBoxService<T, U, E> {
     inner: Box<dyn Service<T, Response = U, Error = E, Future = UnsyncBoxFuture<U, E>>>,
 }
 
-/// A boxed `Future` trait object.
+/// A boxed [`Future`] trait object.
 ///
-/// This type alias represents a boxed future that is *not* `Send` and must
+/// This type alias represents a boxed future that is *not* [`Send`] and must
 /// remain on the current thread.
 type UnsyncBoxFuture<T, E> = Pin<Box<dyn Future<Output = Result<T, E>>>>;
 
@@ -35,7 +35,7 @@ impl<T, U, E> UnsyncBoxService<T, U, E> {
         UnsyncBoxService { inner }
     }
 
-    /// Returns a [`Layer`] for wrapping a [`Service`] in an `UnsyncBoxService` middleware.
+    /// Returns a [`Layer`] for wrapping a [`Service`] in an [`UnsyncBoxService`] middleware.
     ///
     /// [`Layer`]: crate::Layer
     pub fn layer<S>() -> LayerFn<fn(S) -> Self>
diff --git a/tower/src/util/call_all/common.rs b/tower/src/util/call_all/common.rs
index 0a54cb3..fde0f04 100644
--- a/tower/src/util/call_all/common.rs
+++ b/tower/src/util/call_all/common.rs
@@ -7,7 +7,7 @@ use std::{
 };
 use tower_service::Service;
 
-/// TODO: Dox
+/// The [`Future`] returned by the [`ServiceExt::call_all`] combinator.
 #[pin_project]
 #[derive(Debug)]
 pub(crate) struct CallAll<Svc, S, Q> {
@@ -23,7 +23,6 @@ pub(crate) trait Drive<F: Future> {
 
     fn push(&mut self, future: F);
 
-    // NOTE: this implicitly requires Self: Unpin just like Service does
     fn poll(&mut self, cx: &mut Context<'_>) -> Poll<Option<F::Output>>;
 }
 
@@ -43,12 +42,12 @@ where
         }
     }
 
-    /// Extract the wrapped `Service`.
+    /// Extract the wrapped [`Service`].
     pub(crate) fn into_inner(mut self) -> Svc {
         self.service.take().expect("Service already taken")
     }
 
-    /// Extract the wrapped `Service`.
+    /// Extract the wrapped [`Service`].
     pub(crate) fn take_service(self: Pin<&mut Self>) -> Svc {
         self.project()
             .service
diff --git a/tower/src/util/call_all/mod.rs b/tower/src/util/call_all/mod.rs
index 4e06c26..0cac72d 100644
--- a/tower/src/util/call_all/mod.rs
+++ b/tower/src/util/call_all/mod.rs
@@ -1,4 +1,7 @@
-//! `Stream<Item = Request>` + `Service<Request>` => `Stream<Item = Response>`.
+//! [`Stream<Item = Request>`][stream] + [`Service<Request>`] => [`Stream<Item = Response>`][stream].
+//!
+//! [`Service<Request>`]: crate::Service
+//! [stream]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html
 
 mod common;
 mod ordered;
diff --git a/tower/src/util/call_all/ordered.rs b/tower/src/util/call_all/ordered.rs
index 235cb90..1d91056 100644
--- a/tower/src/util/call_all/ordered.rs
+++ b/tower/src/util/call_all/ordered.rs
@@ -1,4 +1,7 @@
-//! `Stream<Item = Request>` + `Service<Request>` => `Stream<Item = Response>`.
+//! [`Stream<Item = Request>`][stream] + [`Service<Request>`] => [`Stream<Item = Response>`][stream].
+//!
+//! [`Service<Request>`]: crate::Service
+//! [stream]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html
 
 use super::common;
 use futures_core::Stream;
@@ -11,8 +14,8 @@ use std::{
 };
 use tower_service::Service;
 
-/// This is a `futures::Stream` of responses resulting from calling the wrapped `tower::Service`
-/// for each request received on the wrapped `Stream`.
+/// This is a [`Stream`] of responses resulting from calling the wrapped [`Service`] for each
+/// request received on the wrapped [`Stream`].
 ///
 /// ```rust
 /// # use std::task::{Poll, Context};
@@ -78,6 +81,8 @@ use tower_service::Service;
 ///     assert_eq!(rsps.into_inner(), FirstLetter);
 /// }
 /// ```
+///
+/// [`Stream`]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html
 #[pin_project]
 #[derive(Debug)]
 pub struct CallAll<Svc, S>
@@ -95,32 +100,38 @@ where
     Svc::Error: Into<crate::BoxError>,
     S: Stream,
 {
-    /// Create new `CallAll` combinator.
+    /// Create new [`CallAll`] combinator.
+    ///
+    /// Each request yielded by `stream` is passed to `svc`, and the resulting responses are
+    /// yielded in the same order by the implementation of [`Stream`] for [`CallAll`].
     ///
-    /// Each request yielded by `stread` is passed to `svc`, and the resulting responses are
-    /// yielded in the same order by the implementation of `Stream` for `CallAll`.
+    /// [`Stream`]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html
     pub fn new(service: Svc, stream: S) -> CallAll<Svc, S> {
         CallAll {
             inner: common::CallAll::new(service, stream, FuturesOrdered::new()),
         }
     }
 
-    /// Extract the wrapped `Service`.
+    /// Extract the wrapped [`Service`].
     ///
     /// # Panics
     ///
-    /// Panics if `take_service` was already called.
+    /// Panics if [`take_service`] was already called.
+    ///
+    /// [`take_service`]: crate::util::CallAll::take_service
     pub fn into_inner(self) -> Svc {
         self.inner.into_inner()
     }
 
-    /// Extract the wrapped `Service`.
+    /// Extract the wrapped [`Service`].
     ///
-    /// This `CallAll` can no longer be used after this function has been called.
+    /// This [`CallAll`] can no longer be used after this function has been called.
     ///
     /// # Panics
     ///
-    /// Panics if `take_service` was already called.
+    /// Panics if [`take_service`] was already called.
+    ///
+    /// [`take_service`]: crate::util::CallAll::take_service
     pub fn take_service(self: Pin<&mut Self>) -> Svc {
         self.project().inner.take_service()
     }
@@ -131,7 +142,9 @@ where
     ///
     /// # Panics
     ///
-    /// Panics if `poll` was called.
+    /// Panics if [`poll`] was called.
+    ///
+    /// [`poll`]: std::future::Future::poll
     pub fn unordered(self) -> super::CallAllUnordered<Svc, S> {
         self.inner.unordered()
     }
diff --git a/tower/src/util/call_all/unordered.rs b/tower/src/util/call_all/unordered.rs
index 4f9c65e..6d1fd64 100644
--- a/tower/src/util/call_all/unordered.rs
+++ b/tower/src/util/call_all/unordered.rs
@@ -1,4 +1,7 @@
-//! `Stream<Item = Request>` + `Service<Request>` => `Stream<Item = Response>`.
+//! [`Stream<Item = Request>`][stream] + [`Service<Request>`] => [`Stream<Item = Response>`][stream].
+//!
+//! [`Service<Request>`]: crate::Service
+//! [stream]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html
 
 use super::common;
 use futures_core::Stream;
@@ -13,8 +16,10 @@ use tower_service::Service;
 
 /// A stream of responses received from the inner service in received order.
 ///
-/// Similar to `CallAll` except, instead of yielding responses in request order,
+/// Similar to [`CallAll`] except, instead of yielding responses in request order,
 /// responses are returned as they are available.
+///
+/// [`CallAll`]: crate::util::CallAll
 #[pin_project]
 #[derive(Debug)]
 pub struct CallAllUnordered<Svc, S>
@@ -32,33 +37,35 @@ where
     Svc::Error: Into<crate::BoxError>,
     S: Stream,
 {
-    /// Create new `CallAllUnordered` combinator.
+    /// Create new [`CallAllUnordered`] combinator.
     ///
-    /// Each request yielded by `stread` is passed to `svc`, and the resulting responses are
-    /// yielded in the same order by the implementation of `Stream` for
-    /// `CallAllUnordered`.
+    /// [`Stream`]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html
     pub fn new(service: Svc, stream: S) -> CallAllUnordered<Svc, S> {
         CallAllUnordered {
             inner: common::CallAll::new(service, stream, FuturesUnordered::new()),
         }
     }
 
-    /// Extract the wrapped `Service`.
+    /// Extract the wrapped [`Service`].
     ///
     /// # Panics
     ///
-    /// Panics if `take_service` was already called.
+    /// Panics if [`take_service`] was already called.
+    ///
+    /// [`take_service`]: crate::util::CallAllUnordered::take_service
     pub fn into_inner(self) -> Svc {
         self.inner.into_inner()
     }
 
     /// Extract the wrapped `Service`.
     ///
-    /// This `CallAll` can no longer be used after this function has been called.
+    /// This [`CallAllUnordered`] can no longer be used after this function has been called.
     ///
     /// # Panics
     ///
-    /// Panics if `take_service` was already called.
+    /// Panics if [`take_service`] was already called.
+    ///
+    /// [`take_service`]: crate::util::CallAllUnordered::take_service
     pub fn take_service(self: Pin<&mut Self>) -> Svc {
         self.project().inner.take_service()
     }
diff --git a/tower/src/util/either.rs b/tower/src/util/either.rs
index e53d954..1bb1997 100644
--- a/tower/src/util/either.rs
+++ b/tower/src/util/either.rs
@@ -1,6 +1,6 @@
-//! Contains `Either` and related types and functions.
+//! Contains [`Either`] and related types and functions.
 //!
-//! See `Either` documentation for more details.
+//! See [`Either`] documentation for more details.
 
 use futures_core::ready;
 use pin_project::pin_project;
@@ -14,14 +14,14 @@ use tower_service::Service;
 /// Combine two different service types into a single type.
 ///
 /// Both services must be of the same request, response, and error types.
-/// `Either` is useful for handling conditional branching in service middleware
+/// [`Either`] is useful for handling conditional branching in service middleware
 /// to different inner service types.
 #[pin_project(project = EitherProj)]
 #[derive(Clone, Debug)]
 pub enum Either<A, B> {
-    /// One type of backing `Service`.
+    /// One type of backing [`Service`].
     A(#[pin] A),
-    /// The other type of backing `Service`.
+    /// The other type of backing [`Service`].
     B(#[pin] B),
 }
 
diff --git a/tower/src/util/future_service.rs b/tower/src/util/future_service.rs
index 189c474..54378be 100644
--- a/tower/src/util/future_service.rs
+++ b/tower/src/util/future_service.rs
@@ -6,9 +6,9 @@ use std::{
 };
 use tower_service::Service;
 
-/// Returns a new `FutureService` for the given future.
+/// Returns a new [`FutureService`] for the given future.
 ///
-/// A `FutureService` allows you to treat a future that resolves to a service as a service. This
+/// A [`FutureService`] allows you to treat a future that resolves to a service as a service. This
 /// can be useful for services that are created asynchronously.
 ///
 /// # Example
@@ -37,10 +37,10 @@ use tower_service::Service;
 /// # }
 /// ```
 ///
-/// # Regarding the `Unpin` bound
+/// # Regarding the [`Unpin`] bound
 ///
-/// The `Unpin` bound on `F` is necessary because the future will be polled in
-/// `Service::poll_ready` which doesn't have a pinned receiver (it takes `&mut self` and not `self:
+/// The [`Unpin`] bound on `F` is necessary because the future will be polled in
+/// [`Service::poll_ready`] which doesn't have a pinned receiver (it takes `&mut self` and not `self:
 /// Pin<&mut Self>`). So we cannot put the future into a `Pin` without requiring `Unpin`.
 ///
 /// This will most likely come up if you're calling `future_service` with an async block. In that
@@ -55,9 +55,9 @@ where
     }
 }
 
-/// A type that implements `Service` for a `Future` that produces a `Service`.
+/// A type that implements [`Service`] for a [`Future`] that produces a [`Service`].
 ///
-/// See `future_service` for more details.
+/// See [`future_service`] for more details.
 #[derive(Clone)]
 pub struct FutureService<F, S> {
     state: State<F, S>,
diff --git a/tower/src/util/map_result.rs b/tower/src/util/map_result.rs
index 7cfbb30..dfdd76c 100644
--- a/tower/src/util/map_result.rs
+++ b/tower/src/util/map_result.rs
@@ -28,7 +28,7 @@ opaque_future! {
 }
 
 impl<S, F> MapResult<S, F> {
-    /// Creates a new `MapResult` service.
+    /// Creates a new [`MapResult`] service.
     pub fn new(inner: S, f: F) -> Self {
         MapResult { f, inner }
     }
diff --git a/tower/src/util/mod.rs b/tower/src/util/mod.rs
index c19aca3..a4234fb 100644
--- a/tower/src/util/mod.rs
+++ b/tower/src/util/mod.rs
@@ -80,10 +80,14 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
         Oneshot::new(self, req)
     }
 
-    /// Process all requests from the given `Stream`, and produce a `Stream` of their responses.
+    /// Process all requests from the given [`Stream`], and produce a [`Stream`] of their responses.
     ///
-    /// This is essentially `Stream<Item = Request>` + `Self` => `Stream<Item = Response>`. See the
-    /// documentation for [`CallAll`](struct.CallAll.html) for details.
+    /// This is essentially [`Stream<Item = Request>`][stream] + `Self` => [`Stream<Item =
+    /// Response>`][stream]. See the documentation for [`CallAll`] for
+    /// details.
+    ///
+    /// [`Stream`]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html
+    /// [stream]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html
     fn call_all<S>(self, reqs: S) -> CallAll<Self, S>
     where
         Self: Sized,
@@ -302,27 +306,27 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// to a different value, regardless of whether the future succeeds or
     /// fails.
     ///
-    /// This is similar to the [`map_response`] and [`map_err] combinators,
+    /// This is similar to the [`map_response`] and [`map_err`] combinators,
     /// except that the *same* function is invoked when the service's future
     /// completes, whether it completes successfully or fails. This function
-    /// takes the `Result` returned by the service's future, and returns a
-    /// `Result`.
+    /// takes the [`Result`] returned by the service's future, and returns a
+    /// [`Result`].
     ///
     /// Like the standard library's [`Result::and_then`], this method can be
     /// used to implement control flow based on `Result` values. For example, it
-    /// may be used to implement error recovery, by turning some `Err`
-    /// responses from the service into `Ok` responses. Similarly, some
+    /// may be used to implement error recovery, by turning some [`Err`]
+    /// responses from the service into [`Ok`] responses. Similarly, some
     /// successful responses from the service could be rejected, by returning an
-    /// `Err` conditionally, depending on the value inside the `Ok`. Finally,
+    /// [`Err`] conditionally, depending on the value inside the [`Ok`.] Finally,
     /// this method can also be used to implement behaviors that must run when a
     /// service's future completes, regardless of whether it succeeded or failed.
     ///
     /// This method can be used to change the [`Response`] type of the service
     /// into a different type. It can also be used to change the [`Error`] type
-    /// of the service. However, because the `map_result` function is not applied
+    /// of the service. However, because the [`map_result`] function is not applied
     /// to the errors returned by the service's [`poll_ready`] method, it must
     /// be possible to convert the service's [`Error`] type into the error type
-    /// returned by the `map_result` function. This is trivial when the function
+    /// returned by the [`map_result`] function. This is trivial when the function
     /// returns the same error type as the service, but in other cases, it can
     /// be useful to use [`BoxError`] to erase differing error types.
     ///
@@ -514,6 +518,7 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     ///
     /// [`map_response`]: ServiceExt::map_response
     /// [`map_err`]: ServiceExt::map_err
+    /// [`map_result`]: ServiceExt::map_result
     /// [`Error`]: crate::Service::Error
     /// [`Response`]: crate::Service::Response
     /// [`poll_ready`]: crate::Service::poll_ready
@@ -760,7 +765,7 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> {
     /// This method can be thought of as an equivalent to the [`futures`
     /// crate]'s [`FutureExt::then`] combinator, but acting on `Service`s that
     /// _return_ futures, rather than on an individual future. Similarly to that
-    /// combinator, `ServiceExt::then` can be used to implement asynchronous
+    /// combinator, [`ServiceExt::then`] can be used to implement asynchronous
     /// error recovery, by calling some asynchronous function with errors
     /// returned by this service. Alternatively, it may also be used to call a
     /// fallible async function with the successful response of this service.
diff --git a/tower/src/util/oneshot.rs b/tower/src/util/oneshot.rs
index 0f73a4a..3e3ebbb 100644
--- a/tower/src/util/oneshot.rs
+++ b/tower/src/util/oneshot.rs
@@ -8,9 +8,9 @@ use std::{
 };
 use tower_service::Service;
 
-/// A `Future` consuming a `Service` and request, waiting until the `Service`
-/// is ready, and then calling `Service::call` with the request, and
-/// waiting for that `Future`.
+/// A [`Future`] consuming a [`Service`] and request, waiting until the [`Service`]
+/// is ready, and then calling [`Service::call`] with the request, and
+/// waiting for that [`Future`].
 #[pin_project]
 #[derive(Debug)]
 pub struct Oneshot<S: Service<Req>, Req> {
diff --git a/tower/src/util/optional/error.rs b/tower/src/util/optional/error.rs
index c49f6f7..7806133 100644
--- a/tower/src/util/optional/error.rs
+++ b/tower/src/util/optional/error.rs
@@ -1,6 +1,8 @@
 use std::{error, fmt};
 
-/// Error returned if the inner `Service` has not been set.
+/// Error returned if the inner [`Service`] has not been set.
+///
+/// [`Service`]: crate::Service
 #[derive(Debug)]
 pub struct None(());
 
diff --git a/tower/src/util/optional/future.rs b/tower/src/util/optional/future.rs
index 3b3c023..1821322 100644
--- a/tower/src/util/optional/future.rs
+++ b/tower/src/util/optional/future.rs
@@ -7,7 +7,9 @@ use std::{
     task::{Context, Poll},
 };
 
-/// Response future returned by `Optional`.
+/// Response future returned by [`Optional`].
+///
+/// [`Optional`]: crate::util::Optional
 #[pin_project]
 #[derive(Debug)]
 pub struct ResponseFuture<T> {
diff --git a/tower/src/util/optional/mod.rs b/tower/src/util/optional/mod.rs
index 9ee7f51..8ba3ab9 100644
--- a/tower/src/util/optional/mod.rs
+++ b/tower/src/util/optional/mod.rs
@@ -1,11 +1,10 @@
-//! Contains `OptionService` and related types and functions.
-//!
-//! See `OptionService` documentation for more details.
+//! Contains [`Optional`] and related types and functions.
 //!
+//! See [`Optional`] documentation for more details.
 
-/// Error types for `OptionalService`.
+/// Error types for [`Optional`].
 pub mod error;
-/// Future types for `OptionalService`.
+/// Future types for [`Optional`].
 pub mod future;
 
 use self::future::ResponseFuture;
@@ -14,14 +13,16 @@ use tower_service::Service;
 
 /// Optionally forwards requests to an inner service.
 ///
-/// If the inner service is `None`, `Error::None` is returned as the response.
+/// If the inner service is [`None`], [`optional::None`] is returned as the response.
+///
+/// [`optional::None`]: crate::util::error::optional::None
 #[derive(Debug)]
 pub struct Optional<T> {
     inner: Option<T>,
 }
 
 impl<T> Optional<T> {
-    /// Create a new `OptionService`
+    /// Create a new [`Optional`].
     pub fn new<Request>(inner: Option<T>) -> Optional<T>
     where
         T: Service<Request>,
diff --git a/tower/src/util/ready.rs b/tower/src/util/ready.rs
index 2f3ec14..190fcab 100644
--- a/tower/src/util/ready.rs
+++ b/tower/src/util/ready.rs
@@ -8,9 +8,11 @@ use std::{
 };
 use tower_service::Service;
 
-/// A future that yields the service when it is ready to accept a request.
+/// A [`Future`] that yields the service when it is ready to accept a request.
 ///
-/// `ReadyOneshot` values are produced by `ServiceExt::ready_oneshot`.
+/// [`ReadyOneshot`] values are produced by [`ServiceExt::ready_oneshot`].
+///
+/// [`ServiceExt::ready_oneshot`]: crate::util::ServiceExt::ready_oneshot
 pub struct ReadyOneshot<T, Request> {
     inner: Option<T>,
     _p: PhantomData<fn() -> Request>,
@@ -62,7 +64,9 @@ where
 
 /// A future that yields a mutable reference to the service when it is ready to accept a request.
 ///
-/// `ReadyAnd` values are produced by `ServiceExt::ready_and`.
+/// [`ReadyAnd`] values are produced by [`ServiceExt::ready_and`].
+///
+/// [`ServiceExt::ready_and`]: crate::util::ServiceExt::ready_and
 pub struct ReadyAnd<'a, T, Request>(ReadyOneshot<&'a mut T, Request>);
 
 // Safety: This is safe for the same reason that the impl for ReadyOneshot is safe.
diff --git a/tower/src/util/service_fn.rs b/tower/src/util/service_fn.rs
index f109d6b..8e3335d 100644
--- a/tower/src/util/service_fn.rs
+++ b/tower/src/util/service_fn.rs
@@ -2,12 +2,12 @@ use std::future::Future;
 use std::task::{Context, Poll};
 use tower_service::Service;
 
-/// Returns a new `ServiceFn` with the given closure.
+/// Returns a new [`ServiceFn`] with the given closure.
 pub fn service_fn<T>(f: T) -> ServiceFn<T> {
     ServiceFn { f }
 }
 
-/// A `Service` implemented by a closure.
+/// A [`Service`] implemented by a closure.
 #[derive(Copy, Clone, Debug)]
 pub struct ServiceFn<T> {
     f: T,
diff --git a/tower/src/util/then.rs b/tower/src/util/then.rs
index 60b3e5c..a187b5d 100644
--- a/tower/src/util/then.rs
+++ b/tower/src/util/then.rs
@@ -6,7 +6,7 @@ use std::{
 use tower_layer::Layer;
 use tower_service::Service;
 
-/// Service returned by the [`then`] combinator.
+/// [`Service`] returned by the [`then`] combinator.
 ///
 /// [`then`]: crate::util::ServiceExt::then
 #[derive(Clone, Debug)]


Test patch:
diff --git a/tower-test/src/lib.rs b/tower-test/src/lib.rs
index 44c5359..1fa59da 100644
--- a/tower-test/src/lib.rs
+++ b/tower-test/src/lib.rs
@@ -6,6 +6,7 @@
     unreachable_pub
 )]
 #![allow(elided_lifetimes_in_paths)]
+#![deny(broken_intra_doc_links)]
 
 //! Mock `Service` that can be used in tests.