编译器认为借用还活着

Compiler thinks a borrow is alive when it isn't

我有这个竞技场的代码,其中分配给你一个索引,你稍后使用相同的索引来获取对象。

struct Node<'a>(i32, Option<&'a Node<'a>>);

struct Arena<'a>(Vec<Node<'a>>);

impl<'a> Arena<'a> {
    fn alloc(&'a mut self, node: Node<'a>) -> usize {
        let index = self.0.len();
        self.0.push(node);
        index
    }
    fn get(&'a mut self, index: usize) -> &'a mut Node<'a> {
        &mut self.0[index]
    }
}

fn main() {
    let mut arena = Arena(vec![]);
    let x = arena.alloc(Node(1, None));
    println!("{}", arena.get(x).0)
}

self 正在使用生命周期 'a 因为 rust 会给出另一个错误:

cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements

alloc 的 return 值只是一个 usize 所以 self 的借用应该是临时的。 然而,出于某种原因,当我在 println 中调用 arena.get 时,rust 认为 arena 仍然是可变借用的,并给我这个错误:

error[E0499]: cannot borrow `arena` as mutable more than once at a time
  --> src/main.rs:19:20
   |
18 |     let x = arena.alloc(Node(1, None));
   |             ----- first mutable borrow occurs here
19 |     println!("{}", arena.get(x).0)
   |                    ^^^^^
   |                    |
   |                    second mutable borrow occurs here
   |                    first borrow later used here

为什么会这样?

注意:我知道我可以在 Option 中使用索引而忘记这个问题,但我仍然想知道为什么 rust 认为 arena 是可变借用的。

因为这就是您告诉编译器的内容。两步:

在行

fn alloc(&'a mut self, node: Node<'a>) -> usize

Node 还有一些生命周期 'a;此外,您还通过 &'a mut self 告诉编译器可变引用 &mut self 将具有相同的生命周期 'a。也就是说,&mut self 引用将与 Node.

的生命周期参数一样长

其次,在行 arena.alloc(Node(1, None)) 中,您正在创建的 Node 的文字实例没有比 'static 短的生命周期,因此它是 Node<'static>。这意味着 arenaArena<'static>.

错误的地方在于这两个组合:由于您声明 &mut selfNode 具有相同的生命周期,因此编译器必须推断出 &mut self 是一个&'static mut self,因为'a'static。因此,一旦第一次借用发生在 main永远不会 允许再借用,你正式陷入困境。

AFAICS 无论如何都不需要那些生命周期注释。如果您将签名更改为简单

fn alloc(&mut self, node: Node<'a>) -> usize {
fn get(&mut self, index: usize) -> &mut Node<'a> {

你的例子可以编译,因为编译器可以自由分配比 Node 借给 Arena.

的任何生命周期都短的生命周期