I'm trying to find the correct syntax to solve a problem.
The goal is to create a trait that allows visiting it's type in a nested fashion. Ie if you have a large tree structure, where each tree item might be in different vecs on the same type, or even non vec data structures, and then you visit each node in the tree and call a passed in closure on the node.
And the point of implementing the trait on a reference type wrapper, is so you could create a reference enum wrapper, and make this whole thing work on multiple different types.
Was trying to avoid dyn because of performance, but starting to think there is no way around it. As my code (which is the closest Ive gotten to solving it):
pub trait MyTrait: Sized{
type MyStruct<'a> : MyTrait<MyStruct<'a> = Self::MyStruct<'a>>;
fn visit_child_mut<F>(&mut self, index: usize, visitor: F)
where F: for<'b, 'c> FnMut(&'b mut Self::MyStruct<'c>);
}
pub struct VariantMut<'a>{
ref_data: &'a mut Recursive,
}
pub struct Recursive{
data: Vec<Recursive>
}
impl<'a> MyTrait for VariantMut<'a>{
type MyStruct<'b> = VariantMut<'b>;
fn visit_child_mut<F>(&mut self, index: usize, mut visitor: F) where
F: for<'b, 'c> FnMut(&'b mut VariantMut<'c>), {
let mut child_data = VariantMut{
ref_data: &mut self.ref_data.data[index]
};
visitor(&mut child_data)
}
}
fn render_children<T: for<'a>MyTrait<MyStruct<'a> = T>>(
node: &mut T,
render_fn: &impl Fn(&mut T),
) where
{
for index in 0..3 {
node.visit_child_mut(index, |child| {
render_fn(child);
render_children(child, render_fn);
});
}
}
fn main() {
let mut root = Recursive {
data: vec![
Recursive { data: vec![Recursive { data: vec![] }, Recursive { data: vec![] }, Recursive { data: vec![] }] },
Recursive { data: vec![Recursive { data: vec![] }, Recursive { data: vec![] }, Recursive { data: vec![] }] },
Recursive { data: vec![Recursive { data: vec![] }, Recursive { data: vec![] }, Recursive { data: vec![] }] },
],
};
let mut root_variant = VariantMut {
ref_data: &mut root,
};
let render_fn = |node: &mut VariantMut| {
println!("Rendering node with {} children", node.ref_data.data.len());
};
render_children(&mut root_variant, &render_fn);
}
Results in an error:
error[E0597]: `root` does not live long enough
--> src/main.rs:51:19
|
41 | let mut root = Recursive {
| -------- binding `root` declared here
...
51 | ref_data: &mut root,
| ^^^^^^^^^ borrowed value does not live long enough
...
60 | render_children(&mut root_variant, &render_fn);
| ---------------------------------------------- argument requires that `root` is borrowed for `'static`
61 | }
| - `root` dropped here while still borrowed
|
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
--> src/main.rs:29:28
|
29 | ) where T: for<'a> MyTrait<MyStruct<'a> = T>
| ^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> src/main.rs:60:5
|
60 | render_children(&mut root_variant, &render_fn);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected struct `VariantMut<'a>`
found struct `VariantMut<'_>`
note: the lifetime requirement is introduced here
--> src/main.rs:29:28
|
29 | ) where T: for<'a> MyTrait<MyStruct<'a> = T>
| ^^^^^^^^^^^^^^^^
due to current limitations in the borrow checker, this implies a
'staticlifetime
Does this mean its not possible to solve this?