我有一个竞技场的代码,其中分配给您一个索引,您稍后使用相同的索引来获取对象。
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>
。这意味着arena
是Arena<'static>
。
当这两者结合在一起时,一切都会出错:由于您声明&mut self
与Node
具有相同的生存期,编译器必须推断&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
的借用。