Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
util: add
FutureService::new
, with relaxed bounds
There are a couple issues with the current implementation of `FutureService`. The first, and less important, is a minor usability issue: there's no `FutureService::new`, just a free function that returns `FutureService`. While the free function is nice in some cases, it means that if a user *is* naming the type someplace, they need to import `tower::util::future_service` *and* `tower::util::FutureService`, which is slightly annoying. Also, it just kind of violates the common assumption that most publicly constructable types have a `new`, requiring a look at the docs. The second, more significant issue is that the `future_service` function places a `Service` bound on the future's output type. While this is of course necessary for the *`Service` impl* on `FutureService`, it's not required to construct a `FutureService`. Of course, you generally don't want to construct a `FutureService` that *won't* implement service. However, the bound also means that additional generic parameters are now required at the site where the `FutureService` is constructed. In particular, the caller must now either know the request type, or be generic over one. In practice, when other middleware returns or constructs a `FutureService`, this essentially means that it's necessary to add a `PhantomData` for the request type parameter. This complicates code, and perhaps more importantly, increases compile times, especially with deeply-ensted middleware stacks. As an example of the downside of aggressive bounds at the constructor, it's worth noting that the implementation of `FutureService` currently in `tower` is based directly on a similar implementation in `linkerd2-proxy`. Except for the difference of whether or not the constructor has a `Service` bound on the future's output, the two implementations are very similar, almost identical. This gist shows some of the change necessary to replace our otherwise identical implementation with the `tower` version that bounds the `Service` type at construction-time: https://gist.github.com/hawkw/a6b07f9f4a8bce0c4b61036ed94114db This PR solves these issues by adding a `FutureService::new` constructor that does not introduce the `Service` bound. I didn't change the `future_service` function: I don't *think* removing bounds is a breaking change, but it is a modification to a publicly exposed function's type signature, so I'm a little leery about it. Also, I thought that the more aggressive bounding at construction-time might still be useful in simpler use-cases where the `FutureService` is not part of a more complex middleware stack, and that the free fn might be more likely to be used in those cases anyway. cc @davidpdrsn
- Loading branch information