编译器认为借用是活的,而实际上并非如此



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

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,因为锈蚀会导致另一个错误:

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

alloc的返回值只是一个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-think-arena是可变借用的。

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

在线

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

对于CCD_ 7存在一些寿命CCD_;此外,您通过&'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的借用。

最新更新