smol-rs / async-channel

Async multi-producer multi-consumer channel
Apache License 2.0
726 stars 38 forks source link

async_channel::Receiver::poll_next can not be used because Receiver is unpinnable #74

Closed oblique closed 7 months ago

oblique commented 7 months ago

The following does not compile from v2.0.0 and after:

use futures::Stream;
use std::pin::Pin;
use std::task::{Context, Poll};

struct RecvU32(async_channel::Receiver<u32>);

impl Stream for RecvU32 {
    type Item = u32;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<u32>> {
        Pin::new(&mut self.0).poll_next(cx)
    }
}

This is the error message:

error[E0277]: `PhantomPinned` cannot be unpinned
   --> src/main.rs:11:18
    |
11  |         Pin::new(&mut self.0).poll_next(cx)
    |         -------- ^^^^^^^^^^^ within `(PhantomData<&()>, PhantomPinned)`, the trait `Unpin` is not implemented for `PhantomPinned`
    |         |
    |         required by a bound introduced by this call
    |
    = note: consider using the `pin!` macro
            consider using `Box::pin` if you need to access the pinned value outside of the current scope
    = note: required because it appears within the type `(PhantomData<&()>, PhantomPinned)`
    = note: required for `event_listener::EventListener` to implement `Unpin`
note: required because it appears within the type `__Origin<'_, u32>`
   --> /home/oblique/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-channel-2.1.0/src/lib.rs:480:1
    |
480 | / pin_project_lite::pin_project! {
481 | |     /// The receiving side of a channel.
482 | |     ///
483 | |     /// Receivers can be cloned and shared among threads. When all receivers associated with a channel
...   |
507 | |     }
508 | | }
    | |_^
    = note: required for `async_channel::Receiver<u32>` to implement `Unpin`
note: required by a bound in `Pin::<P>::new`
   --> /home/oblique/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/pin.rs:484:23
    |
484 | impl<P: Deref<Target: Unpin>> Pin<P> {
    |                       ^^^^^ required by this bound in `Pin::<P>::new`
...
503 |     pub const fn new(pointer: P) -> Pin<P> {
    |                  --- required by a bound in this associated function
    = note: this error originates in the macro `$crate::__pin_project_make_unpin_impl` which comes from the expansion of the macro `pin_project_lite::pin_project` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.
error: could not compile `tt` (bin "tt") due to previous error

Was this a design decision?

notgull commented 7 months ago

Yes, it allows for a significant optimization in the event handling mechanism. To get around this you can box and pin the receiver. Or, alternatively, you can pin project your stream type.

oblique commented 7 months ago

Ok. Thank you