Polling async Function - No Method Named poll

If I try to compile the code below, I get the following error:

error[E0599]: no method named `poll` found for type `impl std::future::Future` in the current scope

The documentation (https://doc.rust-lang.org/std/future/trait.Future.html) states that the poll method is required for std::future::Future, so how could there be no such method?

async fn f(){
   something_async().await;
}
fn main(){
   let x=f();
   x.poll();
}

so how could there be no such method?

I suppose the problem in poll method signature, exactly in the first argument:

fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output>;

You see, the first argument is not &Self, not &mut Self, but Pin<&mut Self>,
so to call poll, you need Pin<&mut X>, where X: Future, while you have just impl Future,
so you need pin it before calling poll.

Okay, so how do I pin it? let p=std::pin::Pin::new(&mut x); gives the error:

the trait bound `std::future::GenFuture<[static generator@src/main.rs:1:13: 3:2 {}]>: std::marker::Unpin` is not satisfied in `impl std::future::Future`

Pin is a whole deal on its own - if you want to get into the intricacies of using it, we can, but I think the simplest option is to just use Box::pin to turn T into Pin<Box<T>>. Something in a Pin is guaranteed to never move, and using a box here gives that guarantee.

Then using Pin::as_mut can grab a Pin<&mut T> from Pin<Box<T>>.


If you want to dive deeper into this, the std::pin module docs have a lot of detail about pinning itself, and chapter 4.1 of the rust book describes how this interacts with futures and why we need it. This reddit post is also pretty nice advice on concretely using it.

If you want to just use futures, though, I'd recommend reading through the async book and using an existing executor, like tokio or async-std. Or if you want a super simple executor, something like embedded_executor.

It's expected that all most Future users use an existing executor, and that the only pieces of code calling Future::poll are executor implementations.

1 Like

I tried pinning and then as_mut (see code below), but I'm still unable to poll it (see error below).

no method named `poll` found for type `std::pin::Pin<&mut impl std::future::Future>` in the current scope
async fn f(){

}
fn main(){
   let afn=f();
   let mut pbox=std::boxed::Box::pin(afn);
   let mut p=pbox.as_mut();
   p.poll();
}

I've yet to find a simple complete hello world example for async/await that doesn't use any external libraries, and it seems strange to me that Rust would make would be possible to easily define an async function, and then provide no way of actually calling (or awaiting) it. I figured there had to be a simple way to do it, but so far it seems like I'm wrong. In any case, I wanted to see if could construct a simple hello world program for async/await without having to get into choosing a library to get it to run. There are six different ones mentioned here: http://smallcultfollowing.com/babysteps/blog/2019/11/22/announcing-the-async-interviews/

I had noticed a proposal for an executor (https://github.com/rust-lang/rust/pull/65875), but it didn't seem to be met with much enthusiasm.

The error message goes on to say:

   = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
   |
3  | use std::future::Future;
   |

And indeed, importing the Future trait lets you call the poll method. However, you can't call poll without a std::task::Context, which brings us to...

async/await is very new. There is still a plan to have a simple executor included in the standard library eventually, but at this early stage, the standard library only includes the bare minimum to enable third-party executors.

You may be interested in Build your own block_on and Build your own executor.

Good point. I actually had that use line in earlier, but it didn't seem to be helping (I had other errors at the time).

Thanks for the comments. I'll take a look at those last two links. I guess the simple async/await hello world will have to wait for the standard library executor. :frowning_face:

I posted a minimum working example for resolving futures here:

It's worth noting that there is no plan for stdlib to have a executor. It's explicitly the plan that std has just enough to glue things together, and external crates do the job of executor and libraries.

Specifically, tokio has existed for a long time, and existed for a long time even before async/await was released. tokio 0.1 had no integration with std futures because it and the futures 0.1 crate were the base on which async fn and std::future::Future were designed.

It's always been the plan that you use one of these crates, tokio or otherwise, and std would only provide the glue to work between all the crates. If you're waiting for an std executor, you're probably going to be waiting a long time.

If you use tokio, then your initial program becomes

async fn f() {
   something_async().await;
}

#[tokio::main]
async fn main() {
   let x = f();
   x.await;
}

or async_std

async fn f() {
   something_async().await;
}

#[async_std::main]
async fn main() {
   let x = f();
   x.await;
}
1 Like

Oops, I mistakenly said there was, in my previous comment. I had misunderstood some of the previous discussions about this. Though, if I understand correctly, there are at least some people who hope to propose this again at some point.

1 Like

Ah- sorry! I think I'm probably a bit wrong too here, then, if there are still proposals for it. I hadn't read through the whole thread.

I.. guess it isn't out of the question. I mostly just wanted to recommend against waiting for such an executor, given that it's explicitly designed to be used with out-of-std ones.

Thanks for everyone's comments. They were very helpful for adding context around the async/await feature.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.