How to implement async/await in main

I'm trying the first steps with async/await by writing the below:

async fn test() -> String {
    format!("Hi there")
}

async fn main() -> Result<(), ()>{
    test().await;
    println!("Hello, world!");
    Ok(())
}

But got the below error:

error[E0277]: `main` has invalid return type `impl std::future::Future`
 --> src/main.rs:5:20
  |
5 | async fn main() -> Result<(), ()>{
  |                    ^^^^^^^^^^^^^^ `main` can only return types that implement `std::process::Termination`
  |
  = help: consider using `()`, or a `Result`
1 Like

You cannot directly; many libraries have some sort of attribute that will re-write main for you.

Any example?

tokio has one, for instance:

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    ...
}
2 Likes

BTW, you need to require features = ["rt-threaded", "macros"] to get this.

1 Like

Tokio:


use tokio::net::TcpStream;
use tokio::prelude::*;

#[tokio::main]
async fn main() {
    let mut stream = TcpStream::connect("127.0.0.1:6142").await.unwrap();
    println!("created stream");

    let result = stream.write(b"hello world\n").await;
    println!("wrote to stream; success={:?}", result.is_ok());
}

Async-std


async fn say_hello() {
    println!("Hello, world!");
}

#[async_std::main]
async fn main() {
    say_hello().await;
}
3 Likes

Sorry, did not get where to use it!!

I got:

  |
6 | #[async_std::main]
  |              ^^^^ could not find `main` in `async_std`

error[E0277]: `main` has invalid return type `impl std::future::Future`

In Cargo.toml:

[dependencies]
tokio = {"version"= "0.2", features=["rt-threaded", "macros"]}

or just use "full" instead.

1 Like

And you need features = ["attributes"] in Cargo.toml for async-std::main.

2 Likes

Thanks @steveklabnik / @naim / @jameseb7 / @asymmetrikon / @kornel
But there is something I did not understand, I thought async/await is part of the stable Rust now, so why I need to use external crate for it :roll_eyes:

Rust provides a trait, which is common for all libraries. It's up to you to decide which runtime you want the futures to run on.

The runtimes I know of are tokio and async-std. They both implement futures, each have their own pros and cons.

I think that Rust wouldn't want to support an official standard runtime.

1 Like

What has been stabilized is the minimal feature set needed to enable the async await feature which requires rather extensive compiler support. Adding an executor to the standard library would mean that this specific choice of executor api is now locked down forever because of backwards compatibility. You may be interested in this thread.

5 Likes

Languages like JavaScript have a built-in event loop that is global, hardcoded and can't be customized, and JavaScript's Promise works only with that event loop.

Rust has separated interface of the Future (async/await) — an abstract concept of a function that doesn't run all at once, from the implementation of the event loop that runs these functions. You can choose how futures will be executed, and different implementations make different choices about performance, memory usage, etc.

So async/await as known from JavaScript and alike, isn't built into Rust. Only one half of it is.

3 Likes

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