如何在 Rust 中声明除生命周期外的相同类型的泛型参数?

Yoh*_*hei 5 lifetime rust

我写了下面的代码,但我不能写生命时间约束来工作并得到一个错误:

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"
}
Run Code Online (Sandbox Code Playgroud)

错误:

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

Run Code Online (Sandbox Code Playgroud)

操场

我认为如果函数中的两个参数f可以有自己的生命周期就可以解决。例如,

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

Run Code Online (Sandbox Code Playgroud)

如何解决这个问题?

E_n*_*ate 7

可以使用另一个最小示例来重现相同的问题,使用函数接口而不是异步函数。

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);
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)

这个例子允许我们变成get一个函数参数,并观察到传递这个函数对生命周期施加了严格的约束。尽管程序有最好的意图,但返回供应商函数(或承诺)的函数并不提供关于输出生命周期的协方差。也就是说,不满足。有时,编译器会建议您坚持最薄弱的环节,即生命周期,即使这可能并不理想。'a'static() -> &'static strfor<'a> () -> &'a str'static

请注意,表示在其生命周期内通用的类型的方法目前非常有限。这些是较高种类类型的一种形式,只能通过较高等级的特征边界指定某种程度的表达能力(一旦完全实现并稳定,最终将成为通用关联类型)。在这种情况下,与其尝试f为某种类型(伪代码)工作,不如在整个生命周期T<'a>中使我们的泛型更好。然后可以在实现时进行子类型化,因为我们知道字符串文字可以满足任何生命周期。get'a

fn get<'a>() -> impl FnOnce() -> &'a str {
    || "foo"
}
Run Code Online (Sandbox Code Playgroud)

在这种async情况下(游乐场):

async fn get<'a>() -> &'a str {
    "foo"
}
Run Code Online (Sandbox Code Playgroud)

也可以看看:


归档时间:

查看次数:

186 次

最近记录:

4 年,10 月 前