Skip to content

Buffered stream losing Send marker #2636

@Tuetuopay

Description

@Tuetuopay

Hi,

I hit a higher-ranked lifetime error when using buffered streams, where the compiler complains that it cannot prove the future consuming the stream are Send, despite the stream itself being Send.

use futures::stream::{empty, StreamExt};
use std::future::ready;

fn send<T: Send>(_: T) {}

fn main() {
    send(async {
        empty().map(ready::<&()>).buffered(0).next().await
    });
}

Resulting error:

   Compiling playground v0.0.1 (/playground)
error: higher-ranked lifetime error
 --> src/main.rs:7:5
  |
7 | /     send(async {
8 | |         empty().map(ready::<&()>).buffered(0).next().await
9 | |     });
  | |______^
  |
  = note: could not prove for<'r> impl futures::Future<Output = Option<&'r ()>>: std::marker::Send

error: could not compile `playground` due to previous error

Buffered is the key here, as dropping it to use .then() instead of .map() + buffered() compiles fine. This shows that the stream and its future is definitely send, and the buffering makes it weird. I cannot see which bound in the Buffered struct/future makes the resulting stream !Send.

use futures::stream::{empty, StreamExt};
use std::future::ready;

fn send<T: Send>(_: T) {}

fn main() {
    send(async {
        empty().then(ready::<&()>).next().await
    });
}

Obviously, I need buffered for parallelism of the futures, as they do some long-ish network calls; and the Send requirement comes from Tonic's usage of async_trait that requires futures to be Send.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions