从“async fn"返回的未来的具体类型是什么? [英] What is the concrete type of a future returned from `async fn`?

查看:25
本文介绍了从“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.

另见:

这篇关于从“async fn"返回的未来的具体类型是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