【问题标题】:Why "expected named lifetime parameter" in a generic function为什么在通用函数中“预期命名的生命周期参数”
【发布时间】:2021-10-24 09:15:42
【问题描述】:

如果我写一个这样的函数:

fn parse_json<'a, T: Deserialize<'a>>(s: &'a str) -> Vec<T> {
    serde_json::from_str(s).unwrap()
}

它按预期工作。 但是,如果我尝试在不明确声明生命周期的情况下做同样的事情,就像这样:

fn parse_json<T: Deserialize>(s: &str) -> Vec<T> {
    serde_json::from_str(s).unwrap()
}

我得到一个编译器错误:

| fn parse_json<T: Deserialize>(s: &str) -> Vec<T> {
|                  ^^^^^^^^^^^ expected named lifetime parameter

为什么?在这种情况下,编译器是否有理由要求 explicit 生命周期声明?

如果我没有使用泛型而是具体类型,我就不需要显式声明任何生命周期:

fn parse_json(s: &str) -> Vec<MyStruct>   // that compiles file

我相信,这是由于所谓的终身省略规则。问题是,为什么具有通用返回类型的版本不被省略规则覆盖?

【问题讨论】:

  • 因为编译还没猜到
  • 因为生命周期省略规则只适用于references,不适用于泛型参数,所以必须写Deserialze&lt;'a&gt;。此时您还必须说引用的生命周期与泛型参数相同,因此您也需要明确声明它们。
  • @Jmb 它似乎也适用于其他类型的生命周期,例如this compiles 即使MyStruct 不是参考。

标签: generics rust


【解决方案1】:

生命周期省略适用于函数参数和返回类型,但目前不适用于特征边界,例如T: Deserialize

为什么?在这种情况下,编译器是否有理由要求显式生命周期声明?

我不确定,但总的来说,生命周期省略规则是相当有限的,大概是为了让它们更容易理解并减少引入令人困惑的编译器“魔法”的机会。


请注意,通用参数中支持生命周期省略,但它已被半弃用(请参阅elided_lifetimes_in_paths lint):

struct Foo<'a>(&'a str);

// Compiles, but causes a warning with `#![warn(rust_2018_idioms)]`
fn bar1(s: &str) -> Foo { Foo(s) }

// Compiles, does not cause warning
fn bar2(s: &str) -> Foo<'_> { Foo(s) }

【讨论】:

    猜你喜欢
    • 2015-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 1970-01-01
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多