I have a tree structure with a node and children, and a loop from a GUI library which expects a function to run on each iteration. I'm struggling to get the borrow checker to let me keep a reference to the node I'm processing - it complains that nodes
doesn't live long enough.
Here's a minimal reproduction:
#[derive(Debug)]
struct Node {
value: u64,
children: Vec<Node>,
}
fn run_loop<F>(mut handler: F)
where
F: 'static + FnMut(),
{
for _ in 0..500 {
handler();
}
}
fn main() {
let nodes = vec![
Node {
value: 1,
children: vec![Node {
value: 3,
children: vec![],
}],
},
Node {
value: 2,
children: vec![],
},
];
let mut node = &nodes[0];
run_loop(move || {
println!("Node: {:?}", node);
node = &node.children[0];
});
}
error[E0597]: `nodes` does not live long enough
--> src/main.rs:30:21
|
30 | let mut node = &nodes[0];
| ^^^^^ borrowed value does not live long enough
31 |
32 | / run_loop(move || {
33 | | println!("Node: {:?}", node);
34 | | node = &node.children[0];
35 | | });
| |______- argument requires that `nodes` is borrowed for `'static`
36 | }
| - `nodes` dropped here while still borrowed
What's the best way to make this work? I can't change the structure of run_loop
. Ideally I wouldn't change the structure of Node
(it's an object returned from a third-party library so while I could parse the object out into a new data structure, that wouldn't be elegant). Can I make the borrow checker happy with this just making changes in main
?
node
andnodes
tied together, with some sort of guarantee thatnode
will never outlivenodes
. And of course, the funny thing is that you can't movenodes
because it's borrowed bynode
anyway. – Bartek BanachewiczRc
s, but I'm hoping there's a somewhat more elegant solution since in principlenodes
can live as long as the closure and never needs to move/change. – Juliannode
inside the closure, that would work. I can't see any way to pass state to the closure without initializing it outside, and depending on capture, but if there's a way to do that I'd love to know it. – Juliannode
anOption<&Node>
and setting it toSome(&nodes[0])
inside the loop work? (possibly with-Z polonius=y
?) – Solomon Ucko