`async fn` 返回的 future 的具体类型是什么?

What is the concrete type of a future returned from `async fn`?

我应该为存储期货的向量使用什么类型?

我尝试在同一个 URL 上发出多个并发请求,并将所有 futures 保存到向量中以与 join_all 一起使用。

如果我没有明确地为向量设置类型,一切正常。我知道 Rust 可以找到变量的正确类型。 CLion 将矢量类型确定为 Vec<dyn Future<Output = ()>>,但是当我尝试自己设置类型时,它给我一个错误:

error[E0277]: the size for values of type `dyn core::future::future::Future<Output = ()>` cannot be known at compilation time
  --> src/lib.rs:15:23
   |
15 |     let mut requests: Vec<dyn Future<Output = ()>> = Vec::new();
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `dyn core::future::future::Future<Output = ()>`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: required by `std::vec::Vec`

我必须将类型声明为 Vec<Pin<Box<dyn Future<Output=()>>>>,这迫使我将函数结果包装到 requests.push(Pin::from(Box::new(request(i))));

use futures::future::join_all;
use std::future::Future;
use std::pin::Pin;

async fn request(n: i32) {
    println!("Started: {}", n);
    let response = reqwest::get("https://www.rust-lang.org")
        .unwrap()
        .text()
        .unwrap();
    println!("Completed: {}. Response: {}", n, &response[0..10]);
}

async fn main() {
    let mut requests: Vec<dyn Future<Output = ()>> = Vec::new();
    for i in 0..5 {
        requests.push(request(i));
    }
    join_all(requests).await;
}

应该是哪种类型?

来自RFC

The return type of an async function is a unique anonymous type generated by the compiler, similar to the type of a closure. You can think of this type as being like an enum, with one variant for every "yield point" of the function - the beginning of it, the await expressions, and every return. Each variant stores the state that is needed to be stored to resume control from that yield point.

When the function is called, this anonymous type is returned in its initial state, which contains all of the arguments to this function.

您不能显式声明未来的具体类型,因为它是匿名类型。作为 API 用户,我们只需要知道它实现了 std::futures::Future 但这并不意味着我们不需要更深入地了解这种匿名类型及其实现,如果有掌握概念。


CLion determines the vector type as Vec<dyn Future<Output = ()>>

这是一个类型提示,不是实际类型,因为编译器无法知道 dyn Future<Output = ()> 的大小,因此不会被编译。


Pin<Box<_>>-ing a Future 来声明显式类型可能不是一个好主意。在您的情况下,不需要它,因为从 async fn 编辑的具体类型 return 是相同的。让编译器推断类型就好了。

另请参阅:

  • 对于各种具体 return 类型:
  • 静态和动态调度:Trait Objects