-
Notifications
You must be signed in to change notification settings - Fork 668
Description
Ran into quite a confusing issue in a situation like:
async fn foo<'a, St>(bar: St) -> impl Stream<...> + Send + 'a
where St: TryStream<Ok = _, Error = _> + Send + 'a
{
async_stream::stream! {
futures::pin_mut!(bar);
// eventually
bar.try_next().await;
}
}
The error I received was E0277 "St cannot be unpinned" with a help of adding an + std::marker::Unpin bound on the where clause. Now this lead me to question everything I thought I understood about pinning until I was answered on #tokio-users that TryStream is not implemented for Pin<&mut T> where T: TryStream. I guess it's not implemented because of restrictions related to the relationship of Stream between TryStream and nothing cannot be done for those details right now, however I was thinking this should be written into the documentation of TryStreamExt methods and/or maybe TryStream trait docs.
Reviewing all Unpin bounded methods in TryStreamExt:
- try_next
- try_poll_next_unpin
- compat
- into_async_read
Of these only the into_async_read has the following paragraph:
Note that because
into_async_readmoves the stream, theStreamtype must beUnpin. If you want to useinto_async_readwith a!Unpinstream, you'll first have to pin the stream. This can be done by boxing the stream usingBox::pinor pinning it to the stack using thepin_mut!macro from thepin_utilscrate.
The above paragraph appears 1:1 on StreamExt::next for example, and it's not too fitting for the TryStreamExt as the real answer would be either to Box::pin or convert to Stream before futures::pin_mut!. Also I am not sure if pin_utils should be mentioned since the pin_mut! is re-exported by futures (or even implemented, did not check).
I think a solution would be to:
- add paragraph about using TryStreamExt methods on
!Unpinvalues at the trait level docs- something about
Box::pin'ing the value or transforming it toStreamusinginto_stream()beforefutures::pin_mut!
- something about
- add links to trait level docs on the four methods which have
T: Unpinbound
Any objections, ideas, could there be a better solution overall? I don't understand any/all details behind the Stream vs. TryStream and the reason to need to call into_stream().