几年来,我一直把Rust 作为一种爱好.就在我以为我开始理解生命的时候,我发现了这个.我试图"泛化"一个函数来处理不同类型的数据.以下是我的问题的MRE.


pub struct BorrowedData<'data> {
    inner: Vec<&'data u16>
}

struct ConcreteData {
    data: Vec<u16>
}

impl TryFrom<BorrowedData<'_>> for ConcreteData {
    type Error = ();

    fn try_from(value: BorrowedData<'_>) -> Result<Self, Self::Error> {
        Ok(Self {
            data: value.inner.into_iter().map(|n| *n).collect()
        })
    }
}


pub fn test_generic<'data,Entity: TryFrom<BorrowedData<'data>,Error=()>>() -> Result<(),()> {

    let data = [4,8,15,16,23,42];

    let borrowed = BorrowedData {
        inner: data.iter().collect()
    };

    let _data = Entity::try_from(borrowed)?;

    // ...Process and save data to file in appropriate structure

    Ok(())

} // data dropped here while still borrowed?

pub fn test_concrete() -> Result<(),()> {

    let data = [4,8,15,16,23,42];

    let borrowed = BorrowedData {
        inner: data.iter().collect()
    };

    let _data = ConcreteData::try_from(borrowed)?;

    // ...Process and save data to file in appropriate structure

    Ok(())

}

这将返回编译错误:

error[E0597]: `data` does not live long enough
  --> src/mre.rs:26:16
   |
21 | pub fn test_generic<'data,Entity: TryFrom<BorrowedData<'data>,Error=()>>() -> Result<(),()> {
   |                     ----- lifetime `'data` defined here
...
26 |         inner: data.iter().collect()
   |                ^^^^^^^^^^^ borrowed value does not live long enough
...
29 |     let _data = Entity::try_from(borrowed)?;
   |                 -------------------------- argument requires that `data` is borrowed for `'data`
...
35 | } // data dropped here while still borrowed?
   | - `data` dropped here while still borrowed

它在具体函数中工作得很好,但泛型函数会带来问题.

有谁能解释一下这个吗?

有没有办法修复test_generic的功能?*或者这是不可能的?

*不接触data变量或BorrowedData struct .后者是对从外部c库调用返回的对象的模拟,前者是因为它是我重现错误的唯一方法.这是我在我的真实代码中得到的错误.

推荐答案

此签名:

pub fn test_generic<'data, Entity: TryFrom<BorrowedData<'data>, Error = ()>>() -> Result<(), ()>

使用调用方提供的'data的生存期,该生存期将始终大于函数体.因为你调用Entity::try_from(borrowed),编译器推断borrowed'data是有效的,这是不可能的,因为它borrow 了data,其中cannot比函数体存活时间更长,所以你得到了编译错误.

您需要一个更高级别的特征界限(HRTB),它允许您说"Entity必须在any个有效生命周期'a内实现TryFrom<BorrowedData<'a> ...>",然后它可以比函数体更短.

pub fn test_generic<Entity: for<'a> TryFrom<BorrowedData<'a>, Error = ()>>() -> Result<(), ()>

此更改允许您的代码进行编译.

Rust相关问答推荐

关联类型(类型参数)命名约定

如何对字符串引用的引用向量进行排序,而不是对最外层的引用进行排序?

关于Rust 中回归的逻辑

在没有引用计数或互斥锁的情况下,可以从Rust回调函数内的封闭作用域访问变量吗?

rust 蚀生命周期 行为

限制未使用的泛型导致编译错误

制作一片连续整数的惯用Rust 方法?

如何导入crate-type=[";cdylib;]库?

有没有一种惯用的方法来判断VEC中是否存在变体?

用于判断整数块是否连续的SIMD算法.

如何在嵌套的泛型 struct 中调用泛型方法?

如何在Rust中基于字符串 Select struct ?

是否提供Bundle 在可执行文件中的warp中的静态文件?

当我try 使用 SKI 演算中的S I I实现递归时,为什么 Rust 会失败?

在发布中包含 Rust DLL

push 方法是否取得所有权?

SDL2 没有在终端键上触发?

当用作函数参数时,不强制执行与绑定的关联类型

需要括号的宏调用中的不必要的括号警告 - 这是编写宏的糟糕方法吗?

当值是新类型包装器时,对键的奇怪 HashMap 生命周期要求