rust 为什么我不能使用PineMap来存储引用cons-list?即使在main [duplicate]结束后,仍会出现“still borrowed”错误

eaf3rand  于 2023-01-13  发布在  其他
关注(0)|答案(1)|浏览(75)
    • 此问题在此处已有答案**:

Why can't I store a value and a reference to that value in the same struct?(4个答案)
5天前关闭。
为什么这个代码:

#[derive(Eq, PartialEq, Ord, PartialOrd)]
enum List<'a> {
    Cons(isize, &'a List<'a>),
    Nil,
}

fn main() {
    use List::*;
    use pinus::{prelude::*, sync::PineMap};
    let table = PineMap::new();
    table.insert(Nil, Nil);
    let nil = table.get(&Nil).unwrap();
    table.insert(Cons(1, nil), Cons(1, nil));
}

导致此错误:

error[E0597]: `table` does not live long enough
  --> src/main.rs:12:15
   |
12 |     let nil = table.get(&Nil).unwrap();
   |               ^^^^^^^^^^^^^^^ borrowed value does not live long enough
13 |     table.insert(Cons(1, nil), Cons(1, nil));
14 | }
   | -
   | |
   | `table` dropped here while still borrowed
   | borrow might be used here, when `table` is dropped and runs the `Drop` code for type `PineMap`

我使用一个pinus::sync::PineMap来确保所有对List等价示例的引用实际上是对内存中同一对象的引用,我认为一种方法是使用一个表将List键Map到一个表拥有的List示例,我正在为它试用PineMap,因为它的insert不会移动内存中的项(它的insert借用了&self,而不是&mut self),所以对它的List值的引用将保持有效,并且我可以构建自引用项。
为什么在我的代码中,table在其作用域的末尾仍然被认为是被借用的?

bvjveswy

bvjveswy1#

当你把nil从表中取出,然后用Cons(1, nil)把它放回表中时,nil的类型是一个与table的生存期绑定的引用,因此你存储的List的生存期'a与存储它们的table绑定。
这里的核心问题是,这创建了一个自引用结构体,它引入了无数的问题,你也不能调用任何可变的方法,因为table永久地借用了自己。
编译器所抱怨的具体问题是,由于元素持有对表的引用,当它被删除时,删除逻辑可能会试图访问正在被销毁的数据,这是不合理的。
我鼓励你阅读Rustonomicon中关于Drop Check的更多信息,这里有一个指导原则:
对于一个泛型类型来说,要正确地实现drop,它的泛型参数必须严格地比它的寿命长。
我没有任何变通办法或解决方案,你除了你不能这样做。

相关问题