编译器认为借用还活着
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>
。这意味着 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
.
的任何生命周期都短的生命周期
我有这个竞技场的代码,其中分配给你一个索引,你稍后使用相同的索引来获取对象。
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>
。这意味着 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
.