Generally they are separate structs, though I'm not sure that what you mean. There are iterator which take ownership of the original data structure and there are iterators that borrow the original data structure.
By convention, an iter() method indicates a borrowing iterator that doesn't consume the collection, so that's usually reasonable (possible).
And in fact it indicates a shared borrow,[1] so both can be active at the same time.
There's nothing preventing some weird implementation, but generally speaking, they will have separate state and not interfere with each other. So long as they implement Send, you can send them to different threads and iterate them independently.
Yes. That's the whole point of iterators. If iteration state weren't decoupled from collections, then there would be no need for separate iterators.
As long as they do not result in shared mutability (i.e., the iterators are read-only), then yes.
But the best part of Rust is: you can just try it! If it violated thread safety, then it wouldn't even compile. So as long as it compiles, you know it's thread-safe.
This couldn't really be done well (and would be highly undesirable). This would mean that advancing a would silently advance b (and vice versa). Rust generally tries to fight against shared mutability, since shared mutability is an ample source of logic and safety bugs.
In general, when two things are separate in this language, there won't be spooky action-at-a-distance between them. This is one of the cornerstones of the design of this language.
I don't think OP is asking about that; I'm pretty sure the question is about the iteration state — which is necessarily different from the contents of the data structure, even in the case of an owning iterator.
Lifetimes on the Iterator trait prevent collections from returning references to their own elements. This is a hard guarantee enforced at compile time for all iterators. By-reference iterators are forced to always be a separate object.
Iterators are never meant to be implemented on the collection directly, and you can rely on this. Very often it's literally impossible to implement iterator on the collections, and even in cases where it could be doable technically (when returning owned elements by draining the collection empty), even that is not implemented by convention, and consuming/draining iterators are still always a separate type.
What I actually meant is that the iteration state is necessarily another, additional piece of information.
Even if you were to implement Iterator directly on a Vec or HashMap type itself, you would still somehow need to keep track of the next element. So the Vec or HashMap would, for example, need an additional index or pointer that would point to the next item. I don't think there's any way around that, whether or not you store that extra pointer in the same struct or a separate one.
(Realistically speaking – let's try to stick to O(n) and not start shifting all items to the front upon every call to next :D)
Thanks, that's good information. Some languages track the iterator right on the object for some reason (the iterator is set up on the class's state and moves an index, modifying the class while iterating can be bad, etc.) so I wasn't sure.
Sometimes I write code for months before it's in a state where it can be compiled, especially in a new language Weird thing with Rust is I did that with something relatively complex and I'm not a great programmer and I got no warnings and no errors first try…not sure if that's encouraging or terrifying.