-
Notifications
You must be signed in to change notification settings - Fork 625
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OptionFuture is_terminated design confusion #2475
Comments
This question is also in Pending, which impl FusedFuture with always true. select! will ignore it by Fuse::terminated() == true. futures-rs/futures-macro/src/select.rs Line 206 in c0e9368
futures-rs/futures-macro/src/select.rs Line 314 in c0e9368
futures-rs/futures-macro/src/select.rs Line 319 in c0e9368
This problem can cause strange behavior: let mut a_fut = future::pending::<()>();
let mut b_fut = future::pending::<()>();
loop {
select! {
_ = a_fut => (),
_ = b_fut => (),
complete => break,
default => panic!(), // never runs (futures run first, then complete)
};
}
println!("1") // will print out future::pending::<()>().await;
println!("1") // never print out |
I find this behaviour to be very confusing and unexpected. I fully expected the behaviour of let a_mut = future::pending::<()>();
let b_mut = async {
future::pending::<()>().await;
()
}
.boxed()
.fuse(); |
OptionFuture
's design seems inconsistent to me.The docs don't clearly explain what it's for:
Which could describe any
Future<Output = Option<_>>
.Given that it's constructed from an
Option<Future>
though, it seems clear that it's an adapter forOption<Future>
that can be awaited, yieldingSome(output)
when the future is present, andNone
when it's absent.However, it also implements
FusedFuture
(whereF: FusedFuture
at least) so thatOptionFuture::from(None).is_terminated() == true
which seems inconsistent with that interpretation.is_terminated
is documented as meaning:Which sort of means you're not supposed to await it if it's none?
And practically speaking, FusedFuture affects the behavior of
select!
, which will skip over futures that are terminated (so it can safely be used in a loop). OptionFuture's current implementation will result in it getting skipped entirely for theNone
case which is surprising if you're just expecting it to be an adapter that'll produceNone
.One might suggest that this
None
-skipping behavior is desirable, as a solution for #2270. But for that usecase, why is the result wrapped in aSome()
? And why can you create anOptionFuture
from a!FusedFuture
which doesn't work this way?A third option (pun not intended) is suggested by #2457 which is to have none mean terminated and have the inner transition to None after the future completes. Which would make
OptionFuture::from(None)
very similar toFuse::terminated()
, except polling/awaiting it yieldsNone
rather than panicking.Personally I think the adapter interpretation is correct, and
OptionFuture
should not implementFusedFuture
. If that's desirable I'd be happy to send a PR. But I admit I haven't personally found a use forOptionFuture
in code I've written, so maybe I'm missing the point here?The text was updated successfully, but these errors were encountered: