I want to call async function in Future::poll(), but the poll() is not async function, so I have to poll the async fn, but got error:
error[E0599]: no method named `poll` found for opaque type `impl Future` in the current scope
--> src\lib.rs:18:22
|
18 | let a = fut1.poll(cx);
| ^^^^ method not found in `impl Future`
I try to Pin::new(async fn()).poll(), got another error:
error[E0277]: `from_generator::GenFuture<[static generator@src\lib.rs:33:23: 36:2 {ResumeTy, u64, Duration, impl Future, ()}]>` cannot be unpinned
--> src\lib.rs:22:23
|
22 | let pinfut1 = Pin::new(&mut fut1);
| ^^^^^^^^ within `impl Future`, the trait `Unpin` is not implemented for `from_generator::GenFuture<[static generator@src\lib.rs:33:23: 36:2 {ResumeTy, u64, Duration, impl Future, ()}]>`
...
33 | async fn fn1() -> i32 {
| --- within this `impl Future`
code:
use std::future::Future;
use std::task::{Context, Poll};
use std::pin::Pin;
use std::sync::{Arc,Mutex};
#[pin_project::pin_project]
struct Person<'a> {
name: &'a str,
age: i32,
}
impl<'a> Future for Person<'a> {
type Output = i32;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
*this.age += 1;
// error: poll() ^^^^ method not found in `impl Future`
// let mut fut1 = fn1();
// let a = fut1.poll(cx);
// error: Pin::new() ^^^^^^^^ within `impl Future`, the trait `Unpin` is not implemented for `from_generator::GenFuture
let mut fut1 = fn1();
let pinfut1 = Pin::new(&mut fut1);
let a = pinfut1.poll(cx);
if *this.age > 4 {
Poll::Ready(*this.age)
} else {
Poll::Pending
}
}
}
async fn fn1() -> i32 {
async_std::task::sleep(std::time::Duration::from_secs(2)).await;
123
}
fn main() {
let p1 = Person {name: "jack", age: Default::default()};
async_std::task::block_on(async {
let a = p1.await;
dbg!(a);
});
}
To call poll
on fut1
which is returned by fn1
, you need to obtain a Pin<&mut F>
, where F
is the type of the future fut1
. There are at least three possibilities to do this (I omit unsafe
):
fut1
implements Unpin
, you can call Pin::new
,fut1
on the heap by using Box::pin
, orfut1
on the stack by using the futures_util::pin_mut!
macro.It is sometimes a little bit hard to figure out whether Unpin
is implemented, and if not, then why. A general advice here is to desugar the signature of fn1
into: fn fn1() -> impl Future<Output = usize> + Unpin
. The compiler errors are usually more precise then.
The implementation of the pin_mut!
macro has some useful insights, btw. It uses the Rust type system to move the future and shadows the variable, s.t. it cannot be accessed anymore, and by doing this, it guarantees that the invariants of Pin::new_unchecked
are satisfied and therefore it can call it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With