I've attempted to create the smallest, interesting "hello world" app, and it works fine with features = ["full"] and fails when selecting specific features
$ cargo tree | grep tokio
tokio-hello-world v0.1.0 (/Users/sallen/src/rust/tokio-hello-world)
└── tokio v0.2.8
└── tokio-macros v0.2.3
$ uname -a
Darwin newair.local 18.7.0 Darwin Kernel Version 18.7.0: Sun Dec 1 18:59:03 PST 2019; root:xnu-4903.278.19~1/RELEASE_X86_64 x86_64 i386 MacBookAir8,1 Darwin
[dependencies]
tokio = { version = "0.2", features = ["macros", "tcp"] }
use tokio::net::TcpStream;
use tokio::prelude::*;
#[tokio::main]
async fn main() {
// Open a TCP stream to the socket address.
//
// Note that this is the Tokio TcpStream, which is fully async.
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());
}
I must be missing something very basic. Here are the errors:
Compiling tokio-hello-world v0.1.0 (/Users/sallen/src/rust/tokio-hello-world)
error[E0433]: failed to resolve: could not find `main` in `tokio`
--> src/main.rs:6:10
|
6 | #[tokio::main]
| ^^^^ could not find `main` in `tokio`
warning: unused import: `tokio::prelude::*`
--> src/main.rs:4:5
|
4 | use tokio::prelude::*;
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0277]: the trait bound `str: tokio::net::addr::ToSocketAddrs` is not satisfied
--> src/main.rs:11:41
|
11 | let mut stream = TcpStream::connect("127.0.0.1:6142").await.unwrap();
| ^^^^^^^^^^^^^^^^ the trait `tokio::net::addr::ToSocketAddrs` is not implemented for `str`
|
::: /Users/sallen/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.8/src/net/tcp/stream.rs:79:29
|
79 | pub async fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
| ------------- required by this bound in `tokio::net::tcp::stream::TcpStream::connect`
|
= note: required because of the requirements on the impl of `tokio::net::addr::ToSocketAddrs` for `&str`
error[E0599]: no method named `write` found for type `tokio::net::tcp::stream::TcpStream` in the current scope
--> src/main.rs:14:25
|
14 | let result = stream.write(b"hello world\n").await;
| ^^^^^ method not found in `tokio::net::tcp::stream::TcpStream`
error[E0277]: `main` has invalid return type `impl std::future::Future`
--> src/main.rs:7:17
|
7 | async fn main() {
| ^ `main` can only return types that implement `std::process::Termination`
|
= help: consider using `()`, or a `Result`
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0277, E0433, E0599.
For more information about an error, try `rustc --explain E0277`.
I think this is the simplest set of features needed:
tokio = { version = "0.2", features = ["macros", "tcp", "dns", "io-util"] }
Off the top of my head I believe tokio::main required both macros and rt-core. The idea is that main starts a runtime so it needs both. In theory, we may add macros that do not require rt-core so we did not want to couple the macros feature flag with rt-core.
I will try to write a proposal for macros / runtime for 0.3 as there is a lot of weirdness that needs to be smoothed out (this was our first attempt)
tokio::main in particular is... well, weird: https://docs.rs/tokio/0.2.8/src/tokio/lib.rs.html#266
It definitely needs macros, it looks like it needs rt-core, and which macro is used depends on whether or not rt-threaded is used. Somewhere in the layers of macros it gets documented as only needing rt-threaded.
tokio::main requiring the rt-core feature seems to be a breaking change in 0.2.7, with older versions only macros was needed
That is unfortunate. I will look into that.
To confirm, the current docs for these macros only show the need for the _rt-threaded_ feature, which is clearly wrong:
https://docs.rs/tokio/0.2.11/tokio/index.html#attributes
The current approach to using nested macros to apply doc(cfg(feature = …))) attributes, seems to have limitations:
Only one set of features is chosen at cargo doc time (--all-features for docs.rs), so I don't see how the macro approach could fully express the requirements (e.g. feature1 _or_ feature2) in cases like this?
AFAICT, the macros fail to apply all nested required features in doc(cfg), in complex cases such as this.
Most helpful comment
I think this is the simplest set of features needed:
tokio = { version = "0.2", features = ["macros", "tcp", "dns", "io-util"] }