2

To my understanding, for loop implicitly call into_iter() on vector to loop through it.

However, in the code below, why does vec in the first for loop in question1_1 not consumed, but vec in the second for loop does?

fn question1_1(vec: &mut [i32]) {
    for &mut item in vec.into_iter() {
        println!("{}", item);
    }
    for &mut item in vec { // --- `vec` moved due to this implicit call to `.into_iter()`
        println!("{}", item);
    }
    vec; // Error: move occurs because `vec` has type `&mut [i32]`, which does not implement the `Copy` trait
}

pub fn main() {
    let mut s = vec![1, 2, 3];
    question1_1(&mut s);

No matter the variable in loop is &mut item or item, it's all showing the same error

fn question1_2(vec: &mut [i32]){
    for item in vec.into_iter() {
        println!("{} {:p}", item, item);
    }
    for item in vec { // -- vec` moved due to this implicit call to `.into_iter()`
        println!("{} {:p}", item, item);
    }
    vec; // Error: move occurs because `vec` has type `&mut [i32]`, which does not implement the `Copy` trait
}

pub fn main() {
    let mut s = vec![1, 2, 3];
    question1_2(&mut s);
Jack Lien
  • 105
  • 6
  • @ChayimFriedman The answer in this article explained how reborrow `&mut *v` can be repeated iterate but didn't explain why `vec.into_iter()` can be repeatedly used while `vec` can't. I thought into_iter() is an implicit call made from for loop. – Jack Lien May 12 '22 at 12:42
  • There is another better duplicate, I just haven't found it (not that I really tried). The point is that calling `into_iter()` performs a reborrow but without it it doesn't. – Chayim Friedman May 12 '22 at 12:45
  • 2
    [Iterate through a mutable reference of vector without moving the value from the vector](https://stackoverflow.com/questions/70430078/iterate-through-a-mutable-reference-of-vector-without-moving-the-value-from-the/70431955) – Chayim Friedman May 12 '22 at 12:46
  • @ChayimFriedman Just to make sure if I am understanding it correctly. When we call a method with a mutable reference (`vec.into_iter`), it automatically reborrow. But what for loop do is calling a function (`IntoIterator::into_iter(vec)`), which doesn't have automatically reborrowing provided, and that's why vec was consumed. Am I right? – Jack Lien May 12 '22 at 12:59
  • 1
    The difference is how you call the method: if you use the dot syntax, reborrowing takes place and `vec.into_iter()` is actually `(&mut *vec).into_iter()`. But when called with UFCS syntax, reborrowing is not involved. – Chayim Friedman May 12 '22 at 13:10
  • I would've vote to close this as a duplicate to the second question I linked, but I already voted so I can't. – Chayim Friedman May 12 '22 at 13:22
  • 1
    @ChayimFriedman Calling the method with UFCS syntax, i.e. `<&mut [i32] as IntoIterator>::into_iter(vec)`, will also reborrow. I'ts only moved when it is called as `IntoIterator::into_iter(vec)`. See [Do mutable references have move semantics?](https://stackoverflow.com/questions/62960584/do-mutable-references-have-move-semantics) for an explanation. – Sven Marnach May 12 '22 at 13:52
  • @SvenMarnach Yes I meant not really UFCS just the method trait name but I don't know a specific name for that. – Chayim Friedman May 12 '22 at 14:12
  • I suggest looking at a much simpler case to gain understanding. [Playground Link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ce096c408db2b912076c523dacbcb484). This will not compile. But replace one line by **let z1 = &vec;** and it will. – PaulCommentary May 06 '23 at 14:43

0 Answers0