0

Let me give the code first

fn dump(iter: &mut dyn Iterator<Item=String>) {
    for (i, v) in iter.enumerate() {
        println!("{} {}", i, v);
    }
    for v in iter {
        println!("{}", v);
    }
}

#[test]
fn test_trait() {
    let v = vec!["a".to_string(), "b".to_string(), "c".to_string()];
    let mut iter = v.into_iter();
    dump(&mut iter);
}

Here is the output when I run this test

running 1 test

0 a

1 b

2 c

test test_trait ... ok

Why the iter not moved when calling enumerate?

The enumerate is accepting self as its first argument, so I think it should move the iter, but it doesn't! The second for-loop can still run, without any compilation error.

shimoo
  • 1
  • let me clear my thought. `&mut dyn Iterator` somehow implements the `Iterator` trait, so `iter` can call `enumerate` function, and because the `Self` is `&mut`, so `iter` is not moved according to the answer mentioned above. And also `&mut dyn Iterator` implements `IntoIterator`, so the `iter.into_iter()` is called in the second for-loop. This time `Self` is also `&mut`( I guess), why moved? – shimoo Nov 05 '21 at 11:08
  • Here is an [explanation](https://doc.rust-lang.org/std/iter/index.html#for-loops-and-intoiterator) of why iter would be moved by for-loop. It is not moved by enumerate because of re-borrowing explained in the reference [post](https://stackoverflow.com/questions/62960584/do-mutable-references-have-move-semantics). – Joe_Jingyu Nov 05 '21 at 13:25

1 Answers1

1

In this case, Self is actually &mut (dyn Iterator<Item = String>) making the enumerate call return Enumerate<&mut (dyn Iterator<Item = String>)>. I am not that familiar how Rust deals with this kind of dynamic trait objects but my guess is that what gets dropped at the end of enumeration is actually the reference.

By the way - if you are using VSCode and the Rust analyzer extension, you can turn on the "Inlay Hints: Type Hints" option to see the types of things. There is a similar option for the Intellij Idea IDE that I can not remember off the top of my head. That way I was able to see the type by making a variable of the enumeration and this is what it showed:

let a: Enumerate<&mut (dyn Iterator<Item = String>)>
Kendas
  • 1,963
  • 13
  • 20
  • but the second loop does move the `iter`, because if I add a third loop `for v in iter`, compiler will tell me it is moved – shimoo Nov 05 '21 at 06:47