You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
select! is awesome. But we require FusedFutures for it. That currently introduces a few downsides:
Libraries must all depend futures-core in order to make their futures support select! without going the extra .fuse() way. Lots of libraries which just build some fundamental futures might otherwise not need that.
We have everywhere multiple trait bounds. One for Future and one for FusedFuture.
It makes it not convenient to create fuse wrappers around Futures which might not might not be FusedFutures. .fuse() actually is broken for cases where the inner future is already a FusedFuture and is terminated. Then it shouldn't be called again, but the Fuse will tell us it's ok. The problem might get solved via specialization, if we can let fuse() return something different depending on whether the receiver is already a FusedFuture or not. But doesn't seem to be on the near-term roadmap.
One thing which I thought would be great when working on the select! improvements is to also add the ability to automatically fuse futures if they are provided as expressions instead of a path. So that this would work without adding any .fuse():
asyncfnmake_fut(){5}select!{
x = make_fut() => x, // no .fuse()}
which doesn't work with the current approach.
Therefore I wondered we could somehow make this work by moving the fusing concept somewhere else. The how is more of a brainstorm that a good proposal. But what I thought could work is adding is_terminated and another method that tells us whether the Future naturally supports fusing to Future itself, and provide default implementations for backward compatibility. Those could look like:
traitFuture{// ... existing stuff/// This equals the default behavior of futures, that they can be polled after terminationfnis_terminated(&self) -> {false}/// Whether the Future implementation provides an exact termination statusfnsupports_termination_status(&self) -> bool{false}}
We could then implement a generically correct .fuse() -> Fuse with:
Could it make sense to think about this before FusedFuture gets released as the canonical solution? Or would the general strategy be to rely on this as a separate trait and wait for new Rust language features like specialization to fill the gaps?
The text was updated successfully, but these errors were encountered:
I think it is misjudgement in FusedFuture trait definition that it allows for is_terminated() to be true before future had returned Poll::Ready.
Allowing a future to terminate without producing a value crates a new distinct
way to terminate it. For reasons already described it is unrealistic to expect
that all wrappers will propagate such a termination status correctly. If a
future might not produce the value T, it should use Option<T> or a Result<T> instead, rather than trying to express it through FusedFuture
API.
On the other hand if FusedFuture::is_terminated() were to indicate whether a
future returned Poll::Ready already, then using .fuse() on a future that
implements FusedFuture would preserve the meaning of termination.
Note that the case where a user fuses a future that already returned Poll:Ready is clearly a misuse of the API (in similar fashion to fusing an
iterator that already returned None). In contrast currently it is impossible to
avoid using a .fuse() on a future that is terminated, since termination is
outside user control and might change in concurrent fashion e.g., future might
indicate termination when another thread closes the channel used by the future.
select!
is awesome. But we requireFusedFuture
s for it. That currently introduces a few downsides:futures-core
in order to make their futures supportselect!
without going the extra.fuse()
way. Lots of libraries which just build some fundamental futures might otherwise not need that.Future
and one forFusedFuture
.Future
s which might not might not beFusedFuture
s..fuse()
actually is broken for cases where the inner future is already aFusedFuture
and is terminated. Then it shouldn't be called again, but theFuse
will tell us it's ok. The problem might get solved via specialization, if we can letfuse()
return something different depending on whether the receiver is already aFusedFuture
or not. But doesn't seem to be on the near-term roadmap.One thing which I thought would be great when working on the
select!
improvements is to also add the ability to automatically fuse futures if they are provided as expressions instead of a path. So that this would work without adding any.fuse()
:which doesn't work with the current approach.
Therefore I wondered we could somehow make this work by moving the fusing concept somewhere else. The how is more of a brainstorm that a good proposal. But what I thought could work is adding
is_terminated
and another method that tells us whether theFuture
naturally supports fusing toFuture
itself, and provide default implementations for backward compatibility. Those could look like:We could then implement a generically correct
.fuse() -> Fuse
with:Could it make sense to think about this before
FusedFuture
gets released as the canonical solution? Or would the general strategy be to rely on this as a separate trait and wait for new Rust language features like specialization to fill the gaps?The text was updated successfully, but these errors were encountered: