rusttonicrust-tonic

oneshot::channel `tokio::sync::oneshot::Receiver<()>` is not an iterator add `use futures_util::FutureExt`


In the tokio tests I see they use oneshot::channel together with serve_with_shutdown but the the compiler tells me to add use futures_util::future::future::FutureExt but as you can see in the example below I already added that trait to the scope.

What am I missing?

Here a reprex

run cargo new tokio-test

Cargo.toml

[package]
name = "tokio-test"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tonic = "0.7"
prost = "0.10.1"
tokio = { version = "1.18", features = ["macros", "rt-multi-thread"] }

[build-dependencies]
tonic-build = "0.7.2"

src/main.rs

pub mod console {
    tonic::include_proto!("console");
}
use console::console_server::{Console, ConsoleServer};
use console::{ConsoleResponse, InfoRequest};

use tokio::runtime::Runtime;
use tokio::sync::oneshot;
use tonic::{transport::Server, Request, Response};
use futures_util::FutureExt;

#[derive(Default)]
pub struct ConsoleImpl {}

#[tonic::async_trait]
impl Console for ConsoleImpl {
    async fn info(
        &self,
        request: Request<InfoRequest>,
    ) -> Result<Response<ConsoleResponse>, tonic::Status> {
        println!("{}", request.get_ref().text);
        Ok(Response::new(ConsoleResponse {}))
    }

}

fn main() {
    let addr = "[::1]:50051".parse().unwrap();
    let maxconsole = ConsoleImpl::default();
    println!("Console server listening on {}", addr);

    let mut rt = Runtime::new().expect("failed to obtain a new RunTime object");
    let (shutdown_send, shutdown_recv) = oneshot::channel::<()>();

    let server_future = Server::builder()
        .add_service(ConsoleServer::new(maxconsole))
        // .serve(addr)
        .serve_with_incoming_shutdown(
            addr,
            shutdown_recv.map(drop),
        );
    rt.block_on(server_future).expect("failed to successfully run the future on RunTime");
}

src/console.proto

syntax = "proto3";

package console;

service Console {
  rpc info (InfoRequest) returns (ConsoleResponse) {}
}


message InfoRequest {
  string text = 1;
}


message ConsoleResponse {
}

If you build the project it will complain

❯ cargo build
    Updating crates.io index
   Compiling tokio-test v0.1.0 (C:\s\tokio-test)
error[E0432]: unresolved import `futures_util`
  --> src\main.rs:10:5
   |
10 | use futures_util::FutureExt;
   |     ^^^^^^^^^^^^ use of undeclared crate or module `futures_util`

error[E0599]: `tokio::sync::oneshot::Receiver<()>` is not an iterator
   --> src\main.rs:40:27
    |
40  |             shutdown_recv.map(drop),
    |                           ^^^ `tokio::sync::oneshot::Receiver<()>` is not an iterator
    |
   ::: C:\Users\FrancescElies\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-1.20.1\src\sync\oneshot.rs:318:1
    |
318 | pub struct Receiver<T> {
    | ---------------------- doesn't satisfy `tokio::sync::oneshot::Receiver<()>: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `tokio::sync::oneshot::Receiver<()>: Iterator`
            which is required by `&mut tokio::sync::oneshot::Receiver<()>: Iterator`
    = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
1   | use futures_util::future::future::FutureExt;
    |

Some errors have detailed explanations: E0432, E0599.
For more information about an error, try `rustc --explain E0432`.
error: could not compile `tokio-test` due to 2 previous errors

Solution

  • Yes, you added the FutureExt import, but did not tell Rust where to find that crate. The critical part of the error message is:

    error[E0432]: unresolved import `futures_util`
      --> src\main.rs:10:5
       |
    10 | use futures_util::FutureExt;
       |     ^^^^^^^^^^^^ use of undeclared crate or module `futures_util`
    

    This can be fixed by adding the futures_util crate to your Cargo.toml dependency section.