In the stabilization for async fn in traits (AFIT) and return position impl trait in traits (RPITIT), there was some discussion about possibly needing return type notation (RTN) in order to support Send bounds.
This was decided against, in favor of just linting against async functions in trait definitions for now, with an open question for possibly implementing RTN in the future to solve this.
I had been mulling over this, and realized that instead of RTN, it is also possible to use associated type position impl trait (ATPIT), together with a new trait and a blanket impl, to bound on an existing AFIT's return type: Rust Playground (this is using the examples from this blog post).
trait HealthCheckDesugared {
type MethodRet<'a>: std::future::Future<Output = ()> + 'a
where
Self: 'a;
fn check_desugared<'s>(&'s mut self, server: a::Server) -> Self::MethodRet<'s>;
}
impl<T: a::HealthCheck> HealthCheckDesugared for T {
type MethodRet<'s> = impl std::future::Future<Output = ()> + 's where T: 's;
fn check_desugared<'s>(&'s mut self, server: a::Server) -> Self::MethodRet<'s> {
return self.check(server);
}
}
With implementable trait aliases, it appears to even be possible for upstream to provide such an aliased/desugared trait.
Long-term, it may still be useful to have RTN on its own. However, since there are still syntax/semantics questions around RTN, while ATPIT seems much more likely to be stabilized soon, this seems like a useful workaround.