"cannot borrow `graph` as immutable because it is also borrowed as mutable." 我怎样才能让 Rust 知道我已经完成了那个可变借用?
"cannot borrow `graph` as immutable because it is also borrowed as mutable." How can I let Rust know that I'm done with that mutable borrow?
我正在尝试用 Rust 制作一个类似图形的结构。我的第一个实现编译得很好:
fn main() {
let mut graph: Graph = Graph::new(); // Contains a vector of all nodes added to the graph. The graph owns the nodes.
// Create a node
let parent: usize = graph.add_node(ParentNode::new()); // Returns the ID of the node.
let parent: &Node = graph.get_node_with_id(parent); // Returns a borrowed reference to the node with the given ID
// Print the number of nodes
println!("Num nodes: {}", graph.count_nodes());
}
我不喜欢我必须先调用 add_node
然后再调用 get_node_with_id
的方式,因此我编写了另一种将这两个步骤合二为一的方法:
fn main() {
let mut graph: Graph = Graph::new();
// Create a node
let parent: &Node = graph.add_node_and_borrow(ParentNode::new());
// Print the number of nodes
println!("Num nodes: {}", graph.count_nodes());
}
add_node_and_borrow
只是一个 shorthand:
/// Like add_node, but returns a borrowed reference
/// instead of the id
pub fn add_node_and_borrow(&mut self, node: Box<Node>) -> &Node {
let id = self.add_node(node);
return self.get_node_with_id(id);
}
当我尝试编译它时,出现错误:
error[E0502]: cannot borrow `graph` as immutable because it is also borrowed as mutable
--> src/main.rs:23:31
|
20 | let parent: &Node = graph.add_node_and_borrow(ParentNode::new());
| ----- mutable borrow occurs here
...
23 | println!("Num nodes: {}", graph.count_nodes());
| ^^^^^ immutable borrow occurs here
24 | }
| - mutable borrow ends here
奇怪!在这两个示例中,我都在做完全相同的事情……不是吗?为什么 Rust 认为我从未停止在第二个示例中可变借用 graph
?
这是完整的源文件,去掉了不重要的部分,这样您就可以看到完整的图片:
fn main() {
does_not_compike();
}
fn compiles() {
let mut graph: Graph = Graph::new();
// Create a node
let parent: usize = graph.add_node(ParentNode::new());
let parent: &Node = graph.get_node_with_id(parent);
// Print the number of nodes
println!("Num nodes: {}", graph.count_nodes());
}
fn does_not_compike() {
let mut graph: Graph = Graph::new();
// Create a node
let parent: &Node = graph.add_node_and_borrow(ParentNode::new());
// Print the number of nodes
println!("Num nodes: {}", graph.count_nodes());
}
struct Graph {
nodes: Vec<Box<Node>>,
next_node_id: usize,
}
impl Graph {
pub fn new() -> Graph {
// Construct a new graph with no nodes.
let new_graph = Graph {
nodes: Vec::new(),
next_node_id: 0,
};
return new_graph;
}
/// Adds a newly-created node to graph.
/// The graph becomes the new owner of the node.
/// Returns the node id of the node.
pub fn add_node(&mut self, node: Box<Node>) -> usize {
// Add the node
self.nodes.push(node);
// Return the id
let id = self.next_node_id;
self.next_node_id += 1;
return id;
}
/// Like add_node, but returns a borrowed reference
/// instead of the id
pub fn add_node_and_borrow(&mut self, node: Box<Node>) -> &Node {
let id = self.add_node(node);
return self.get_node_with_id(id);
}
/// Returns a borrowed reference to the node with the given id
pub fn get_node_with_id(&self, id: usize) -> &Node {
return &*self.nodes[id];
}
pub fn count_nodes(&self) -> usize {
return self.nodes.len();
}
}
trait Node {
// Not important
}
struct ParentNode {
// Not important
}
impl ParentNode {
pub fn new() -> Box<Node> {
Box::new(ParentNode {
// lol empty struct
})
}
}
impl Node for ParentNode {
// Not important
}
在你的第一个例子中:
let parent: usize = graph.add_node(ParentNode::new());
为调用 add_node
可变地借用 graph
然后释放借用。
let parent: &Node = graph.get_node_with_id(parent);
不可变地借用 graph
并且 保留 借用,因为 parent 是对属于该图的节点的引用。此时,,您将无法向图中添加新节点,因为不可变借用阻止您创建新的可变借用。但是,您可以不可变地重新借用 graph
来打印它。
在你的第二个例子中:
let parent: &Node = graph.add_node_and_borrow(ParentNode::new());
可变借用graph
(因为函数签名)并保留借用(因为parent
引用)。在此之后,您根本无法再借用图表,因为您已经有一个活动的可变借用。
我正在尝试用 Rust 制作一个类似图形的结构。我的第一个实现编译得很好:
fn main() {
let mut graph: Graph = Graph::new(); // Contains a vector of all nodes added to the graph. The graph owns the nodes.
// Create a node
let parent: usize = graph.add_node(ParentNode::new()); // Returns the ID of the node.
let parent: &Node = graph.get_node_with_id(parent); // Returns a borrowed reference to the node with the given ID
// Print the number of nodes
println!("Num nodes: {}", graph.count_nodes());
}
我不喜欢我必须先调用 add_node
然后再调用 get_node_with_id
的方式,因此我编写了另一种将这两个步骤合二为一的方法:
fn main() {
let mut graph: Graph = Graph::new();
// Create a node
let parent: &Node = graph.add_node_and_borrow(ParentNode::new());
// Print the number of nodes
println!("Num nodes: {}", graph.count_nodes());
}
add_node_and_borrow
只是一个 shorthand:
/// Like add_node, but returns a borrowed reference
/// instead of the id
pub fn add_node_and_borrow(&mut self, node: Box<Node>) -> &Node {
let id = self.add_node(node);
return self.get_node_with_id(id);
}
当我尝试编译它时,出现错误:
error[E0502]: cannot borrow `graph` as immutable because it is also borrowed as mutable
--> src/main.rs:23:31
|
20 | let parent: &Node = graph.add_node_and_borrow(ParentNode::new());
| ----- mutable borrow occurs here
...
23 | println!("Num nodes: {}", graph.count_nodes());
| ^^^^^ immutable borrow occurs here
24 | }
| - mutable borrow ends here
奇怪!在这两个示例中,我都在做完全相同的事情……不是吗?为什么 Rust 认为我从未停止在第二个示例中可变借用 graph
?
这是完整的源文件,去掉了不重要的部分,这样您就可以看到完整的图片:
fn main() {
does_not_compike();
}
fn compiles() {
let mut graph: Graph = Graph::new();
// Create a node
let parent: usize = graph.add_node(ParentNode::new());
let parent: &Node = graph.get_node_with_id(parent);
// Print the number of nodes
println!("Num nodes: {}", graph.count_nodes());
}
fn does_not_compike() {
let mut graph: Graph = Graph::new();
// Create a node
let parent: &Node = graph.add_node_and_borrow(ParentNode::new());
// Print the number of nodes
println!("Num nodes: {}", graph.count_nodes());
}
struct Graph {
nodes: Vec<Box<Node>>,
next_node_id: usize,
}
impl Graph {
pub fn new() -> Graph {
// Construct a new graph with no nodes.
let new_graph = Graph {
nodes: Vec::new(),
next_node_id: 0,
};
return new_graph;
}
/// Adds a newly-created node to graph.
/// The graph becomes the new owner of the node.
/// Returns the node id of the node.
pub fn add_node(&mut self, node: Box<Node>) -> usize {
// Add the node
self.nodes.push(node);
// Return the id
let id = self.next_node_id;
self.next_node_id += 1;
return id;
}
/// Like add_node, but returns a borrowed reference
/// instead of the id
pub fn add_node_and_borrow(&mut self, node: Box<Node>) -> &Node {
let id = self.add_node(node);
return self.get_node_with_id(id);
}
/// Returns a borrowed reference to the node with the given id
pub fn get_node_with_id(&self, id: usize) -> &Node {
return &*self.nodes[id];
}
pub fn count_nodes(&self) -> usize {
return self.nodes.len();
}
}
trait Node {
// Not important
}
struct ParentNode {
// Not important
}
impl ParentNode {
pub fn new() -> Box<Node> {
Box::new(ParentNode {
// lol empty struct
})
}
}
impl Node for ParentNode {
// Not important
}
在你的第一个例子中:
let parent: usize = graph.add_node(ParentNode::new());
为调用 add_node
可变地借用 graph
然后释放借用。
let parent: &Node = graph.get_node_with_id(parent);
不可变地借用 graph
并且 保留 借用,因为 parent 是对属于该图的节点的引用。此时,graph
来打印它。
在你的第二个例子中:
let parent: &Node = graph.add_node_and_borrow(ParentNode::new());
可变借用graph
(因为函数签名)并保留借用(因为parent
引用)。在此之后,您根本无法再借用图表,因为您已经有一个活动的可变借用。