从“async fn"返回的未来的具体类型是什么? [英] What is the concrete type of a future returned from `async fn`?
问题描述
我应该为存储期货的向量使用什么类型?
What type should I use for a vector that stores futures?
我尝试在同一个 URL 上发出多个并发请求,并将所有期货保存到向量中以与 join_all
一起使用.
I tried to make multiple concurrent requests on the same URL and save all the futures into the vector to use with join_all
.
如果我没有为向量明确设置类型,一切正常.我知道 Rust 可以找到变量的正确类型.CLion 将向量类型确定为 Vec
,但是当我尝试自己设置类型时,它给了我一个错误:
If I don't set a type for the vector explicitly, everything works. I understand that Rust can find the proper type of a variable. CLion determines the vector type as Vec<dyn Future<Output = ()>>
, but when I try to set the type by myself, it gives me an error:
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
这迫使我将函数的结果包装到 requests 中.push(Pin::from(Box::new(request(i))));
I must declare the type as Vec<Pin<Box<dyn Future<Output=()>>>>
which forces me to wrap result of function into 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:
异步函数的返回类型是编译器生成的唯一匿名类型,类似于闭包的类型.您可以将这种类型视为一个枚举,函数的每个屈服点"都有一个变体——它的开头、await 表达式和每个返回.每个变体都存储了从该屈服点恢复控制所需存储的状态.
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
但这并不意味着我们不需要更深入地了解这种匿名类型及其实现,它掌握这个概念会很好.
You can't explicitly declare the concrete type of a future since it is an anonymous type. As an API user we only need to know that it implements std::futures::Future
but this doesn't mean that we don't need a deeper knowledge of this anonymous type and it's implementation, it would be nice to have for grasping the concept.
CLion 将向量类型确定为 Vec
CLion determines the vector type as
Vec<dyn Future<Output = ()>>
这是一个类型提示,不是实际类型,因为编译器无法知道dyn Future
的大小,所以不会被编译.
This is a type hint, not the actual type, since compiler is not able to know the size of dyn Future<Output = ()>
, it will not be compiled.
Pin<Box<_>>
- 使用 Future
来声明显式类型可能不是一个好主意.在您的情况下,不需要它,因为从 async fn
返回的具体类型是相同的.让编译器推断类型就好了.
Pin<Box<_>>
-ing a Future
to declare an explicit type might not be a good idea. In your case it's not needed because the concrete types returned from async fn
are identical. Letting the compiler infer the type will just be fine.
另见:
- 对于各种具体的返回类型:我该如何放置将异步函数转换为 Rust 中的地图?
- 静态&动态调度:特征对象
这篇关于从“async fn"返回的未来的具体类型是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!