A type with an (&mut self) function needs to be mutable?

This is a snippet from the Crust of Rust youtube series

pub struct StrSplit<'a> {
    remainder: Option<&'a str>,
    delimiter: &'a str,
}

impl<'a> StrSplit<'a> {
    pub fn new(document: &'a str, delimiter: &'a str) -> Self {
        Self {
            remainder: Some(document),
            delimiter,
        }
    }
}

impl<'a> Iterator for StrSplit<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<Self::Item> {
        let remainder = self.remainder.as_mut()?;

        if let Some(next_delim) = remainder.find(self.delimiter) {
            let next_split = &remainder[..next_delim];
            *remainder = &remainder[next_delim + self.delimiter.len()..];
            Some(next_split)
        } else {
            self.remainder.take()
        }
    }
}

#[test]
fn it_works() {
    let document = "a b c d e f";
    let str_spl = StrSplit::new(document, " ");
    let letters: Vec<_> = str_spl.collect();
    assert_eq!(letters, vec!["a", "b", "c", "d", "e", "f"]);
}

#[test]
fn tail() {
    let document = "a b c d e ";
    let str_spl = StrSplit::new(document, " ");
    let letters: Vec<_> = str_spl.collect();
    assert_eq!(letters, vec!["a", "b", "c", "d", "e", ""]);
}

notice here that the next(&mut self) takes an &mut self. but let str_spl = StrSplit::new(document, " "); doesn't declare it as mutable

So how come that works fine but this below snippet doesn't?
Why doesn't str_spl need to be mutable?

struct Foo {
    bar: u32,
}

impl Foo {
    fn increment(&mut self) {
        self.bar += 1;
    }
}

fn main() {
    let foo = Foo { bar: 1 };
    foo.increment(); // this line errors
}

This is because you are moving the iterator out of the non-mut variable before the mutation happens. In the case of collect, the collect method takes its self argument by-value, so str_spl is moved into the collect method, and the collect method then internally marks it as mut there.

In some sense, it's similar to this:

fn main() {
    let foo = Foo { bar: 1 };
    let mut bar = foo;
    bar.increment();
}

Thanks, makes sense

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.