【问题标题】:What does a lifetime mean when returning a conservative impl trait?返回保守的 impl 特征时,一生意味着什么?
【发布时间】:2018-10-25 09:16:31
【问题描述】:

在搜索有关 conservative impl trait 的文档时,I found this example:

struct A {
    x: [(u32, u32); 10]
}

impl A {
    fn iter_values<'a>(&'a self) -> impl 'a + Iterator<Item = u32> {
        self.x.iter().map(|a| a.0)
    }
}

返回类型中'a 的生命周期是什么意思?

我知道this question about lifetime bound in Box,但我认为用例不同。如果我很好理解答案:

trait 对象只在生命周期内有效 'a

这意味着存在于堆中某处的 trait 对象将持续一生'a。

但是在这里,这不是一个特征对象,而是一个存在于堆栈中的具体对象。所以编译器不需要提示它的生命周期。

我错过了什么?

【问题讨论】:

  • 这意味着几乎与您在任何范围内看到一生时的含义相同。例如T: 'a + Debug.
  • @PeterHall 如果我理解这个表示法,当我们在某处使用对T 的引用时需要它。但在这里,我返回一个具体的struct,它实现了Iterator。
  • 借用检查器使用人类读者也无法访问的任何信息来推理代码是不公平的。虽然具体类型在函数内部是已知的,但在外部是未知的。

标签: generics rust lifetime


【解决方案1】:

语法impl Iterator&lt;Item = u32&gt; + 'a表示

  • 将返回函数定义的某些类型,但您不知道确切的类型。这就是impl ... 部分。
  • 未指定的具体类型将是u32 值的迭代器。这就是Iterator&lt;Item = u32&gt; 部分。
  • 未指定的具体类型可能包含引用,其生命周期为'a。这就是+ 'a 部分。

在您的示例中,返回的迭代器包含对self 的引用,因此不能允许它的寿命比A 的实例长,否则它将无效。具体类型(如果我们能写的话)是iter::Map&lt;slice::Iter&lt;'a, (u32, u32)&gt;, &lt;closure&gt;&gt;——注意它里面有一个'a。

这意味着存在于堆中某处的 trait 对象将持续一生'a。

这并不完全正确。这两种情况具有相同的含义:未指定的具体类型可能包含引用。对于 trait 对象,具体类型位于某种指针后面(Box、&amp;、Rc 等)。使用 impl trait,具体类型直接放在堆栈上。

这不是一个特征对象,而是一个存在于堆栈中的具体对象

特征对象不需要堆;他们只能利用堆栈:

let x: &std::fmt::Display = &42;
println!("{}", x);

另见:

【讨论】:

  • "可能包含生命周期为 'a" 的引用——有趣的是你用这种方式表达了它。完全等价,但我对其含义的直觉是相反的:“不能活得超过生命'a”。
【解决方案2】:

这意味着存在于堆中某处的 trait 对象将持续一生'a。

不完全是。

'a 这里并没有具体说明,它只是在对象的生命周期上设置了一个上限。对象位于堆上还是栈上都没有关系:编译器必须保证这个对象的生命周期不超过'a。

生命周期代表了被引用者和被引用者之间的关系,用于确保被引用者永远不会超过被引用者。因此,它为引用对象的生命周期设置了一个上限,并为被引用对象的生命周期设置了一个下限。


编译器可以从函数返回的实际具体类型派生必要的生命周期,但是它要求类型检查器能够查看函数实现以执行其工作.

因此,在接口边界记录生命周期约束对人类和编译器都更友好:它允许本地推理。

【讨论】:

    猜你喜欢
    • 2021-04-30
    • 2021-12-11
    • 1970-01-01
    • 2023-03-10
    • 2019-04-23
    • 2021-08-02
    • 2019-02-16
    • 2013-07-03
    • 2014-04-03
    相关资源
    最近更新 更多