notes

Log | Files | Refs | README

async_futures.md (1835B)


      1 # Async Futures
      2 
      3 These two signatures are functionally equivalent — `async fn` is just syntactic
      4 sugar that the compiler desugars into the explicit `impl Future` form.
      5 
      6 ```rust
      7 trait T {
      8   async fn f(&self) -> u32;
      9 }
     10 ```
     11 
     12 ```rust
     13 trait T {
     14   fn f(&self) -> impl Future<Output = u32>;
     15 }
     16 ```
     17 
     18 ### Question: whats the different between:
     19 
     20 ```rust
     21 fn create_user(user: NewUser, pool: &Pool<Postgres>) -> impl std::future::Future<Output = sqlx::Result<User>> + Send;
     22 ```
     23 
     24 and
     25 
     26 ```rust
     27 async fn create_user(user: NewUser, pool: &Pool<Postgres>) -> sqlx::Result<User>;
     28 ```
     29 
     30 ## What the compiler does
     31 
     32 When you write:
     33 
     34 ```rust
     35 async fn create_user(user: NewUser, pool: &Pool<Postgres>) -> sqlx::Result<User>
     36 ```
     37 
     38 The compiler automatically rewrites it to something like:
     39 (rust-lang)[https://blog.rust-lang.org/inside-rust/2022/11/17/async-fn-in-trait-nightly.html]
     40 
     41 ```rust
     42 fn create_user(user: NewUser, pool: &Pool<Postgres>) -> impl Future<Output = sqlx::Result<User>> + '_
     43 ```
     44 
     45 So the first signature in your example is just the explicit version of what
     46 async fn does implicitly.
     47 
     48 The + Send detail The most important practical difference in your specific
     49 example is the explicit `+ Send` bound on the first signature. This guarantees
     50 the returned future is safe to send across threads, which is required when
     51 spawning tasks with `tokio::spawn`. With `async fn`, whether the future is
     52 `Send` is inferred from the function body — if any non-`Send` type is held
     53 across an .await` point, the compiler will reject it without giving you an
     54 explicit contract.
     55 [rust-lang](https://rust-lang.github.io/async-book/part-guide/more-async-await.html)
     56     57 
     58 So the explicit form is useful when you're writing trait objects, function
     59 pointers, or want to enforce `Send` as part of a public API contract, while
     60 `async
     61 fn` is preferred for everyday use.