Why does the Iterator::filter method accept a mutable reference as self?

Viewed 210

The signature of Iterator::filter is

fn filter<P>(self, predicate: P) -> Filter<Self, P>
where
    Self: Sized,
    P: FnMut(&Self::Item) -> bool,

Because it has self as the first parameter, I was assuming I would have to pass the iterator by value, thus moving ownership to that function. However, I am able to call it with just a ref mut and the code compiles and runs. For example:

fn char_count(i: &mut impl Iterator<Item=char>, c: char) -> usize {
    i.filter(|&x| c == x).count()
}

What am I missing here?

1 Answers

There is confusion about the two parameters here.

The self parameter refers to the original iterator. That is, filter() moves whatever the original iterator is into the new Filter struct, which takes ownership of that iterator (the Self in Filter<Self, _>)

The predicate is a FnMut because it does not need to be an Fn. That is, the function provided as predicate is allowed to modify the context it captures while it executes. This is possible because Filter itself does not borrow predicate when it calls it. If it did, predicate would have to be an Fn(&Self::Item).

The predicate takes the iterator's items by reference. Notice the sigil in the signature FnMut(&Self::Item).

Related