generics - 异步迭代 BTreeSet 时出现奇怪的生命周期错误
问题描述
我希望实现以下代码中的异步块Send
(Playground):
use std::collections::BTreeSet;
use std::future::ready;
pub fn test<T: Sync>(set: &BTreeSet<T>) -> impl Send + '_ {
async move {
for _ in set {
ready(()).await;
}
}
}
但它给出了以下错误:
Compiling playground v0.0.1 (/playground)
error[E0311]: the parameter type `T` may not live long enough
--> src/lib.rs:4:44
|
4 | pub fn test<T: Sync>(set: &BTreeSet<T>) -> impl Send + '_ {
| -- ^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
| help: consider adding an explicit lifetime bound...: `T: 'a +`
error: aborting due to previous error
error: could not compile `playground`
To learn more, run the command again with --verbose.
我根本不明白这个错误。添加生命周期边界并不能解决问题(Playground),除非添加的生命周期边界是'static
(Playground)。
我尝试用BTreeSet
, Vec
, VecDeque
, LinkedList
,HashSet
替换BinaryHeap
。全部编译无误。有什么特别之处BTreeSet
?
解决方案
该错误似乎是 Rust 中的一个错误——async
函数是相当新的,而且似乎存在许多奇怪或不正确的编译器错误问题,尤其是泛型。我认为这可能是问题#71058或问题 #64552。
我发现经常出现这样的终身错误,只是意味着编译器在说“救命!我很困惑。”
这是一个无偿更改的示例,我认为在功能上是相同的:
use std::collections::BTreeSet;
use std::future::ready;
type ItemType = dyn Sync;
pub fn test<ItemType>(set: &BTreeSet<ItemType>) -> impl Send + '_ {
async move {
for _ in set {
ready(()).await;
}
}
}
这会产生一个错误,我认为它更接近于使编译器绊倒的错误(但仍然不正确)Playground:
error: future cannot be sent between threads safely
--> src/lib.rs:6:52
|
6 | pub fn test<ItemType>(set: &BTreeSet<ItemType>) -> impl Send + '_ {
| ^^^^^^^^^^^^^^ future created by async block is not `Send`
|
note: captured value is not `Send`
--> src/lib.rs:8:18
|
8 | for _ in set {
| ^^^ has type `&BTreeSet<ItemType>` which is not `Send`
help: consider restricting type parameter `ItemType`
|
6 | pub fn test<ItemType: std::marker::Sync>(set: &BTreeSet<ItemType>) -> impl Send + '_ {
| ^^^^^^^^^^^^^^^^^^^
上面的 Rust 错误表明,Send
如果 async 闭包捕获了不支持的数据结构,那么未来将不是这种情况Send
。在这种情况下,它会捕获支持Send的BTreeSet 。为什么会发生这种情况BTreeSet
而不会发生这种情况,Vec
或者您提到的其他数据结构之一可能是其实现语法的一些微小差异导致编译器出错。
您创建了一个不错的最小示例,因此不确定您要完成什么。这是一个可能有帮助的解决方法:
use std::collections::BTreeSet;
use std::future::ready;
use std::vec::Vec;
use futures::future::join_all;
pub async fn test<T: Sync>(set: &BTreeSet<T>) -> impl Send + '_ {
let mut future_list = Vec::new();
for _ in set {
let new_future = async move {
ready(()).await;
};
future_list.push(new_future);
};
join_all(future_list).await
}
推荐阅读
- python - 如何在python中拆分数组中的每个值?
- vba - 如何将 Outlook 邮件转换为保持双字节字符集的文本?
- angular - 如何解析上传文件的 MIDI 内容?
- reactjs - 父状态更改时子组件不更新
- php - 使用带有 FileType 的转换器
- excel - VBA 代码无法很好地跨多个工作簿进行复制和粘贴
- c++ - C++ 和 SDL2 网格移动太快
- android - 使用 ConstraintLayout 在横向模式下居中对齐 ImageButton
- python - 如何获取嵌套列表python中每列的最大值?
- c++ - 为什么在公共数据成员之前使用“静态”关键字?