Hi, I don’t even know how to start with this one.
I’m implementing a visitor/transformer pattern and am stuck trying to convert a macro into a function. The self.transform_children(&mut d, Self::transform_…)
below used to be transform_children!(d, self.transform_…)
, which worked, but I have no clue how to define the lifetimes for the below function version of it:
pub trait Transform {
fn transform_children<C, E, I>(
&mut self,
e: &mut E,
mut meth: impl FnMut(&mut Self, C) -> I,
) where
E: HasChildren<C>,
I: Iterator<Item = C>,
{
let mut new = Vec::new();
for c in e.children_mut().drain(..) {
new.extend(meth(self, c));
}
e.children_mut().extend(new);
}
fn transform(&mut self, mut d: e::Document) -> e::Document {
self.transform_children(&mut d, Self::transform_structural_sub_element);
d
}
fn transform_structural_sub_element(
&mut self,
c: c::StructuralSubElement,
) -> impl Iterator<Item = c::StructuralSubElement> {
std::iter::once(c)
}
}
trait HasChildren<C> {
fn children_mut(&mut self) -> &mut Vec<C>;
}
mod e {
use crate::HasChildren;
use crate::c;
pub struct Document;
impl HasChildren<c::StructuralSubElement> for Document {
fn children_mut(&mut self) -> &mut Vec<c::StructuralSubElement> { todo!() }
}
}
mod c {
pub struct StructuralSubElement;
}
I get
error[E0308]: mismatched types
--> src/lib.rs:18:9
|
18 | self.transform_children(&mut d, Self::transform_structural_sub_element);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected associated type `impl for<'a> Iterator<Item = StructuralSubElement>`
found associated type `impl Iterator<Item = StructuralSubElement>`
= note: an associated type was expected, but a different one was found
note: the lifetime requirement is introduced here
--> src/lib.rs:5:47
|
5 | mut meth: impl FnMut(&mut Self, C) -> I,
| ^
and whatever I do, I only end up with `*self` was mutably borrowed here in the previous iteration of the loop
or so.
Playground link: Rust Playground