sarik123
sarik123

Reputation: 21

into_iter() available on Iterator and multiple times

I am new to rust and was going over iterators and this where I got blocked.So if I am implementing Iterator directly and not IntoIterator,how come I am able to call into_iter (and too multiple times).My understanding is if I implemented IntoIterator,I should be going to Iterator via into_iter.But if I am able to implement Iterator,why do I still need into_iter(would be called implicitly if i didnt give I guess for for in )

struct StrSplit<'a> {
    rest: &'a str,
    delim: &'a str,
}

impl<'a> StrSplit<'a> {
    fn new(haystack: &'a str, delim: &'a str) -> Self {
        Self {
            rest: haystack,
            delim,
        }
    }
}

impl<'a> Iterator for StrSplit<'a> {
    type Item = &'a str;
    fn next(&mut self) -> Option<Self::Item> {
        let to_return;
        if let Some(next) = self.rest.find(self.delim) {
            to_return = &self.rest[..next];
            self.rest = &self.rest[next + self.delim.len() + 1..];
            return Some(to_return);
        } else if !self.rest.is_empty() {
            to_return = self.rest;
            self.rest="";
            return Some(to_return);
        }
        return None;
    }
}

fn main() {
    let check = StrSplit::new("this was to check what was to be checked", "was");

    let iterr = check.into_iter().into_iter().into_iter();
    for part in iterr {
        println!("{}", part);
    }
}

Upvotes: 1

Views: 696

Answers (1)

cadolphs
cadolphs

Reputation: 9617

If you're new to Rust this might be a bit subtle, but it's a thing that you'll see quite often with the traits of the standard library:

You correctly note that into_iter is a method of the IntoIterator trait. You also note that you implemented Iterator for your struct, but not IntoIterator. So what gives?

Checking the methods defined on Iterator, there's no into_iter to be found.

But now if you check the documentation for IntoIterator, and scroll down to the list of Implementors https://doc.rust-lang.org/std/iter/trait.IntoIterator.html#implementors

you will find the following snippet:

impl<I> IntoIterator for I
where
    I: Iterator

This is called a blanket implementation: For any type T that implements the Iterator trait, there will be automatically an implementation for the IntoIterator trait!

Because your struct implements Iterator, it also gets IntoIterator implemented.

There's some other examples of this in the standard library. For example, if you implement From<A> for some type B, you automatically get the Into<B> trait implemented for type A.

Another example is ToString:

impl<T> ToString for T where
    T: Display + ?Sized,

Any type that implements the Display trait gets the ToString trait for free!

Upvotes: 3

Related Questions