Reputation: 175
When compiling the following code:
pub enum NodeType {
None,
Node(Box<Node>),
}
pub struct Node {
next: NodeType,
}
impl Node {
fn traverse_recursively<F>(&self, depth: usize, f: &mut F)
where
F: FnMut(&Node, usize),
{
f(self, depth);
match &self.next {
NodeType::None => {}
NodeType::Node(node) => {
node.traverse_recursively(depth + 1, f);
}
}
}
pub fn visit_all<F>(&self, f: &mut F)
where
F: FnMut(&Node, usize),
{
self.traverse_recursively(1, f);
}
}
pub fn create_small_recursive_structure() -> Node {
Node {
next: NodeType::Node(Box::new(Node {
next: NodeType::Node(Box::new(Node { next: NodeType::None })),
})),
}
}
#[test]
fn test_so() {
let parent = create_small_recursive_structure();
let mut visited = Vec::new();
parent.visit_all(&mut |node, depth| {
visited.push((node, depth));
});
}
The compiler gives me the following error:
error[E0521]: borrowed data escapes outside of closure
--> src/so_question.rs:50:9
|
47 | let mut visited = Vec::new();
| ----------- `visited` declared here, outside of the closure body
48 |
49 | parent.visit_all(&mut |node, depth| {
| ---- `node` is a reference that is only valid in the closure body
50 | visited.push((node, depth));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `node` escapes the closure body here
I have found a similar question here, but the solution does not help me. I.e. my closure parameters already has no types, and I've experimented by adding and removing types and it doesn't seem to help.
What would I need to do in order to temporarily store a vector of references to the nodes in the tree structure? The intention is for the vector to live shorter than the node structure. Adding an extra pair of brackets to emphasize this for the compiler doesn't help.
Thanks!
Upvotes: 1
Views: 109
Reputation: 42678
You need to specify the lifetimes, so the compiler knows that the references will live for the same amount as self
does:
pub enum NodeType {
None,
Node(Box<Node>),
}
pub struct Node {
next: NodeType,
}
impl Node {
fn traverse_recursively<'s, F>(&'s self, depth: usize, f: &mut F)
where
F: FnMut(&'s Node, usize),
{
f(self, depth);
match &self.next {
NodeType::None => {}
NodeType::Node(node) => {
node.traverse_recursively(depth + 1, f);
}
}
}
pub fn visit_all<'s, F>(&'s self, f: &mut F)
where
F: FnMut(&'s Node, usize),
{
self.traverse_recursively(1, f);
}
}
pub fn create_small_recursive_structure() -> Node {
Node {
next: NodeType::Node(Box::new(Node {
next: NodeType::Node(Box::new(Node { next: NodeType::None })),
})),
}
}
#[test]
fn test_so() {
let parent = create_small_recursive_structure();
let mut visited = Vec::new();
parent.visit_all(&mut |node: &Node, depth| {
visited.push((node, depth));
});
}
Upvotes: 2