Learn Rust With Entirely Too Many Linked Lists
13

Iter

Iter walks the list without consuming it, yielding &T. The iterator doesn't own anything — it holds a reference to the current node. That reference has to live as long as the borrow of the list it came from, so a lifetime appears in the type for the first time.

  1. Iter<'a, T> carries Option<&'a Node<T>>. 'a is the lifetime of the borrow of the list — the iterator can't outlive the list it's walking. The constructor takes &'a self and uses as_deref to peel the Box off the head.
    pub struct Iter<'a, T> {
        next: Option<&'a Node<T>>,
    }
    
    impl<T> List<T> {
        pub fn iter(&self) -> Iter<'_, T> {
            Iter { next: self.head.as_deref() }
        }
    }
  2. Each next returns the current node's element and advances the cursor by walking node.next.as_deref() to the next Option<&Node<T>>. Shared references can be copied freely, so this is a one-line state update.
    impl<'a, T> Iterator for Iter<'a, T> {
        type Item = &'a T;
        fn next(&mut self) -> Option<&'a T> {
            self.next.map(|node| {
                self.next = node.next.as_deref();
                &node.elem
            })
        }
    }
  3. The '_ in iter(&self) -> Iter<'_, T> is the elided lifetime — the compiler infers it from &self. Spelling it out as <'a>(&'a self) -> Iter<'a, T> is equivalent.
    let mut list = List::new();
    list.push(1); list.push(2); list.push(3);
    let mut it = list.iter();
    assert_eq!(it.next(), Some(&3));
    assert_eq!(it.next(), Some(&2));
    assert_eq!(it.next(), Some(&1));
    assert_eq!(it.next(), None);
    // list is still alive here.