Reputation: 259
I'm still a little confused on how the Fn
-FnMut
-FnOnce
thing works with other traits. I want to eliminate the Copy
constraint from the following function for traversing a tree structure.
pub fn for_each<F>(&mut self, mut f: F)
where
F: FnMut(&mut Tree<T>) + Copy,
{
self.children.iter_mut().for_each(|c| c.for_each(f));
f(self);
}
The reason for this is that I am trying to pass a closure that modifies an outside variable to for_each
and the Copy
prevents that (E0277
). However, when I get rid of the Copy
, I get the following error message:
error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure
--> src/tree.rs:34:58
|
30 | pub fn for_each<F>(&mut self, mut f: F)
| ----- captured outer variable
...
34 | self.children.iter_mut().for_each(|c| c.for_each(f));
| ^ move occurs because `f` has type `F`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value: `f`
--> src/tree.rs:35:9
|
30 | pub fn for_each<F>(&mut self, mut f: F)
| ----- move occurs because `f` has type `F`, which does not implement the `Copy` trait
...
34 | self.children.iter_mut().for_each(|c| c.for_each(f));
| --- - variable moved due to use in closure
| |
| value moved into closure here
35 | f(self);
| ^ value borrowed here after move
|
help: consider further restricting this bound
|
32 | F: FnMut(&mut Tree<T>) + Copy,
| ^^^^^^
error: aborting due to 2 previous errors
How can I solve this issue? I'm also open to turning this into an iterator if that makes it easier.
Upvotes: 3
Views: 1610
Reputation: 227
The reason for this is, that for_each
takes ownership of f
.
This means, that once you call c.for_each(f)
, you loose ownership of f
, thus you cannot use f
later.
In order to fix this, you could change the for_each
function to instead take a reference, so you can pass it along like this
pub fn for_each<F>(&mut self, f: &mut F)
where
F: FnMut(&mut Tree<T>),
{
// Only a reference is passed into for_each here
self.children.iter_mut().for_each(|c| c.for_each(f));
// f can be used again, as reference is reborrowed implicitly
f(self);
}
Or you could also (if possible) move the call to f
up a line like this
pub fn for_each<F>(&mut self, mut f: F)
where
F: FnMut(&mut Tree<T>),
{
// f is used, but ownership is kept
f(self);
// ownership of f can now be transferred, as there is no further use of it
self.children.iter_mut().for_each(|c| c.for_each(f));
}
Upvotes: 4