Lifetime may not live long enough custom impl iterator

struct A<'a> {
    a: &'a mut [u8]
}

impl<'a> Iterator for A<'a> {
    type Item=&'a mut u8;

    fn next(&mut self) -> Option<Self::Item> {
        Some(&mut self.a[0])
    }
}
error: lifetime may not live long enough
 --> src/next_lifetime.rs:9:9
  |
5 | impl<'a> Iterator for A<'a> {
  |      -- lifetime `'a` defined here
...
8 |     fn next(&mut self) -> Option<Self::Item> {
  |             - let's call the lifetime of this reference `'1`
9 |         Some(&mut self.a[0])
  |         ^^^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`

How could I solve this error?

Is it only way to use raw pointer with unsafe ?

1 Like

Think about what would happen if you .collect() this iterator: you'd have multiple mutable references to the same place. So, the code you posted must not compile because it is unsound.

It won't compile if you add a proper incrementing index, either; not because it would be unsound but because the compiler isn't clever enough to determine that it is sound.

How could I solve this error?

Write your iterator as a wrapper around the built-in std::slice::IterMut.

Is it only way to use raw pointer with unsafe ?

The right thing to do is to make use of the std code that has already been written for you. That will be the safe and efficient option. Keep the total amount of unsafe code in the world small. If you really wanted to write a mutable slice iterator from scratch, you could use raw pointers — but it's actually possible to make a slice iterator with careful use of pattern matching.

impl<'a> Iterator for A<'a> {
    type Item = &'a mut u8;

    fn next(&mut self) -> Option<Self::Item> {
        if let [item, rest @ ..] = std::mem::take(&mut self.a) {
            self.a = rest;
            Some(item)
        } else {
            None
        }
    }
}

(This is also available as a function under the name std::slice::split_first_mut.)

5 Likes

I have an example walking through the creation of such an iterator in slow motion here. (One of) the end result(s) is the same as @kpreid's example. The failing versions examined along the way hopefully illustrate why the naive approach can't work.

1 Like

But you cannot get a &'long mut U through dereferencing a &'short mut &'long mut U .

Could be the following an example explaning it?

struct B<'a>(&'a mut String);

impl<'a> B<'a> {
    fn some_mutating_method(&mut self) -> &'a mut String {
        &mut self.0
    }
}

fn ssss() {
    let mut s = String::from("Understaning Lifetime...");

    let mut a = B(&mut s);

    let c = a.some_mutating_method();
    
    s.push_str("2");

    c.push_str("1");

    
}

Is the reason that I have two mutable references of an object?

If it is not correct, could you give an example?

Yes, that's the idea. &mut _ are exclusive references. I rewrote your playground a bit to try and spell it out more.

1 Like

Thanks

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.