I am trying (and struggling) to create a simple tree structure in Rust and a breadth-first iterator for it, however I've been stuck for hours trying to fix lifetimes. This is the closest I've got to a successful build, but the only error is the one in the title.
Here is the full code:
use std::{vec, vec::Vec};
pub struct Tree<K, V>
where K: PartialEq + Clone {
subtrees: Vec<Tree<K, V>>,
key: K,
value: Option<V>,
}
impl<K, V> Tree<K, V>
where K: PartialEq + Clone {
pub const fn new(root_key: K, root_value: Option<V>) -> Tree<K, V> {
Tree {
subtrees: Vec::new(),
key: root_key,
value: root_value,
}
}
pub fn get_subtree(&mut self, key: K) -> Option<&mut Self> {
for tree in &mut self.subtrees {
if tree.key == key {
return Some(tree);
}
}
None
}
pub fn value(&mut self) -> Option<&mut V> {
self.value.as_mut()
}
pub fn insert_subtree(&mut self, key: K, value: Option<V>) {
self.subtrees.push(Tree::new(key, value));
}
pub fn iter_bfs(&mut self) -> BFSIterator<K, V> {
BFSIterator {
levels: vec![(0, vec![SearchState {
tree: self,
parent: None,
visited: false,
}])],
}
}
}
struct SearchState<'a, K: 'a, V: 'a>
where K: PartialEq + Clone {
tree: &'a mut Tree<K, V>,
parent: Option<&'a mut Tree<K, V>>,
visited: bool,
}
struct BFSIterator<'a, K: 'a, V: 'a>
where K: PartialEq + Clone {
levels: Vec<(usize, Vec<SearchState<'a, K, V>>)>,
}
impl<'a, K, V> BFSIterator<'a, K, V>
where K: PartialEq + Clone {
fn current_level(&mut self) -> &mut (usize, Vec<SearchState<'a, K, V>>) {
self.levels.last_mut().unwrap()
}
fn current_node(&mut self) -> &mut SearchState<'a, K, V> {
let index = self.current_level().0;
&mut self.current_level().1[index]
}
fn advance_vertical(&mut self) {
// current node is parent
let parent = &self.current_node().tree;
// fill next level vec with children of current node
let mut level_vec = Vec::new();
let a_tree = self.current_node().tree;
for tree in &mut a_tree.subtrees {
level_vec.push(SearchState {
tree,
parent: Some(*parent),
visited: false,
});
}
// advance horizontally to get to the next one when we go back here
self.current_level().0 += 1;
// if it is a leaf, do not advance
if level_vec.len() != 0 {
self.levels.push((0, level_vec));
}
}
}
impl<'a, K: 'a, V: 'a> Iterator for BFSIterator<'a, K, V>
where K: PartialEq + Clone {
type Item = &'a mut Tree<K, V>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_node().visited {
if self.current_level().0 < self.current_level().1.len() {
// we can go down if not at the end of the line
self.advance_vertical();
let junk_state = self.current_node().tree;
return Some(junk_state);
} else {
if self.levels.len() > 0 {
// if everything on this line has been searched, go back
self.levels.pop();
} else {
// got back to beginning, quit
return None;
}
}
} else {
let ret_ref = self.current_node().tree;
self.current_node().visited = true;
if self.current_level().0 < self.current_level().1.len() - 1 {
// advance horizontally if we can
self.current_level().0 += 1;
} else {
// last node visited on this level, let's advance horizontally from the beginning if we can
// go back to node 0 horizontally
self.current_level().0 = 0;
self.advance_vertical();
return Some(ret_ref);
}
}
None
}
}
The problematic line is the following:
// current node is parent
let parent = &self.current_node().tree;
Here, it is apparent that the field tree
of the struct SearchState
is a mutable reference with lifetime 'a
, but Rust struggles to realize, as shown in the full error message:
cannot infer an appropriate lifetime for autoref due to conflicting requirements
expected `Vec<SearchState<'a, _, _>>`
found `Vec<SearchState<'_, _, _>>`
What are your suggestions to fix it? I really don't want to end up just using raw pointers instead of references.