Skip to content

Diagnostics around implementing mutable iterators should be improved #107031

Open
@mejrs

Description

@mejrs

Recently I have seen a lot of (new) users struggle with code like this:

pub struct IterMut<'a, T> {
    inner: &'a mut Vec<T>,
    index: usize,
}

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<Self::Item> {
        let item = self.inner.get_mut(self.index);
        self.index += 1;
        item
    }
}

This doesn't compile, of course:

error: lifetime may not live long enough
  --> src/lib.rs:12:9
   |
6  | impl<'a, T> Iterator for IterMut<'a, T> {
   |      -- lifetime `'a` defined here
...
9  |     fn next(&mut self) -> Option<Self::Item> {
   |             - let's call the lifetime of this reference `'1`
...
12 |         item
   |         ^^^^ associated function was supposed to return data with lifetime `'a` 
but it is returning data with lifetime `'1`

This is often seen as a shortcoming of the language, as a pattern that is correct but the compiler doesn't understand - which in this case, is not untrue. But in many impls do involve overlapping mutable references, which would be unsound.

As for improvements, I have some ideas:

  • Reassure the user that they really do need that lifetime, and that they didn't put a wrong lifetime somewhere. Say something like "The contract of Iterator::next demands an item with at least the lifetime 'a"
  • Explain splitting borrows. In my experience this clicks well, and users are often surprised they don't need to reach for unsafe code. We should explain this in-line or link to the nomicon.
  • Explain why the iterator trait has the lifetime requirements that it has ,e.g. "the_iter.collect(); is a thing"

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions