Simple future example - rust

I'm trying to do a simple future example. I followed https://blog.logrocket.com/a-practical-guide-to-async-in-rust/
So I did:
use futures::Future;
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
pub async fn receive_fut(
f: &mut dyn FnMut(&[u8])
) -> impl Future<Output = Result<Vec<u8>>> {
futures::future::ok(Ok(Vec::new())).await
}
but I get
error[E0277]: `std::result::Result<std::result::Result<Vec<_>, _>, _>` is not a future
--> src/lib.rs:6:10
|
6 | ) -> impl Future<Output = Result<Vec<u8>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::result::Result<std::result::Result<Vec<_>, _>, _>` is not a future
|
= help: the trait `futures::Future` is not implemented for `std::result::Result<std::result::Result<Vec<_>, _>, _>`
error: aborting due to previous error
Why std::result::Result should implement future, if I used futures::future::ok to turn it into a future result?

This is answered in the article:
Async functions differ in one important way: all your return types are “wrapped” into a Future.
You might read the documentation about Futures in Rust and think your async function needs to look like this:
async fn our_async_program() -> impl Future<Output = Result<String>> {
future::ok("Hello world".to_string()).await
}
This is wrong! If you’re doing this, you’re overthinking it. An async function already wraps the return type, so you can write functions the way you’re used to.
This is what you actually want:
async fn our_async_program() -> Result<String> {
future::ok("Hello world".to_string()).await
}
So you'd want to drop the impl Future<... part of the return type:
pub async fn receive_fut(
f: &mut dyn FnMut(&[u8])
) -> Result<Vec<u8>> {
futures::future::ok(Ok(Vec::new())).await
}
And then realize that future::ok already yields a Result::Ok, so you don't need to wrap it in Ok() again.
pub async fn receive_fut(
f: &mut dyn FnMut(&[u8])
) -> Result<Vec<u8>> {
futures::future::ok(Vec::new()).await
}

Related

Rust Dummy Future Value?

I have a use case where I need to specify a dummy Future to make a type concrete. The use case is I have a struct which takes a generic parameter, which is a Future:
let thing = Thing<Fut>::some_method().await?;
some_method is a method on Thing which does not use the Fut at all, but the compiler complains because of the compiler limitations such that the type can't be inferred and is necessary because of the async block.
Since I need a concrete sized thing for Fut, I was hoping there was something in futures_util that I could use. Right now, this is my very bad approach:
use futures::Future;
use std::pin::Pin;
struct Thing<Fut>
where
for<'b> Fut: Future<Output = ()> + Send + 'b,
{
callback: dyn Fn() -> Fut + Send + Sync,
}
impl<Fut> Thing<Fut> where for<'b> Fut: Future<Output = ()> + Send + 'b {
async fn some_method(a: i32) -> Result<(), Box<dyn std::error::Error>> {
println!("I am some_method with value {}", a);
Ok(())
}
}
struct Dummy {
}
impl Future for Dummy {
type Output = ();
fn poll(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
unimplemented!()
}
}
#[tokio::main]
async fn main() {
// this fails
Thing::some_method(3).await.unwrap();
// this works
//Thing::<Dummy>::some_method(3).await.unwrap();
}
Is there something I can leverage here to make such a dummy value available?
Here is a minimal playground example:
playground link
The error:
error[E0698]: type inside `async` block must be known in this context
--> src/main.rs:33:5
|
33 | Thing::some_method(3).await.unwrap();
| ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `Fut`
|
note: the type is part of the `async` block because of this `await`
--> src/main.rs:33:26
|
33 | Thing::some_method(3).await.unwrap();
| ^^^^^^
If you uncomment the success line, it will remove the error.
You can use std::future::Ready (or probably Pending alternatively). This is the type returned by the std::future::ready function.
use std::future::Ready;
type Dummy = Ready<()>;
#[tokio::main]
async fn main() {
Thing::<Dummy>::some_method(3).await.unwrap();
}
But if this function has no dependence on Fut, then I'd question why it's an associated function on Thing in the first place. Maybe it should be a free-standing function instead.

How can I pass a reference as a parameter into an async function in Rust? [duplicate]

I have async function to which I am passing async callback. The callback takes a reference as a parameter.
use core::future::Future;
async fn foo(bar: &u32) {}
async fn baz<F, Fut>(f: F)
where
F: FnOnce(&u32) -> Fut,
Fut: Future<Output = ()>,
{
let test: u32 = 42;
f(&test).await;
}
#[tokio::main]
async fn main() {
baz(foo).await;
}
I am getting the following error if I try to build this (playground):
error[E0308]: mismatched types
--> src/main.rs:16:5
|
16 | baz(foo).await;
| ^^^ lifetime mismatch
|
= note: expected associated type `<for<'_> fn(&u32) -> impl Future<Output = ()> {foo} as FnOnce<(&u32,)>>::Output`
found associated type `<for<'_> fn(&u32) -> impl Future<Output = ()> {foo} as FnOnce<(&u32,)>>::Output`
= note: the required lifetime does not necessarily outlive the empty lifetime
note: the lifetime requirement is introduced here
--> src/main.rs:7:24
|
7 | F: FnOnce(&u32) -> Fut,
| ^^^
I understand that it's not happy about the lifetime of the reference. However, I don't understand why.
We borrow "test"
We execute callback f (which is "foo")
There is no way for baz exits before f is done
So, it looks like there is no way for the borrow to outlive the place where test is declared.
What am I missing?
The future returned by foo() has a hidden lifetime. The desugared signature is like:
fn foo<'a>(bar: &'a u32) -> impl Future<Output = ()> + 'a {
async move {}
}
This is done so the function can hold bar across .await points. Sadly, what it means is that the function does not fulfill baz()'s bounds. The errors are obfuscated because the lifetime is hidden, but this is what the compiler is trying to tell you: the bound should be something like where F: for<'a> FnOnce(&'a u32) -> impl Future<Output = ()> + 'a, but you cannot express that in current Rust.
For more and potential solutions, see for example:
Calling a generic async function with a (mutably) borrowed argument
Specify Rust closures lifetime
Static future doesn't live long enough
Generic for FnOnce that returns a future with a lifetime
Just for solving, you can use Box instead of references.

How to pass a Future as a function argument?

I am used to Scala's Future type where you wrap whatever object you're returning in Future[..] to designate it as such.
My Rust function hello returns Query and I don't seem able to pass that result as an argument with type Future<Output = Query>. Why not and how should I type this better?
The failure occurs when I try to pass the future as an argument:
use std::future::Future;
struct Person;
struct DatabaseError;
type Query = Result<Vec<Person>, DatabaseError>;
async fn hello_future(future: &dyn Future<Output = Query>) -> bool {
future.await.is_ok()
}
async fn hello() -> Query {
unimplemented!()
}
async fn example() {
let f = hello();
hello_future(&f);
}
fn main() {}
Which fails to compile with the error:
error[E0277]: `&dyn Future<Output = Result<Vec<Person>, DatabaseError>>` is not a future
--> src/main.rs:9:5
|
9 | future.await.is_ok()
| ^^^^^^^^^^^^ `&dyn Future<Output = Result<Vec<Person>, DatabaseError>>` is not a future
|
= help: the trait `Future` is not implemented for `&dyn Future<Output = Result<Vec<Person>, DatabaseError>>`
= note: required by `poll`
async functions desugar to returning an opaque value that implements the Future trait. This means that you can accept a generic type that implements that trait. The most succinct syntax is impl Trait, but you could also introduce a named generic parameter:
async fn hello_future(future: impl Future<Output = Query>) -> bool {
future.await.is_ok()
}
async fn example() {
let f = hello();
hello_future(f);
}
See also:
Is it possible to await a &dyn Future?
What is the concrete type of a future returned from `async fn`?
Why is `impl` needed when passing traits as function parameters?
What does `impl` mean when used as the argument type or return type of a function?
How to accept an async function as an argument?
You can also use Pin<Box<dyn Future<Output = Query>>> as parameter:
async fn hello_future(future: Pin<Box<dyn Future<Output = Query>>>) -> bool {
future.await.is_ok()
}
...
async fn example() {
let f: impl Future<Output = Result<Vec<Person>, DatabaseError>> = hello();
hello_future(Box::pin(f));
}
The difference is that impl Future is compile-time dispatch. Compiler generates executable code for each per-type instantiation of hello_future. And Pin<Box<...>> is runtime dispatch. Only one copy of the executable binary code for hello_future is generated.

Writing an async function that calls another async function

I am trying to create a async function which takes a function pointer as a parameter. It does some stuff, calls the function, awaits on the result, then does some more stuff:
use std::future::Future;
async fn run_another_async_fn<F, Fut>(f: F)
where
Fut: Future<Output = ()>,
F: FnOnce(&mut i32) -> Fut,
{
let mut i = 42;
println!("running function");
f(&mut i).await;
println!("ran function");
}
async fn foo(i: &mut i32) {}
async fn bar() {
run_another_async_fn(foo);
}
[view on Rust Playground]
Unfortunately this fails to compile:
error[E0308]: mismatched types
--> src/lib.rs:17:5
|
17 | run_another_async_fn(foo);
| ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected associated type `<for<'_> fn(&mut i32) -> impl Future {foo} as FnOnce<(&mut i32,)>>::Output`
found associated type `<for<'_> fn(&mut i32) -> impl Future {foo} as FnOnce<(&mut i32,)>>::Output`
= note: the required lifetime does not necessarily outlive the empty lifetime
note: the lifetime requirement is introduced here
--> src/lib.rs:6:28
|
6 | F: FnOnce(&mut i32) -> Fut,
| ^^^
Firstly, it seems the compiler found exactly what it expected but it's complaining anyway?
Secondly, what's "the empty lifetime"? I guess it must mean the '_, does that have some special significance?
Finally, what's the way to get this to compile?
The issue is that there is no way to specify the same lifetime for F and Fut in the where clause.
Luckily (if you don't mind heap allocating the future) there is an easy workaround. You can use the already existing futures::future::BoxFuture; which looks like:
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
With its help you can specify the same lifetime parameter for both the borrow and as a trait bound for the future:
where for<'a> F: FnOnce(&'a mut i32) -> BoxFuture<'a, ()>,
You also have to add an adapter function which will have the correct return type - i.e. BoxFuture<'_, T> instead of impl Future:
fn asd(i: &mut i32) -> BoxFuture<'_, ()> {
foo(i).boxed()
}
or use a closure:
run_another_async_fn(|i| foo(i).boxed());
As a result your code would look like:
use futures::future::BoxFuture;
use futures::FutureExt;
use std::future::Future;
async fn run_another_async_fn<F>(f: F)
where
for<'a> F: FnOnce(&'a mut i32) -> BoxFuture<'a, ()>,
{
let mut i = 42;
println!("running function");
f(&mut i).await;
println!("ran function");
}
fn asd(i: &mut i32) -> BoxFuture<'_, ()> {
foo(i).boxed()
}
async fn foo<'a>(i: &'a mut i32) {
// no-op
}
async fn bar() {
run_another_async_fn(asd);
run_another_async_fn(|i| foo(i).boxed());
}

