My code is
struct Test<Source>
where
Source: Iterator<Item = char>,
{
source: Source,
}
impl<Source: Iterator<Item = char>> Test<Source> {
fn read(&mut self) {
while let Some(item) = self.source.next() {
match item {
'#' => self.read_head(),
_ => {}
}
println!("Handled char {}", item);
}
}
fn read_head(&mut self) {
println!("Start read heading");
let source = self.source.borrow_mut();
let level = source.take_while(|&char| char == '#').count();
println!("Done, level is {}", level);
}
}
fn main() {
let str = "##### Hello World".to_string();
let str = str.chars().into_iter();
let mut test = Test { source: str };
test.read();
}
It works good. But in this line:
let source = self.source.borrow_mut();
If changes borrow_mut
to borrow
, will produce the error:
error[E0507]: cannot move out of `*source` which is behind a shared reference
--> src/main.rs:24:21
|
24 | let level = source.take_while(|&char| char == '#').count();
| ^^^^^^ move occurs because `*source` has type `Source`, which does not implement the `Copy` trait
So why borrow_mut works but borrow not. I don't have a clear understanding about relation between move
and borrow
.
So why
borrow_mut
works butborrow
not.
Because there is an implementation of Iterator
for exclusive references to iterators:
impl<'_, I> Iterator for &'_ mut I where I: Iterator + ?Sized
This means an exclusive reference to an Iterator is itself an iterator, and can be used "as is" (which incidentally is why Iterator::by_ref
is a thing, and useful).
I don't have a clear understanding about relation between
move
andborrow
.
There isn't one in and of itself, it's just that in this case a mutable reference to an iterator is also an iterator (in its own right), which means it fulfills take_while
's requirements to take an iterator by value:
pub fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> where P: FnMut(&Self::Item) -> bool
a shared reference is not so, and thus triggers the error you see.