`FnOnce` 的实现对于异步递归不够通用
Implementation of `FnOnce` is not general enough with async recursion
我正在尝试用 Rust 编写几个递归异步函数。我创建了一个我面临的问题的最小示例:
use std::collections::HashMap;
use anyhow::Result;
use async_recursion::async_recursion;
use futures::StreamExt;
#[async_recursion]
async fn foo() -> Result<()> {
let map: HashMap<String, String> = HashMap::new();
futures::stream::iter(map.keys().map(|it: &String| tokio::spawn(bar(it.clone()))))
.buffer_unordered(2)
.collect::<Vec<_>>()
.await;
Ok(())
}
#[async_recursion]
async fn bar(it: String) -> Result<()> {
foo().await;
Ok(())
}
当使用映射到同一个 tokio::spawn
调用的字符串引用数组时,它工作正常:
futures::stream::iter(
[&String::from("hi")].map(|it: &String| tokio::spawn(bar(it.clone()))),
)
当使用 HashMap 的键时,它在 #[async_recursion]
宏中给出以下编译器错误:
implementation of `FnOnce` is not general enough
closure with signature `fn(&'0 std::string::String) -> tokio::task::JoinHandle<Result<(), anyhow::Error>>` must implement `FnOnce<(&std::string::String,)>`, for any lifetime `'0`...
...but it actually implements `FnOnce<(&std::string::String,)>`
我不太了解生命周期,我猜这与 HashMap 的键寿命不够长或其他原因有关。我该如何解决这个错误?
如果你切换到
futures::stream::iter(
map.into_keys()
.map(|it: String| tokio::spawn(bar(it.to_owned()))),
)
您的代码将有效。
你的原始代码不起作用的原因是 rust 不知道
.buffer_unordered(2)
.collect::<Vec<_>>()
.await;
强制生成的期货在您的 HashMap
超出范围之前完成。
我正在尝试用 Rust 编写几个递归异步函数。我创建了一个我面临的问题的最小示例:
use std::collections::HashMap;
use anyhow::Result;
use async_recursion::async_recursion;
use futures::StreamExt;
#[async_recursion]
async fn foo() -> Result<()> {
let map: HashMap<String, String> = HashMap::new();
futures::stream::iter(map.keys().map(|it: &String| tokio::spawn(bar(it.clone()))))
.buffer_unordered(2)
.collect::<Vec<_>>()
.await;
Ok(())
}
#[async_recursion]
async fn bar(it: String) -> Result<()> {
foo().await;
Ok(())
}
当使用映射到同一个 tokio::spawn
调用的字符串引用数组时,它工作正常:
futures::stream::iter(
[&String::from("hi")].map(|it: &String| tokio::spawn(bar(it.clone()))),
)
当使用 HashMap 的键时,它在 #[async_recursion]
宏中给出以下编译器错误:
implementation of `FnOnce` is not general enough
closure with signature `fn(&'0 std::string::String) -> tokio::task::JoinHandle<Result<(), anyhow::Error>>` must implement `FnOnce<(&std::string::String,)>`, for any lifetime `'0`...
...but it actually implements `FnOnce<(&std::string::String,)>`
我不太了解生命周期,我猜这与 HashMap 的键寿命不够长或其他原因有关。我该如何解决这个错误?
如果你切换到
futures::stream::iter(
map.into_keys()
.map(|it: String| tokio::spawn(bar(it.to_owned()))),
)
您的代码将有效。
你的原始代码不起作用的原因是 rust 不知道
.buffer_unordered(2)
.collect::<Vec<_>>()
.await;
强制生成的期货在您的 HashMap
超出范围之前完成。