Skip to content

Commit

Permalink
std::iter: document iteration over &T and &mut T
Browse files Browse the repository at this point in the history
A colleague of mine is new to Rust, and mentioned that it was “slightly
confusing” to figure out what `&mut` does in iterating over `&mut foo`:

```rust
for value in &mut self.my_vec {
    // ...
}
```

My colleague had read the `std::iter` docs and not found the answer
there. There is a brief section at the top about “the three forms of
iteration”, which mentions `iter_mut`, but it doesn’t cover the purpose
of `&mut coll` for a collection `coll`. This patch adds an explanatory
section to the docs. I opted to create a new section so that it can
appear after the note that `impl<I: Iterator> IntoIterator for I`, and
it’s nice for the existing “three forms of iteration” to appear near the
top.

Implementation note: I haven’t linkified the references to `HashSet` and
`HashMap`, since those are in `std` and these docs are in `core`;
linkifying them gave an “unresolved link” rustdoc error.

Test Plan:
Ran `./x.py doc library/core`, and the result looked good. Manually
copy-pasted the two doctests into the playground and ran them.

wchargin-branch: doc-iter-by-reference
wchargin-source: 0f35369a8a735868621166608797744e97536792
  • Loading branch information
wchargin committed Nov 23, 2020
1 parent 40cf721 commit ce3d604
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions library/core/src/iter/mod.rs
Expand Up @@ -206,6 +206,49 @@
//! 2. If you're creating a collection, implementing [`IntoIterator`] for it
//! will allow your collection to be used with the `for` loop.
//!
//! # Iterating by reference
//!
//! Since [`into_iter()`] takes `self` by value, using a `for` loop to iterate
//! over a collection consumes that collection. Often, you may want to iterate
//! over a collection without consuming it. Many collections offer methods that
//! provide iterators over references, conventionally called `iter()` and
//! `iter_mut()` respectively:
//!
//! ```
//! let mut values = vec![41];
//! for x in values.iter_mut() {
//! *x += 1;
//! }
//! for x in values.iter() {
//! assert_eq!(*x, 42);
//! }
//! assert_eq!(values.len(), 1); // `values` is still owned by this function.
//! ```
//!
//! If a collection type `C` provides `iter()`, it usually also implements
//! `IntoIterator` for `&C`, with an implementation that just calls `iter()`.
//! Likewise, a collection `C` that provides `iter_mut()` generally implements
//! `IntoIterator` for `&mut C` by delegating to `iter_mut()`. This enables a
//! convenient shorthand:
//!
//! ```
//! let mut values = vec![41];
//! for x in &mut values { // same as `values.iter_mut()`
//! *x += 1;
//! }
//! for x in &values { // same as `values.iter()`
//! assert_eq!(*x, 42);
//! }
//! assert_eq!(values.len(), 1);
//! ```
//!
//! While many collections offer `iter()`, not all offer `iter_mut()`. For
//! example, mutating the keys of a `HashSet<T>` or `HashMap<K, V>` could put
//! the collection into an inconsistent state if the key hashes change, so these
//! collections only offer `iter()`.
//!
//! [`into_iter()`]: IntoIterator::into_iter
//!
//! # Adapters
//!
//! Functions which take an [`Iterator`] and return another [`Iterator`] are
Expand Down

0 comments on commit ce3d604

Please sign in to comment.