httprustrust-tokiohyper

Error: Could not find main or io in tokio, invalid return type `impl Future`


I'm on my way of converting to Rust from the ML family, but I'm finding it hard at some strange places I'm not used to having problems.

I'm trying to use hyper for http handling but can't seem to get tokio to work.

I have tried to copy paste this example:

use hyper::{body::HttpBody as _, Client};
use tokio::io::{self, AsyncWriteExt as _};

type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

#[tokio::main]
async fn main() -> Result<()> {
    // ...
    fetch_url(url).await
}


async fn fetch_url(url: hyper::Uri) -> Result<()> {
    // ...
    Ok(())
}

Here is my Cargo.toml:

[package]
name = "projectname"
version = "0.1.0"
authors = ["username"]
edition = "2018"
    
[dependencies]
hyper = "0.14.4"
tokio = "1.2.0"

It is complaining that it can't find the io crate, and that main has an invalid type impl Future, and that it can't find main in tokio:

error[E0433]: failed to resolve: could not find `main` in `tokio`
 --> src/main.rs:9:10
  |
9 | #[tokio::main]
  |          ^^^^ could not find `main` in `tokio`

error[E0277]: `main` has invalid return type `impl Future`
  --> src/main.rs:10:20
   |
10 | async fn main() -> Result<()> {
   |                    ^^^^^^^^^^ `main` can only return types that implement `Termination`

error[E0432]: unresolved import `hyper::Client`
 --> src/main.rs:3:34
  |
3 | use hyper::{body::HttpBody as _, Client};
  |                                  ^^^^^^ no `Client` in the root

error[E0425]: cannot find function `stdout` in module `io`
  --> src/main.rs:45:13
   |
45 |         io::stdout().write_all(&chunk).await?;
   |             ^^^^^^ not found in `io`
   |

error[E0432]: unresolved import `tokio::io::AsyncWriteExt`
 --> src/main.rs:4:23
  |
4 | use tokio::io::{self, AsyncWriteExt as _};
  |                       -------------^^^^^
  |                       |
  |                       no `AsyncWriteExt` in `io`
  |                       help: a similar name exists in the module: `AsyncWrite`

Is #[tokio::main] and client not in hyper?


Solution

  • The tokio::main macro converts an async main to a regular main that spawns a runtime. However, because the macro is not found is scope, it cannot transform your main function, and the compiler is complaining that your main has an invalid return type of impl Future. To fix this, you have to enable the required features to import the main macro:

    tokio = { version = "1.2.0", features = ["rt", "macros"] }
    

    You also have to enable the io-util feature to access io::AsyncWriteExt, and the io-std feature to access io::stdout. To simplify this, tokio provides the full feature flag, which will enable all optional features:

    tokio = { version = "1.2.0", features = ["full"] }
    

    You also need hyper's client and http feature flags to resolve the Client import:

    hyper = { version = "0.14.4", features = ["client", "http1", "http2"] }