Workaround for RTN using ATPIT

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.

I recently discussed a similar idea on zulip

It could be the sugar syntax for what you propose:

trait HealthCheck {
    // async fn check(&mut self, server: Server);
    auto type Check<‘t>: Future<Output = ()> + ‘t;
    fn check<‘s>(&’s mut self, server: Server) -> Self::Check<‘s>;
}

impl HealthCheck for Thing {
    // Self::Check is inferred
    async fn check(&mut self, server: Server) {
        ...
    }
}

fn start_health_check<H>(health_check: H, server: Server)
where
    H: HealthCheck + Send + 'static,
    for<‘a> H::Check<‘a>: Send,
2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.