Learn Rust With Entirely Too Many Linked Lists
14

IterMut

IterMut looks like Iter with &mut everywhere. It is not. Mutable references are not Copy — at any moment there is exactly one. To advance the cursor we have to move the current &mut Node out, take its next field, and put the new reference back. The tool for that is Option::take.

  1. Type and constructor mirror Iter. as_deref_mut is the &mut counterpart of as_deref: Option<Box<Node<T>>> -> Option<&mut Node<T>>.
    pub struct IterMut<'a, T> {
        next: Option<&'a mut Node<T>>,
    }
    
    impl<T> List<T> {
        pub fn iter_mut(&mut self) -> IterMut<'_, T> {
            IterMut { next: self.head.as_deref_mut() }
        }
    }
  2. The body of next cannot read self.next and then assign to it — the read would be a copy of a &mut, which is forbidden. Option::take swaps self.next with None, handing us the inner &mut Node by value. We then split it into &mut node.elem (returned) and node.next.as_deref_mut() (stored back into self.next).
    impl<'a, T> Iterator for IterMut<'a, T> {
        type Item = &'a mut T;
        fn next(&mut self) -> Option<&'a mut T> {
            self.next.take().map(|node| {
                self.next = node.next.as_deref_mut();
                &mut node.elem
            })
        }
    }
  3. Two things make this safe. First, each yielded &mut T borrows from a different node, so the references handed out across calls don't alias. Second, we only ever hold one cursor at a time — the take enforces that. The compiler verifies all of this without an unsafe keyword.
    let mut list = List::new();
    list.push(1); list.push(2); list.push(3);
    for v in list.iter_mut() { *v *= 10; }
    assert_eq!(list.pop(), Some(30));
    assert_eq!(list.pop(), Some(20));
    assert_eq!(list.pop(), Some(10));