# The same name in the iterator

see the code.

``````
type Item = T;
type IntoIter = IntoIter<T>;

fn into_iter(self) -> Self::IntoIter {
self.into_iter()
}
}

impl<'a, T> IntoIterator for &'a LinkedList<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;

fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}

impl<'a, T> IntoIterator for &'a mut LinkedList<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;

fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
``````
``````    #[test]
fn test_base_first() {

let it1: Iter<i32> = (&list).into_iter();
let it2: IterMut<i32> = (&mut list).into_iter();
let it3: IntoIter<i32> = list.into_iter();
}
``````

LinkedList implements IntoIterator 3 times, so it has 3 'into_iter' methods with the same name, and when I call it with different variations of list, I can call different methods. The principle of this confuses me.

ๅฎๆด็ไปฃ็ ๅ่่ฟ้๏ผBoring Combinatorics - Learning Rust With Entirely Too Many Linked Lists

It's a bit confusing, but this is what lets you iterate over collections by value or using different types of references.

For example,

``````let mut numbers: Vec<u32> = vec![1, 2, 3, 4];

for number in &numbers {
// uses "impl IntoIterator for &Vec<u8>"
// number is a &u32 here
}

for number in &mut numbers {
// uses "impl IntoIterator for &mut Vec<u8>"
// number is a &mut u32
}

for number in numbers {
// uses "impl IntoIterator for Vec<u8>"
// number is a u32
// the original numbers vector is no longer available
}
``````

You'll see this pattern quite often when it comes to collections.

References like `&Vec<u8>` are their own types, so it's perfectly fine to implement a trait for a `&T` and a `T` at the same time.

2 Likes

What does the lifecycle identifier declared between for and struct type do? What is this syntax?
Is this declaration the reason why I can call the same method name with different variations and actually call to different implementations?

In addition to the examples @Michael-F-Bryan provided, it's typical for collections to provide methods with distinct names which yield those same iterators, for example if you own a `LinkedList` then

• `list.into_iter()` will give you the owned iterator (over `T`) via the trait
• `list.iter_mut()` will give you the exclusive borrow iterator (over `&mut T`) via a method
• `list.iter()` will give you the shared borrow iterator (over `&T`) via a method

The methods are more idiomatic and ergonomic in expression position than, say, `(&list).into_iter()`. Where as was demonstrated above, `for item in &list` is the more ergnomic (and idiomatic) approach when using `for`. (What the pattern means is something you pick up when using Rust; you'll see it relatively frequently.)

`&list` creates a shared reference to the `list` and `&mut list` creates an exclusive reference to the `list`. They're similar to address-of operators. The reference calls them borrow operators.

This can happen automatically as part of method calls. In my bullet points above, `list.iter()` creates a `&list` to pass to `LinkedList::iter` and `list.iter_mut()` analogously creates a `&mut list`.

The next question is, how did the compiler choose which methods to call?

To understand what methods are called in which situations and why it's unambiguous, you'll have to learn about method call resolution. The pertinent point when calling `.into_iter()` is that if the type of the variable which is the operand of the method call (to the left of the `.`) is a receiver of the method, that's the 'winner" of method call resolution. So

• `list.into_iter()` "sees" the implementation for the owned `LinkedList` first
• `(&list).into_iter()` "sees" the implementation for `&LinkedList` first
• `(&mut list).into_iter()` "sees" the implementation for `&mut LinkedList` first

`for` ultimately calls `Intoiterator::into_iterator` on the `in _` expression and works in the analogous fashion.

Whereas with `list.iter()`, there is no method called `iter` with a receiver of type `LinkedList`, so the search continues. There is a method called `iter` with a receiver of type `&LinkedList`, and that's the winner.

`list.iter_mut()` similarly finds no `LinkedList` receiver method, also finds no `&LinkedList` receiver method, but then does find the `&mut LinkedList` receiver method called `iter_mut`, so that's the winner.

2 Likes

Another thing that puzzles me is that both of the following impls are wrong

``````impl<T> &LinkedList<T> {
// cannot define inherent `impl` for primitive type
// = help: consider using an extension trait instead
// = note: you could also try moving the reference to uses of `seven::LinkedList<T>` (such as `self`) within the implementation
}

}
``````

It seems that preceding the struct type with a reference and a lifecycle identifier must be implemented in the trait.

Yep. This comes back to the "references are types, too" thing I said. You can think of `&T` as being a type implemented by the standard library. In the same way that I can't add extra inherent methods to `std::string::String`, you can't add extra methods to a reference to `LinkedList<T>`.

2 Likes

The rules for so-called "inherent" `impl`s and trait `impl`s are different. In either case we have restrictions what the `Self`-type, i. e. the type you write at the end of the `impl` line before the opening `{`-brace, but these restrictions are not the same.

For the full story, see this page in the reference: Implementations - The Rust Reference

In short, the `Self`-type for an inherent impl must always be a type that is defined in the same crate as the `impl`. So it's always a `struct` or `enum` or `union` defined in the current crate, or a `dyn Trait + โฆ` trait object type for a trait that is defined in the same crate.

The rules for trait impls are a lot more complex, but for the common case of simple traits without any additional type arguments (like `trait Foo {}` but unlike `trait Bar<T> {}`), it boils down to, essentially, the rule that either

• the trait is defined in the same crate, in which case there are no restrictions to the `Self`-type at all. Since traits can define methods (callable using method call syntax), this rule explains the "extension trait" pattern that is commonly used in crates to implement extra methods for types from other crates, the standard library, or built-in ones. Or
• the trait is defined in a different crate, in which case the `Self` type must be defined in the same crate or of the form `&T`, `&mut T`, `Box<T>` or `Pin<T>` where `T` is a permissable `Self`-type. This applies recursively, so type like `Pin<Box<MyStruct>>`, will work, too.

As you can see, this allows for trait implementations for type like `&LinkedList<T>` (in the same trait where `LinkedList` is defined) but not for inherent `impl`s on the same type, as those didn't have the relevant exception. Usually thats not too much of a problem, as the receiver type of a method can still be `&LinkedList<T>` by means of defining a `&self` method, whereas for trait implementations, the trait itself may prescribe a `self` argument, like `IntoIterator::into_iter` does, which is why it's more useful for trait impls to be less restrictive here.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.