我在Rust代码中遇到了与生存期相关的编译错误.以下是导致错误的代码:

fn to_pointer_vec(ptrs: &[*const dyn ToString]) -> Vec<*const dyn ToString> {
    let mut vec: Vec<*const dyn ToString> = Vec::new();
    for &ptr in ptrs {
        vec.push(ptr);
    }
    vec
}

错误消息如下:

 --> src/table/merger.rs:78:9
   |
73 |     fn to_pointer_vec(ptrs: &[*const dyn ToString]) -> Vec<*const dyn ToString> {
   |                             - let's call the lifetime of this reference `'1`
...
78 |         vec
   |         ^^^ returning this value requires that `'1` must outlive `'static`
   |
help: to declare that the trait object captures data from argument `ptrs`, you can add an explicit `'_` lifetime bound
   |
73 |     fn to_pointer_vec(ptrs: &[*const dyn ToString]) -> Vec<*const dyn ToString + '_> {
   |                                                                                ++++

我不明白为什么特征对象指针有生存期限制.

推荐答案

原始指针没有生存期,但特征对象有生存期.

特征对象是指满足某个特征界限的任何类型(在您的示例T: ToString中),并且该类型可能具有生命周期参数.编译器需要假定特征对象的最短生存期,RFC 599详细说明了如果没有显式提供则如何推断该生存期的规则.在您的函数原型中拼写出省略的生存期将导致以下结果:

fn to_pointer_vec<'a>(ptrs: &'a [*const dyn ToString + 'a]) -> Vec<*const dyn ToString + 'static>

换句话说,传入的特征对象的生存期被推断为'a,而返回的特征对象的生存期被推断为'static.这解释了错误消息,这在本例中无疑是令人困惑的.这两种类型看起来确实一模一样,但事实并非如此.

有几种方法可以解决这个问题.首先,您可以按照编译器的建议执行操作,并告诉编译器通过在返回值中添加'_生存期来根据输入推断生存期:

fn to_pointer_vec(ptrs: &[*const dyn ToString]) -> Vec<*const (dyn ToString + '_)>

您还可以使用泛型类型参数T:

fn to_pointer_vec<T: Clone>(ptrs: &[T]) -> Vec<T>

这保证了参数中的T与返回的T相同.这适用于您的示例代码,但可能不适用于您的实际代码,因为您丢失了T是指向某个特征对象的原始指针的信息.

最后,对于您的示例代码,您根本不需要该函数.这相当于ptrs.to_vec()美元.

Rust相关问答推荐

这种获取-释放关系是如何运作的?

自定义结果枚举如何支持`?`/`FromResidual`?

字段类型为Boxed的 struct 的生存期必须超过static

我应该将哪些文件放入我的GitHub存储库

为什么这个变量不需要是可变的?

Rust编译器似乎被结果类型与anyhow混淆

当推送到 HashMap 中的 Vector 时,类型 `()` 无法取消引用

Rust 如何返回大类型(优化前)?

当没有实际结果时,如何在 Rust 中强制执行错误处理?

更新 rust ndarray 中矩阵的一行

Button.set_hexpand(false) 不会阻止按钮展开

为什么Rust编译器会忽略模板参数应具有静态生命周期?

如何从 rust 中的同一父目录导入文件

无法理解 Rust 对临时值的不可变和可变引用是如何被删除的

以 `static` 为前缀的闭包是什么意思?我什么时候使用它?

更好的方法来模式匹配带有 Rust 的窥视孔装配说明窗口?

具有生命周期和以后引用的可变方法

如何在 nom 中构建负前瞻解析器?

为什么 match 语句对引用类型比函数参数更挑剔?

为什么这里需要类型注解?