Why are some trait methods declared as synchronous when they return a Future?

I am writing an implementation of the bb8::ManageConnection trait.

The documentation lists the methods as synchronous (declaring them with fn and not async fn), but they return futures. This is apparently standard Rust, so why is it done like this?

AI tells me that this gives the code more flexibility and allows the caller to be unconcerned with whether the function is async or not. But, if the function returns a future wouldn't the caller have to know this in order to handle it?

If synchronous and asynchronous return types are mutually exclusive (an fn must not return a future, an async fn must return a future) how would this provide any flexibility at all? It seems like it just makes it confusing by not having a mismatched sync status and return type.

Writing

async fn connect(&self) -> Result<Self::Connection, Self::Error>;

is short-hand for:

fn connect(
    &self,
) -> impl Future<Output = Result<Self::Connection, Self::Error>>;

which does not include the + Send part. Currently there is no way to add + Send while using the async fn short-hand which is why they use the long form instead.

4 Likes

Thank you for the response!
A language limitation, this makes sense now.

Resources for Googlers:
Question about async fn in traits: return type is Send or not
Relevant Rust RFC