Explain why error occurred and solve it

struct Count {
    data: Vec<u32>
}

struct RefMutCountIter<'a> {
    count: &'a mut Count,
    index: usize,
}

impl Count {


    fn iter_mut(& mut self) -> RefMutCountIter {
        RefMutCountIter {
            count: self,
            index: 0,
        }
    }
}


impl<'a> Iterator for RefMutCountIter<'a>{
    type Item = &'a mut u32;

    fn next(& mut self) -> Option<Self::Item>{
        let result = self.count.data.get_mut(self.index);
        if result.is_some() {
            self.index += 1;
        }
        result
    }
}

fn main() {
    let mut count = Count {
        data: vec![100; 10]
    };

    for i in count.iter_mut() {
        println!("{}", *i);
    }
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error: lifetime may not live long enough
  --> src/main.rs:30:9
   |
22 | impl<'a> Iterator for RefMutCountIter<'a>{
   |      -- lifetime `'a` defined here
...
25 |     fn next(& mut self) -> Option<Self::Item>{
   |             - let's call the lifetime of this reference `'1`
...
30 |         result
   |         ^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`

error: could not compile `playground` (bin "playground") due to 1 previous error

Why return reference to 4 bytes? Copy them instead.

impl<'a> Iterator for RefMutCountIter<'a> {
    type Item = u32;

    fn next(&'_ mut self) -> Option<Self::Item> {
        self.count.data.get(self.index).map(|x| {
            self.index += 1;
            *x
        })
    }
}

What are you trying to achieve? The standard library already does provide a mutable-reference iterator for vec/slice.

It's admittedly not such an easy task to do this yourself with Rust's borrow checker - but also it's a very very common question, so I'm sure you can easily find good existing explanation on the topic of mutable iterator implementations for data structures - in particular for Vec and slices - in Rust, online and even on this forum :wink:

Just learning how lifetimes work

So pls explain how to solve

Lifetimes work in a way to ensure soundness w. r. t. Rust's memory guarantees. The borrow checker however isn't magically able to understand any program logic, beyond what basic control flow, as well as information expressed through lifetimes in type signatures can expose. Your code does however rely on subtleties of index calculation to ensure not more than one mutable reference to the same vec position is ever returned from your iterator.

Rust's mutable references type does guarantee no two (active) mutable references to the same place may coexist, and Rust's Iterator interface does opt to allow the user to keep around all items from the iterator and process them together - so having two mutable references to the same entry be returned as separate iterator items would indeed break assumptions relevant for soundness.

It is therefore unsurprising that your code as-is cannot possibly successfully compile. You'll need to involve unsafe code, or restructure against existing APIs for splitting borrows on slices. As for how that would go in detail, i. e. answering your question of:

I'll say, in my opinion, we don't really need to go into any more detail in this thread, unless you have way more specific questions, and show what explanations you've already looked at, and what's perhaps still unclear to you. As I have mentioned before, you're exploring about a very commonly asked topic and should be able to find plenty of existing answers in how to do it, easily.

3 Likes

error: lifetime may not live long enough

so

How to tell lifetime may be live long enough

:backhand_index_pointing_down:t2:

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.