I think I understand how iterators will compile in the simple case using for...in. However I'm unsure about how to think about iterators that get passed around functions, which then add their own iterators. Will this all compile down to a simple loop at the point where it's consumed? By "simple" I mean equivalent to manually writing out the loop instead of using iterators.
Are there any inefficiencies or gotchas I should be aware of?
If you pass iterators across functions as objects of either 1/exactly the right type, 2/impl Iterator opaque type or 3/<T: Iterator> generic parameters, then the performance characteristics should be basically equivalent to using them directly, barring easily-resolved inlining mishaps.
If you use trait objects, however (dyn Trait or the old &Trait/Box<Trait> equivalent), you should expect some loss of optimization due to dynamic dispatch. Basically, the trait object will act as an opaque optimization barrier which the compiler is usually unable to peek through.