How to implement an iterator that produces mutable items?

I am trying to implement an iterator, that iterates through a collection and produces mutable items (or mutable references) of this collection.
It is something, that I'd like to bring into jsonpath library (GitHub - greyblake/jsonpath-rs: JSONPath for Rust).

However I found very challenging to implement an iterator like this. I've decided to start small. I am trying to implement an iterator of mutable items that iterates through a vector of strings.

use std::marker;

struct IterMut<'a, T: 'a> {
    parts: Vec<String>,
    index: usize,
    _marker: marker::PhantomData<&'a mut T>
}

impl<'a, T> IterMut<'a, T> {
    fn new(parts: Vec<String>) -> Self {
        Self { parts, index: 0, _marker: marker::PhantomData }
    }
}

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

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

fn main() {
    let parts = vec![
        "aaa".to_owned(),
        "bbb".to_owned(),
    ];

    let iter = IterMut::new(parts);

for part in iter {
    part.push('!');
    println!("-> {}", part);
}

}

I am getting the following errors:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/main.rs:40:19
   |
40 |         let res = self.parts.get_mut(self.index);
   |                   ^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 39:5...
  --> src/main.rs:39:5
   |
39 | /     fn next(&mut self) -> Option<Self::Item> {
40 | |         let res = self.parts.get_mut(self.index);
41 | |         self.index += 1;
42 | |         res
43 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:40:19
   |
40 |         let res = self.parts.get_mut(self.index);
   |                   ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 36:6...
  --> src/main.rs:36:6
   |
36 | impl<'a, T> Iterator for IterMut<'a, T> {
   |      ^^
   = note: ...so that the types are compatible:
           expected std::iter::Iterator
              found std::iter::Iterator

error: aborting due to previous error

For more information about this error, try `rustc --explain E0495`.
error: Could not compile `it`.

Any ideas how to do this right?
Thanks in advanced.

I would build off of the slice's iter_mut. So instead of storing a Vec, store a std::slice::IterMut. Then you can call next when you implement Iterator. You can get a slice iterator by calling vec.iter_mut()

4 Likes

Thanks for an idea. I assume this may work, but it would not solve my end goal. I'd like to be able implement such iterator myself. The end goal is to have an iterator that would iterate over nested serde::Json structure, instead of Vec<String>.
However I gave me idea: I should probably look into Rust std lib source code, to see how iter_mut is implemented. It looks like it is using unsafe ...

Yes, implementing IterMut will almost always use unsafe.

1 Like

Not really, [T]::iter_mut() is written in totally safe Rust. The key here is [T]::split_mut() which split a &mut [T] into two disjoint slice in safe context. So you can simply split it one by one, until it gets empty.

1 Like

You could implement slice::IterMut that way, but the real one uses pointers:
https://github.com/rust-lang/rust/blob/a73ecb3d9c432f8f53117b1a6b6c209dc802dee7/src/libcore/slice/mod.rs#L3078-L3092

3 Likes

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