rust PineMap即使在主服务器结束后仍“借用”

oiopk7p5  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(104)

为什么这段代码:

#[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::PineMapGitHub)来确保对List的等价示例的所有引用实际上是对内存中同一对象的引用。我正在为它尝试PineMap,因为它的insert不会在内存中移动它的项(它的insert也借用了&self,而不是&mut self),所以对它的List值的引用将保持有效,我可以构建自引用项。
为什么table在我的代码中仍然被认为是在其作用域的末尾被借用的?

fdbelqdn

fdbelqdn1#

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

相关问题