why we should wrap Pin
on a Unpin
if call fuse()
outside a select!
, if it have no effect
Because it is not Unpin
:
error[E0277]: `from_generator::GenFuture<[static generator@src/lib.rs:3:49: 5:2]>` cannot be unpinned
--> src/lib.rs:12:15
|
12 | let res = select! {
| _______________^
13 | | a_res = fut_1 => a_res,
14 | | b_res = fut_2 => b_res,
15 | | };
| |_____^ within `futures::future::future::fuse::_::__Origin<'_, impl futures::Future<Output = usize>>`, the trait `Unpin` is not implemented for `from_generator::GenFuture<[static generator@src/lib.rs:3:49: 5:2]>`
|
= note: consider using `Box::pin`
= note: required because it appears within the type `impl futures::Future<Output = usize>`
= note: required because it appears within the type `impl futures::Future<Output = usize>`
= note: required because it appears within the type `Option<impl futures::Future<Output = usize>>`
= note: required because it appears within the type `futures::future::future::fuse::_::__Origin<'_, impl futures::Future<Output = usize>>`
= note: required because of the requirements on the impl of `Unpin` for `futures::future::Fuse<impl futures::Future<Output = usize>>`
note: required by a bound in `futures_util::async_await::assert_unpin`
--> /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.21/src/async_await/mod.rs:50:24
|
50 | pub fn assert_unpin<T: Unpin>(_: &T) {}
| ^^^^^ required by this bound in `futures_util::async_await::assert_unpin`
= note: this error originates in the macro `$crate::select_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
So it is not valid for select!
. However, even for !Unpin
value, if we pin it the pinned value does implement Unpin
(not because of Pin
itself but because Box
and references are always Unpin
).
why a Pin
could be used in expression of select!
and pass the checker if there needs a Unpin
.
Because the macro can pin the result of the call itself. However, when using variables directly it cannot do that soundly.