rust-lang / rust-lang/rfcs

Proposal: async box fn Syntax

Open
#3,326 2 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Markdown
Stars
6.6k
Forks
1.7k
Avg merge
16h 14m
Merged PRs (30d)
1

Description

Why Rust should re-add box keyword for async function

async fn return type is a static dispatch trait type, which means that the compiler will replace it with a concrete type at compile time.
In following example the concrete type which implements the Future<Output = ()> trait is generated by the compiler, in other words, the concrete type of return value is unknown when we write the code.

The following examples are equivalent, you can understand the code below as the expansion of the code above.

async fn hello_world() -> () {
    // ...
}
use std::future::Future;
fn hello_world() -> impl<Future<Output = ()>> {
    // ...
}
Function pointer type

We cannot use impl keyword for fn pointer, it's not allowed in the fn pointer return.

type AsyncFn = fn() -> impl Future<Output = ()>;
// error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return

And we cannot use dyn keyword too, because use .await object must implements IntoFuture trait, which requires a Sized object, but dyn objects are !Sized.

type AsyncFn = fn() -> dyn Future<Output = ()>;
async fn run_async_fn(async_fn: AsyncFn) {
    async_fn().await;
    // error[E0277]: the size for values of type `dyn Future<Output = ()>` cannot be known at compilation time
    // = help: the trait `Sized` is not implemented for `dyn Future<Output = ()>`
    // = note: required because of the requirements on the impl of `IntoFuture` for `dyn Future<Output = ()>
}

But we can wrap the return type with Pin<Box<dyn Trait>>, pass it into a function without knowing concrete type or complicated generic trait bounds, and it works fine.

type BoxedAsyncFn = fn() -> Pin<Box<dyn Future<Output = ()> + Send >>;

fn run_boxed_async_fn(boxed_async_fn: BoxedAsyncFn) {
    boxed_async_fn().await;
}
Syntax

The async box fn syntax should be expand as the code below. It's easy to understand, just wrapping the return type with Pin<Box<dyn Trait>>.

async box fn hello_world() -> () {
    // ...
}
use std::future::Future;
fn hello_world() -> Pin<Box<dyn Future<Output = ()> + Send >> {
    // ...
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue itself is the only entry point provided and names no files or tests. Start by reviewing the proposed async box fn syntax and its Pin<Box<dyn Future...>> expansion; done would require an accepted RFC specifying the syntax and semantics.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.