How can one await a result of a boxed future?

use futures::{future, Future};
fn test() -> Box<dyn Future<Output = bool>> {
Box::new(future::ok::<bool>(true))
}
async fn async_fn() -> bool {
let result: bool = test().await;
return result;
}
fn main(){
async_fn();
println!("Hello!");
}
Playground
Error:
error[E0277]: the trait bound `dyn core::future::future::Future<Output = bool>: std::marker::Unpin` is not satisfied
--> src/main.rs:8:24
|
8 | let result: bool = test().await;
| ^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn core::future::future::Future<Output = bool>`
|
= note: required because of the requirements on the impl of `core::future::future::Future` for `std::boxed::Box<dyn core::future::future::Future<Output = bool>>`
According to the implementation:
impl<F> Future for Box<F>
where
F: Unpin + Future + ?Sized,
Boxed futures only implement the Future trait when the future inside the Box implements Unpin.
Since your function doesn't guarantee that the returned future implements Unpin, your return value will be considered to not implement Future. You'll not able to await it because your type is basically not a Future.
The solution from #Stargateur, adding an explicit type boundary to the signature, works (Playground):
fn test() -> Box<dyn Future<Output = Result<bool, ()>> + Unpin>
If you are using futures-rs, there is a helper type BoxFuture. You can use BoxedFuture without explicitly stating Unpin:
use futures::future::BoxFuture;
fn test() -> BoxFuture<'static, Result<bool, ()>> {
Box::pin(async { Ok(true) })
}
Playground
When it comes to Box and future, it almost always make sense to use Box::pin instead of Box::new:
use std::pin::Pin;
use futures::{future, Future};
fn test() -> Pin<Box<dyn Future<Output = Result<bool, ()>>>> {
Box::pin(future::ok(true))
}
async fn async_fn() -> bool {
test().await.unwrap()
}
The reason is quite interesting. Pin has a blanket implementation for Unpin:
impl<P> Unpin for Pin<P> where
P: Unpin,
And the Box<T> inside it is unconditionally Unpin:
impl<T> Unpin for Box<T> where
T: ?Sized,
So a Pin<Box<dyn Future>> is a unpinned Future. Everything works out, but why Box itself doesn't? This is one place where Deref gets in the way:
impl<T: ?Sized> Deref for Box<T> {
type Target = T;
}
await expects an unpinned Future, and the Box<dyn Future> you created with Box::new does contain a Future. So it is auto-dereferenced and the Unpin is lost unless you explicitly state it that way with Box<dyn Future + Unpin>.
Edit: #ÖmerErden is right about why Box<dyn Future> wouldn't work.

Resources