我正在处理一个将异步函数作为字段的结构,但是当它接受可变引用时就不起作用了。
这是可行的:
# ![allow(dead_code)]
pub struct TestStruct;
struct TestStruct2<F>
where
F: std::future::Future<Output = ()>,
{
foo: fn(TestStruct) -> F,
}
async fn foo(_x: TestStruct) {}
# [tokio::main]
async fn main() {
let _s = TestStruct2 { foo };
}
这是行不通的:
# ![allow(dead_code)]
pub struct TestStruct;
struct TestStruct2<F>
where
F: std::future::Future<Output = ()>,
{
foo: fn(&mut TestStruct) -> F,
}
async fn foo(_x: &mut TestStruct) {}
# [tokio::main]
async fn main() {
let _s = TestStruct2 { foo }; //error here
}
错误:
mismatched types
expected fn pointer `for<'r> fn(&'r mut TestStruct) -> _`
found fn item `for<'r> fn(&'r mut TestStruct) -> impl std::future::Future<Output = ()> {foo}`
有人能向我解释为什么会发生这种情况,我能做些什么吗?
2条答案
按热度按时间inb24sb21#
问题不在于
mut
,而在于引用和它的生存期。根据the Asynchronous Programming in Rust book,async
函数的返回值的生存期受其参数的生存期限制。您的TestStruct2::foo
定义不接受这一点。要解决这一问题,您可以显式地将此生存期添加到F
中:of1yzvn42#
看起来
foo
的返回类型有一个隐式的+ 'a
绑定,其中'a
是&mut TestStruct
中的匿名生存期。只需将
foo
反语法化为显式impl Trait
类型和async
块即可解决此问题。然而,当我们试图使用
async
块中的引用时,错误再次弹出(看起来编译器将所有参数从async fn
块移到了隐藏的async
块中)。第一个
如果我们应用编译器的建议,那么我们又回到了起点:
第一个
我们可以通过在
TestStruct2
中添加一个lifetime参数并在适当的地方使用它来修复这个问题(我们也可以将foo
恢复到它的原始形式)。