As far as I understand, you’re after two things here.
First, shortening bounds by writing MyTrait instead of the whole Service bound
This can already be achieved by defining a trait such as
pub trait MyTrait: Service<MyRequest, Response = MyResponse, Error = MyErr> {}
impl<T: ?Sized> MyTrait for T where T: Service<MyRequest, Response = MyResponse, Error = MyErr> {}
Second, a more concise way of implementing of the relevant Service<MyResponse> trait. This is where Rust’s trait system still has room for improvement IMO, as something like
impl<T: ?Sized> Service<MyRequest> for T
where
T: ImplementMyTrait,
{
type Response = MyResponse;
type Error = MyErr;
type Future = <Self as ImplementMyTrait>::Future;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
ImplementMyTrait::poll_ready(self, cx)
}
fn call(&mut self, req: MyRequest) -> Self::Future {
ImplementMyTrait::call(self, req)
}
}
Is currently not accepted. (Even though IMO, it should. Provided it happens in the same crate that defines the ImplementMyTrait trait, and with the semantics that it restricts ImplementMyTrait implementations to only be allowed whenever the implied Service<MyRequest> implementation is allowed, too, w.r.t orphan rules.)
The only workarounds are:
- Require a wrapper type, so some
impl<T: ?Sized> Service<MyRequest> for Wrapped<T> where T: ImplementMyTrait, - Require usage of a macro. Here’s a lengthy example of how that could look like.
Making these kinds of things more ergonomics – including a way to give both the trait that’s used for bounds, and the one that’s used for shorter impls the same name – should be possible with some rough feature ideas of mine that I’ve mentioned in this post. I don’t have any time this month to work developing those further.