0

Why do all methods in a chain of calls except the last need a mutable reference to a mutable iterator?

My intention is to change the internal state of the iterator (...: &mut std::slice::Iter<u8>), not the pointer/reference itself (mut it: ...). My intuition is built on this answer.

fn main() {
    let v = vec![1, 2, 3];
    let mut it = v.iter();

    match it.next() {
        Some(v) => {
            fun1(&mut it);
            println!("{:?}", v);
        }
        None => (),
    }
}

fn fun1(mut it: &mut std::slice::Iter<u8>) {
    //  ^-- why mut?
    match it.next() {
        Some(v) => {
            fun2(&mut it);
            println!("{:?}", v);
        }
        None => (),
    }
}

fn fun2(it: &mut std::slice::Iter<u8>) {
    //  ^-- not needed
    match it.next() {
        Some(v) => {
            println!("{:?}", v);
        }
        None => (),
    }
}

When I remove this mut, I get this error:

error[E0596]: cannot borrow `it` as mutable, as it is not declared as mutable
  --> src/main.rs:18:18
   |
14 | fn fun1(it: &mut std::slice::Iter<u8>) {
   |         -- help: consider changing this to be mutable: `mut it`
...
18 |             fun2(&mut it);
   |                  ^^^^^^^ cannot borrow as mutable
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
NiegodziwyBeru
  • 864
  • 1
  • 10
  • 19
  • 5
    You shouldn't be making a reference to the reference at all: `fun2(it)`. Does adding `mut` actually make it compile? – Ry- Aug 18 '20 at 16:27
  • Yes, weird, but it compile with `mut` [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f29c777522ece855488d6c97882cd0ce). I was more interested of this specific, strange "reference collapsing mechanic" (_deref coercions_?), rather what is proper why to do this. This [post](https://stackoverflow.com/questions/38034912/how-do-i-recursively-pass-a-mutable-reference/38034953#38034953) is probably what I was looking for. Thanks. – NiegodziwyBeru Aug 19 '20 at 18:27

0 Answers0