Conflicting lifetime when implementing iterator

I’m having some trouble using a iterator to wrap a struct method.

struct Element<'a>(&'a str);

struct IterStruct<'a> {
    name: &'a str,
}

impl<'a> IterStruct<'a> {
    fn name(&mut self) -> Option<Element> {
        Some(Element(self.name))
    }
}

impl<'a> Iterator for IterStruct<'a> {
    type Item = Element<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.name()
    }
}

It fails to compile with the following error:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/lib.rs:16:14
   |
16 |         self.name()
   |              ^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 15:5...
  --> src/lib.rs:15:5
   |
15 | /     fn next(&mut self) -> Option<Self::Item> {
16 | |         self.name()
17 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/lib.rs:16:9
   |
16 |         self.name()
   |         ^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 13:6...
  --> src/lib.rs:13:6
   |
13 | impl<'a> Iterator for IterStruct<'a> {
   |      ^^
   = note: ...so that the types are compatible:
           expected std::iter::Iterator
              found std::iter::Iterator

I’m not really sure what is going on here, why does the code compile if I leave out the iterator block, but fails when I implement it?

(Playground)

change name to

    fn name(&mut self) -> Option<Element<'a>> {
        Some(Element(self.name))
    }

This will make the lifetime of the Element to the lifetime of the IterStruct. Right now the lifetime of the Element is being bound to the mutable reference, due to the lifetime elison rules, which is too small.

I see, that worked!

Trying to see if my understanding is correct here, this is what it would have looked like without lifetime elision:

fn name<'b>(&'b mut self) -> Option<Element<'b>> {
    Some(Element(self.name))
}

My understanding here is that the conflicting lifetimes are between the

  • lifetime 'b in Option<Element<'b>> in the return type of the name function, and
  • lifetime 'a of in Self::Item in the return type of the next function

Correct me if I’m wrong, it seems like the problem here is that the lifetime 'b would be just a anonymous (? not sure of the correct terminology here) lifetime that has no relationship with 'a that specifies how long the Element have to live for, and because of this, the compiler is unable to proceed?

Yes, that is the lifetime desugaring.

Not exactly, 'b is guaranteed to be smaller than or equal to 'a. This is because a mutable reference must live no longer than what it refers to.

1 Like

Thanks a lot, that really helped!