在辅助函数中逐字包装代码会导致借用错误
Wrapping code in helper function verbatim leads to borrow error
我为一个通用模式创建了一个辅助函数get_node()
,但由于某种原因它会导致借用错误,但在复制粘贴其内容时却不会。我用评论标记了有问题的行:
type NodeMap = HashMap<i32, Node>;
pub trait IdGenerator {
fn gen(&mut self) -> i32;
}
pub struct Tree<'a> {
active: i32,
nodes: NodeMap,
generator: &'a mut dyn IdGenerator,
}
impl<'a> Tree<'a> {
pub fn create_sibling(&mut self) {
let active = self.nodes.get(&self.active).unwrap(); // <-- THIS WORKS
// let active = self.get_node(self.active); // <-- THIS FAILS
let mut node = Node::new(self.generator.gen(), active.parent);
// [......]
}
fn get_node(&self, id: i32) -> &Node {
self.nodes.get(&id).unwrap()
}
}
取消注释和注释这两行 let active...
会导致以下错误:
error[E0502]: cannot borrow `*self.generator` as mutable because it is also borrowed as immutable
--> src/tree_new.rs:35:34
|
34 | let active = self.get_node(self.active);
| ---- immutable borrow occurs here
35 | let mut node = Node::new(self.generator.gen(), active.parent);
| ^^^^^^^^^^^^^^^^^^^^ ------------- immutable borrow later used here
| |
| mutable borrow occurs here
错误消息是有道理的,但我感到困惑的是为什么相同的借用逻辑不适用于没有辅助函数的原始代码。
此行在 active
的生命周期内不变地借用 self.nodes
(这是当前块范围):
// immutably borrows self.nodes
let active = self.nodes.get(&self.active).unwrap();
// mutably borrows self.generator
self.generator.gen();
// no overlap, no problem ✔️
稍后在同一范围内,您可以可变地借用 self.generator
,但 self.nodes
和 self.generator
不重叠,因此没有问题。
但是,此行在 active
的生命周期内不变地借用了 self
的 all,其中包括 self.generator
(这是与以前相同的块作用域):
// immutably borrows self
let active = self.get_node(self.active);
// mutably borrows self.generator
self.generator.gen();
// compiler error:
// immutable borrow of self overlaps with mutable borrow of self.generator ❌
// ...
// this function signature says: as long as the returned
// reference is live the entire struct is immutably borrowed
fn get_node(&self, id: i32) -> &Node {
self.nodes.get(&id).unwrap()
}
现在由于 self
的 all 是不可变借用的,当你稍后尝试可变借用 self.generator
时,self
的不可变借用和 self.generator
的可变借用重叠,你会得到一个编译器错误。
不幸的是,这是 Rust 的一个已知限制。没有办法“丰富”你的辅助函数的类型签名来告诉 Rust 编译器不可变借用只依赖于 self.nodes
而不是所有的 self
。然而,有些人有兴趣将其添加到语言中,您可以在 Partial Borrowing issue on the Rust RFCs repo. The typical workaround is to split borrows 中跟踪他们的进度,但是您的辅助函数太小了,我认为这种方法不适用于此处,您最好的选择是摆脱辅助函数并继续编写内联逻辑。
我为一个通用模式创建了一个辅助函数get_node()
,但由于某种原因它会导致借用错误,但在复制粘贴其内容时却不会。我用评论标记了有问题的行:
type NodeMap = HashMap<i32, Node>;
pub trait IdGenerator {
fn gen(&mut self) -> i32;
}
pub struct Tree<'a> {
active: i32,
nodes: NodeMap,
generator: &'a mut dyn IdGenerator,
}
impl<'a> Tree<'a> {
pub fn create_sibling(&mut self) {
let active = self.nodes.get(&self.active).unwrap(); // <-- THIS WORKS
// let active = self.get_node(self.active); // <-- THIS FAILS
let mut node = Node::new(self.generator.gen(), active.parent);
// [......]
}
fn get_node(&self, id: i32) -> &Node {
self.nodes.get(&id).unwrap()
}
}
取消注释和注释这两行 let active...
会导致以下错误:
error[E0502]: cannot borrow `*self.generator` as mutable because it is also borrowed as immutable
--> src/tree_new.rs:35:34
|
34 | let active = self.get_node(self.active);
| ---- immutable borrow occurs here
35 | let mut node = Node::new(self.generator.gen(), active.parent);
| ^^^^^^^^^^^^^^^^^^^^ ------------- immutable borrow later used here
| |
| mutable borrow occurs here
错误消息是有道理的,但我感到困惑的是为什么相同的借用逻辑不适用于没有辅助函数的原始代码。
此行在 active
的生命周期内不变地借用 self.nodes
(这是当前块范围):
// immutably borrows self.nodes
let active = self.nodes.get(&self.active).unwrap();
// mutably borrows self.generator
self.generator.gen();
// no overlap, no problem ✔️
稍后在同一范围内,您可以可变地借用 self.generator
,但 self.nodes
和 self.generator
不重叠,因此没有问题。
但是,此行在 active
的生命周期内不变地借用了 self
的 all,其中包括 self.generator
(这是与以前相同的块作用域):
// immutably borrows self
let active = self.get_node(self.active);
// mutably borrows self.generator
self.generator.gen();
// compiler error:
// immutable borrow of self overlaps with mutable borrow of self.generator ❌
// ...
// this function signature says: as long as the returned
// reference is live the entire struct is immutably borrowed
fn get_node(&self, id: i32) -> &Node {
self.nodes.get(&id).unwrap()
}
现在由于 self
的 all 是不可变借用的,当你稍后尝试可变借用 self.generator
时,self
的不可变借用和 self.generator
的可变借用重叠,你会得到一个编译器错误。
不幸的是,这是 Rust 的一个已知限制。没有办法“丰富”你的辅助函数的类型签名来告诉 Rust 编译器不可变借用只依赖于 self.nodes
而不是所有的 self
。然而,有些人有兴趣将其添加到语言中,您可以在 Partial Borrowing issue on the Rust RFCs repo. The typical workaround is to split borrows 中跟踪他们的进度,但是您的辅助函数太小了,我认为这种方法不适用于此处,您最好的选择是摆脱辅助函数并继续编写内联逻辑。