Rust DISCUSSION

What is the difference between iter(), iter_mut() and into_iter() on a Rust Vec?

Started by jorge Rust iteratorsinto_iteriter_mutfor loop ownershipmoved value
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

What is the difference between iter(), iter_mut() and into_iter() on a Rust Vec?

jorge Rust Forum
#1

I loop over a vector of sensor readings with for r in readings { ... } and then try to use readings again after the loop. The compiler reports a borrow of a moved value and suggests iterating over &readings. With readings.iter() it compiles, but then the closure in .map(|r| ...) receives a reference instead of a value and I end up sprinkling * around.

What exactly do iter(), iter_mut() and into_iter() yield, and which one does a plain for loop use?

Community replies 4

Re: What is the difference between iter(), iter_mut() and into_iter() on a Rust Vec?

#2

For a Vec<T>: iter() borrows the vector and yields &T; iter_mut() borrows it mutably and yields &mut T; into_iter() takes the vector by value, consumes it and yields T.

for x in c is shorthand for calling IntoIterator::into_iter(c). So for r in readings moves the vector into the loop, and it is gone afterwards. for r in &readings calls into_iter on a &Vec<T>, which is implemented as readings.iter(), and for r in &mut readings is the same as iter_mut().

Re: What is the difference between iter(), iter_mut() and into_iter() on a Rust Vec?

#3

Choose by what the loop body needs. Read only: for r in &readings. Modify in place: for r in &mut readings { *r *= 2.0; }. Hand the elements on without cloning: let scaled: Vec<f32> = readings.into_iter().map(|r| r * 0.5).collect();.

For Copy types such as f32 or u16 the references from iter() are a nuisance. Add .copied() to get values, readings.iter().copied().map(|r| r * 0.5), or destructure in the closure with .map(|&r| r * 0.5). Arithmetic operators are implemented for references to primitives, so r * 0.5 compiles with r: &f32, but a comparison such as r > 1.0 does not, and that is where the stray * come from.

Re: What is the difference between iter(), iter_mut() and into_iter() on a Rust Vec?

#4

A subtle point: what the method call into_iter() yields depends on the type it is called on. If v is a &Vec<T>, a function parameter for example, v.into_iter() yields &T, not T, because it is the reference that is consumed.

Arrays had a historical quirk here. Before the 2021 edition, [1, 2, 3].into_iter() yielded references; from edition 2021 onwards it yields values. When the item type in a long chain is unclear, a quick trick is to write let x: () = it.next(); and read the actual type out of the compiler error.

Re: What is the difference between iter(), iter_mut() and into_iter() on a Rust Vec?

#5

There is no performance reason to prefer one over another. All three compile to simple pointer-stepping loops, and a chain such as readings.iter().map(|r| r * 2.0).sum::<f32>() is normally optimised as well as an indexed loop, often better, because readings[i] may need a bounds check on every access and the iterator does not.

Remember that iterator adaptors are lazy. readings.iter().map(|r| r * 2.0); on its own does nothing, and the compiler warns that the result is unused; it needs a consumer such as collect(), sum() or a for loop. To remove elements while scanning, use readings.retain(|r| *r > 0.0) rather than juggling indexes.

TEP COMMUNITY