Unexpected lifetime does not match

hi everybody,

I'm learning rust recently and writing some code to make sure I have a proper understanding of the concepts in Rust, I encountered something that puzzled me about lifetime, here is the code:

#[derive(Debug)]
struct C(Vec<u32>);

impl C {
    fn iter<'a>(&'a self) -> CIter<'a> {
        CIter {
            c: self,
            index: 0,
        }
    }
}

struct CIter <'a> {
    c: &'a C,
    index: usize,
}

impl <'a> Iterator for CIter<'a> {
    type Item = &'a u32;
    fn next(self:&mut CIter<'a>) -> Option<&'a u32> {
        if self.index >= self.c.0.len() {
            return None;
        }
        let next = &self.c.0[self.index];
        self.index += 1;
        return Some(next);
    }
}

fn test_iter() {
    let c = C(vec!(1,2,3));
    for x in c.iter() {
        println!("{:?}", *x);
    }
    let mut iter = c.iter();
    let _ = iter.next();
    println!("second element of c:{:?}", *iter.next().unwrap());
}

fn main() {
    test_iter();
}

all above works fine, and then I'm trying to write a mutable Iterator and i got some compile error.

#[derive(Debug)]
struct C(Vec<u32>);

impl C {
    fn iter<'a>(&'a self) -> CIter<'a> {
        CIter {
            c: self,
            index: 0,
        }
    }
    fn iter_mut<'a>(&'a mut self) -> CIterMut<'a> {
        CIterMut {
            c: self,
            index: 0,
        }
    }
}

struct CIter <'a> {
    c: &'a C,
    index: usize,
}

impl <'a> Iterator for CIter<'a> {
    type Item = &'a u32;
    fn next(self:&mut CIter<'a>) -> Option<&'a u32> {
        if self.index >= self.c.0.len() {
            return None;
        }
        let next = &self.c.0[self.index];
        self.index += 1;
        return Some(next);
    }
}

struct CIterMut <'a> {
    c: &'a mut C,
    index: usize,
}

impl <'a> Iterator for CIterMut<'a> {
    type Item = &'a mut u32;
    fn next(self:&mut CIterMut<'a>) -> Option<&'a mut u32> {
        if self.index >= self.c.0.len() {
            return None;
        }
        let next = &mut self.c.0[self.index];
        self.index += 1;
        return Some(next);
    }
}

fn test_iter() {
    let c = C(vec!(1,2,3));
    for x in c.iter() {
        println!("{:?}", *x);
    }
    let mut iter = c.iter();
    let _ = iter.next();
    println!("second element of c:{:?}", *iter.next().unwrap());
}

fn test_iter_mut() {
    let c = C(vec!(1,2,3));
    for x in c.iter_mut() {
        println!("{:?}", *x);
    }
    let mut iter = c.iter_mut();
    let _ = iter.next();
    let r = iter.next().unwrap();
    *r = 5;
    println!("c: {:?}", c);
}

fn main() {
    test_iter();
    test_iter_mut();
}

finaly i got a compile error :

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
 --> src/main.rs:47:25
   |
47 |         let next = &mut self.c.0[self.index];
   |                         ^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 43:5...
  --> src/main.rs:43:5
   |
43 | /     fn next(self:&mut CIterMut<'a>) -> Option<&'a mut u32> {
44 | |         if self.index >= self.c.0.len() {
45 | |             return None;
46 | |         }
...  |
49 | |         return Some(next);
50 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:47:25
   |
47 |         let next = &mut self.c.0[self.index];
   |                         ^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 41:7...
  --> src/main.rs:41:7
   |
41 | impl <'a> Iterator for CIterMut<'a> {
   |       ^^
note: ...so that the types are compatible
  --> src/main.rs:43:60
   |
43 |       fn next(self:&mut CIterMut<'a>) -> Option<&'a mut u32> {
   |  ____________________________________________________________^
44 | |         if self.index >= self.c.0.len() {
45 | |             return None;
46 | |         }
...  |
49 | |         return Some(next);
50 | |     }
   | |_____^
   = note: expected  `std::option::Option<&'a mut u32>`
              found  `std::option::Option<&mut u32>`

It confuses me. All difference between CIter and CIterMut is the reference is mutalbe or immutable, the lifetime relation are all the same, but the compile error message told me the lifetime is wrong, why? Is there something I missed?
Thank you.

Mutable references must be unique. In this case the &mut C inside the iterator overlaps with the returned mutable reference without leaving the Iterator borrowed for the duration of the returned mutable reference (it borrows from the C you created the Iterator from, not the Iterator itself). This is not allowed due to the uniqueness rule for mutable references.

The typical solution is to just store a slice in the Iterator instead, which avoids the overlap issue if you reduce the size of the slice so it does not overlap with returned references.

1 Like

Oh I see! your are right! Thank you so much!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.