These two signatures are functionally equivalent — async fn is just syntactic
sugar that the compiler desugars into the explicit impl Future form.
trait T {
async fn f(&self) -> u32;
}trait T {
fn f(&self) -> impl Future<Output = u32>;
}Question: whats the different between:
fn create_user(user: NewUser, pool: &Pool<Postgres>) -> impl std::future::Future<Output = sqlx::Result<User>> + Send;and
async fn create_user(user: NewUser, pool: &Pool<Postgres>) -> sqlx::Result<User>;What the compiler does
When you write:
async fn create_user(user: NewUser, pool: &Pool<Postgres>) -> sqlx::Result<User>The compiler automatically rewrites it to something like: (rust-lang)[https://blog.rust-lang.org/inside-rust/2022/11/17/async-fn-in-trait-nightly.html]
fn create_user(user: NewUser, pool: &Pool<Postgres>) -> impl Future<Output = sqlx::Result<User>> + '_So the first signature in your example is just the explicit version of what async fn does implicitly.
The + Send detail The most important practical difference in your specific
example is the explicit + Send bound on the first signature. This guarantees
the returned future is safe to send across threads, which is required when
spawning tasks with tokio::spawn. With async fn, whether the future is
Send is inferred from the function body — if any non-Send type is held
across an .await` point, the compiler will reject it without giving you an
explicit contract.
rust-lang
So the explicit form is useful when you’re writing trait objects, function
pointers, or want to enforce Send as part of a public API contract, while
async fn is preferred for everyday use.