pin-project icon indicating copy to clipboard operation
pin-project copied to clipboard

Pin-projecting in-line tuples

Open yoshuawuyts opened this issue 3 years ago • 2 comments

The following currently works:

use pin_project::pin_project;
use core::future::Future;

#[pin_project]
struct Pinned<A: Future, B: Future>(#[pin] A, #[pin] B);

But this doesn't:

use pin_project::pin_project;
use core::future::Future;

#[pin_project]
struct Pinned<A: Future, B: Future> {
    futures: (#[pin] A, #[pin] B),
}

So instead we now have to do:

use pin_project::pin_project;
use core::future::Future;

#[pin_project]
struct Futures<A: Future, B: Future> (#[pin] A, #[pin] B);

#[pin_project]
struct Pinned<A: Future, B: Future> {
    futures: Futures<A, B>,
}

We ran into some issues with this in https://github.com/yoshuawuyts/futures-concurrency/pull/74. I'm not sure how feasible this would be to provide, but being able to pin-project into individual enum fields would save us from having to generate an intermediate struct. So I figured I'd raise it here; hope that's alright!

yoshuawuyts avatar Nov 17 '22 12:11 yoshuawuyts

Thanks for the suggestion! At first glance, this seems reasonable to me.

taiki-e avatar Nov 18 '22 03:11 taiki-e

Another approach is providing a trait for pin projection and implementing it for tuples. This allows the removal of tuple-struct workaround. However, unfortunately, this approach cannot support arbitrarily sized tuples, though. As mentioned in 1.0.0 tracking issue, this approach needs recently stabilized GAT. Something like the following:

trait PinProject {
    type Projection<'a>;
    fn project<'a>(self: Pin<&'a mut Self>) -> Self::Projection<'a>;
}

On the other hand, this probably has the advantage of being able to support slices and arrays. (Self::Projection will probably be the iterator instead of slice/array, though.)

(We can probably provide both.)

taiki-e avatar Nov 18 '22 03:11 taiki-e