futures-rs
futures-rs copied to clipboard
oneshot::Receiver's FusedFuture implementation is problematic
oneshot::Receiver
's FusedFuture::is_terminated
implementation will return true if the associated Sender
is dropped without sending anything. I don't think this is the right behavior--it makes it hard to use a oneshot in a select!
since it becomes impossible to detect the drop case.
For example, this panics because all futures have terminated.
fn main() {
futures::executor::block_on(async {
let (send, mut recv) = futures::channel::oneshot::channel::<()>();
drop(send);
futures::select! {
_ = recv => ()
}
})
}
IMO this implementation is simply wrong.
(An underlying cause is that the docs for FustedFuture::is_terminated
are vague about precisely what "should not be polled" means.)
Our (Arti project's) ticket about this and what we might do about it: https://gitlab.torproject.org/tpo/core/arti/-/issues/1059
OptionFuture
seems similarly afflicted. I'm making an MR.
Oh dear. There is a big problem with select!
's "complete
" feature. That requires every future to know whether it has returned Ready
, and that's what FusedFuture
is supposed to produce.
I think the data stored by (say) oneshot::Receiver
is not sufficient to implement futures::select!
; we must choose between an implementation which is always broken, and an implementation which doesn't work with complete =>
.
I think I will have to write a new ticket.
I think select!
is irreparably broken. We have been migrating our code off of select!
and onto the trait-based mechanisms in https://github.com/yoshuawuyts/futures-concurrency.
That issue made me mad before I understood the issue was FusedFuture
implementation for oneshot::Receiver
...