0
votes

I've been trying to understand and play with futures (version 0.3) but couldn't make this work. As I understand, a function is able to return a future of type A only if the type A implements the future trait. If I create a struct and implement the future trait, it's okay but why String doesn't work?

use futures::prelude::*;

async fn future_test() -> impl Future<Output=String> {
    return "test".to_string();
}

I get the error:

the trait bound `std::string::String: core::future::future::Future` is not satisfied

the trait `core::future::future::Future` is not implemented for `std::string::String`

note: the return type of a function must have a statically known sizerustc(E0277)

So I told myself, okay then I can use Box like:

async fn future_test() -> impl Future<Output=Box<String>> {
    return Box::new("test".to_string());
}

But the error is same:

the trait bound `std::string::String: core::future::future::Future` is not satisfied

the trait `core::future::future::Future` is not implemented for `std::string::String`

note: the return type of a function must have a statically known sizerustc(E0277)

What am I doing wrong? And why does the future hold the String instead of the Box itself?

1
async fn automatically wraps the return type in a future for you, so you should change the signature to just async fn future_test() -> String.apetranzilla
@apetranzilla Okay but what if I don't use async?Skai
I'm not sure what you mean. Async functions are automatically compiled to futures regardless of whether they actually use await or not, so async fn hello() -> String { "hello".to_string() } would compile to a function returning impl Future<Output=String> that will immediately complete when polled.apetranzilla
@apetranzilla I mean why writing it manually won't compile?Skai
if you want to write it manually, you need to remove the async qualifier. The function would then be fn hell() -> impl Future<Output=String> { /* ... */ }. The actual type implementing Future would be something you'd have to write by hand or import from another crate (like futures); the compiler has special support to generate futures from async fns that can't be fully replicated manually.apetranzilla

1 Answers

2
votes

When a function is declared async, it implicitly returns a future, with the return type of the function as its Output type. So you would write this function:

async fn future_test() -> String {
    "test".to_string()
}

Alternatively, if you wanted to explicitly specify return type as a Future, you would drop the async keyword. If you did that you would also need to construct a future to return, and you would not be able to use await inside the function.

fn future_test2() -> impl Future<Output=String> {
    ready("test2".to_string())
}

Note that futures::ready constructs a Future that is immediately ready, which is appropriate in this case since there is no actual asynchronous activity going on in this function.

Link to Playground