3 ms·
Like mentioned below, for loops desugar to something that ends up calling the "into_iter" method on the type. In rust &mut T, &T and T are different types, so t
by chlorion 4y ago
Like mentioned below, for loops desugar to something that ends up calling the "into_iter" method on the type. In rust &mut T, &T and T are different types, so the "into_iter" method is actually different for each one!
Here is an example to illustrate what I mean (i did not test to see if it compiles so there may be some mistakes):
struct Foo<T>(Vec<T>);
impl IntoIterator for Foo<T> {
type IntoIter = std::vec::IntoIter<T>;
type Item = T;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a> IntoIterator for &'a Foo<T> {
type IntoIter = std::slice::Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
self.0.as_slice().iter()
}
}
impl<'a> IntoIterator for &'a mut Foo<T> {
type IntoIter = std::slice::IterMut<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
self.0.as_slice().iter_mut()
}
}
Doing "for x in T" calls the first method, "for x in &T" calls the second, and "for x in &mut T" calls the last one.
As you see here, each IntoIterator returns a completely different type, and the first IntoIterator actually consumes the struct Foo as well!
There are also the methods "iter" and "iter_mut", these are just there for convention and technically don't need to exist for the iterator related traits. It's useful for doing iterator pipelines that don't have any for loop.