From ce3d60476a9f307e71c2928ab575cfced6831187 Mon Sep 17 00:00:00 2001 From: William Chargin Date: Mon, 23 Nov 2020 11:59:42 -0800 Subject: [PATCH 1/2] std::iter: document iteration over `&T` and `&mut T` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 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 --- library/core/src/iter/mod.rs | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 072373c00f679..2ace734fb0c7d 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -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` or `HashMap` 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 From 6edc90a3e21a786bfe1e0a6bca28e8e687064554 Mon Sep 17 00:00:00 2001 From: William Chargin Date: Mon, 23 Nov 2020 15:46:13 -0800 Subject: [PATCH 2/2] [update patch] wchargin-branch: doc-iter-by-reference wchargin-source: e4069ac9a9d73860467cea74cf3ae1605af37d74 --- library/core/src/iter/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 2ace734fb0c7d..3e74637b49f1c 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -243,11 +243,13 @@ //! ``` //! //! While many collections offer `iter()`, not all offer `iter_mut()`. For -//! example, mutating the keys of a `HashSet` or `HashMap` could put -//! the collection into an inconsistent state if the key hashes change, so these -//! collections only offer `iter()`. +//! example, mutating the keys of a [`HashSet`] or [`HashMap`] could +//! put the collection into an inconsistent state if the key hashes change, so +//! these collections only offer `iter()`. //! //! [`into_iter()`]: IntoIterator::into_iter +//! [`HashSet`]: ../../std/collections/struct.HashSet.html +//! [`HashMap`]: ../../std/collections/struct.HashMap.html //! //! # Adapters //!