我写了下面的代码,但是我不能写生命周期约束来工作并得到错误:
use futures::Future;
async fn foo<'a>(a: &'a str) -> &'a str {
let task = get();
f(a, task).await
}
async fn f<T>(v: T, task: impl Future<Output = T>) -> T {
if true {
v
} else {
task.await
}
}
async fn get() -> &'static str {
"foo"
}
错误:
error[E0759]: `a` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
--> src/lib.rs:3:18
|
3 | async fn foo<'a>(a: &'a str) -> &'a str {
| ^ ------- this data with lifetime `'a`...
| |
| ...is captured here...
4 | let task = get();
5 | f(a, task).await
| - ...and is required to live as long as `'static` here
我认为如果函数中的两个参数f
可以具有各自的生存期,就可以解决。例如,
v: T,
task: S,
T: 'a,
S: 'b,
'b: 'a,
S == T
如何解决这个问题?
可以使用功能接口而不是异步功能,通过另一个最小示例来重现相同的问题。
fn get() -> impl FnOnce() -> &'static str {
|| "foo"
}
fn foo<'a, T: 'a, F>(_: &'a str, _: F)
where
F: Fn() -> T,
T: FnOnce() -> &'a str,
{
}
let x = "".to_string();
foo(&*x, &get);
error[E0597]: `x` does not live long enough
--> src/main.rs:22:11
|
22 | foo(&*x, &get);
| ------^-------
| | |
| | borrowed value does not live long enough
| argument requires that `x` is borrowed for `'static`
23 | }
| - `x` dropped here while still borrowed
这个例子可以让我们把get
到函数参数,观察,通过此功能施加了硬约束的一生'a
是'static
。尽管有程序的最佳意图,但返回供应商功能(或承诺)的功能在输出寿命方面不提供协方差。也就是说,() -> &'static str
不满足for<'a> () -> &'a str
。有时,编译器会退而建议您坚持使用'static
生命周期中最薄弱的链接,即使这可能不是理想的。
请注意,目前,表示类型在其生命周期中是通用的类型的方法非常有限。这些是较高种类类型的一种形式,只能通过较高等级的特质范围(以及最终的泛型关联类型,一旦它们得到完全实现和稳定),才能在某种程度上指定表达能力。在这种情况下,与其尝试f
为某种类型的工作T<'a>
(伪代码),不如使我们的get
泛型成为整个生命周期更好'a
。然后,子类型化可能会在实现中发生,因为我们知道字符串文字可以满足任何生存期。
fn get<'a>() -> impl FnOnce() -> &'a str {
|| "foo"
}
在async
(Playground)的情况下:
async fn get<'a>() -> &'a str {
"foo"
}
也可以看看:
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句