rust-lang / futures-rs

Zero-cost asynchronous programming in Rust
https://rust-lang.github.io/futures-rs/
Apache License 2.0
5.35k stars 619 forks source link

Misleading documentation for `mpsc::channel`? #2721

Open mgoldenberg opened 1 year ago

mgoldenberg commented 1 year ago

When creating an mpsc::channel with a capacity of 0, calling Sink::send on the Sender will await forever. Here is an example, which is also copied below for ease of viewing.

use futures::{self, StreamExt, SinkExt}; // 0.3.27

#[tokio::main]
async fn main() {
    let (mut sender, mut receiver) = futures::channel::mpsc::channel(0);
    println!("{:?}", sender.send(1).await); // awaits forever
    println!("{:?}", receiver.next().await);
}

The behavior here is definitely intuitive, but I think the documentation is perhaps a bit misleading. It states:

The channel’s capacity is equal to buffer + num-senders. In other words, each sender gets a guaranteed slot in the channel capacity, and on top of that there are buffer “first come, first serve” slots available to all senders.

Looking at the example, I would expect that the call to send waits forever. But reading the documentation, I would think the channel had the capacity to hold on to at least one item.

mgoldenberg commented 1 year ago

Interestingly, Sink::feed() seems to be consistent with the documentation (see here, copied below for ease of viewing).

use futures::{self, StreamExt, SinkExt}; // 0.3.27

#[tokio::main]
async fn main() {
    let (mut sender, mut receiver) = futures::channel::mpsc::channel(0);
    println!("{:?}", sender.feed(1).await); // prints Ok(())
    println!("{:?}", receiver.next().await); // prints Some(1)
}