1 year ago

#375268

test-img

SupaGu

How to resolve lifetime iterator impl error

I have a data structure called 'FluidSim' which is a bunch of cells. Think of a 2d grid (x,y) which then holds a vector of data for each cell (grid location).

I want to make an iterator which lets me iterator over this grid (and in future I want to be able to skip empty cells).

Additionally I want some additional functionality on the iterator to help get data out of the data structure (or put data into it).

get_cell_index is an example function where I am trying to do that.

I'm having trouble getting the Iterator impl working:


struct FluidSimIterator<'a> {
    fluid_sim: &'a FluidSim,
    ix: usize,
    iy: usize,
    skip_empty_buckets: bool
}

impl FluidSimIterator<'_> {
    pub fn get_cell_index(&self) -> usize {
        return self.ix + (self.fluid_sim.bucket_size * self.iy);
    }
}

impl FluidSim {
    pub fn iter(&self) -> FluidSimIterator {
        FluidSimIterator{
            fluid_sim: self,
            ix: 0,
            iy: 0,
            skip_empty_buckets: true
        }
    }
}

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

    fn next(&mut self) -> Option<Self::Item> {
        self.ix += 1;
        Some(self)
    }
}

The errors I am seeing are:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> physics/src/fluid_sim.rs:666:9
    |
666 |         Some(self)
    |         ^^^^^^^^^^
    |
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
   --> physics/src/fluid_sim.rs:664:13
    |
664 |     fn next(&mut self) -> Option<Self::Item> {
    |             ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
   --> physics/src/fluid_sim.rs:666:14
    |
666 |         Some(self)
    |              ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
   --> physics/src/fluid_sim.rs:661:6
    |
661 | impl<'a> Iterator for FluidSimIterator<'a> {
    |      ^^
note: ...so that the types are compatible
   --> physics/src/fluid_sim.rs:664:46
    |
664 |       fn next(&mut self) -> Option<Self::Item> {
    |  ______________________________________________^
665 | |         self.ix += 1;
666 | |         Some(self)
667 | |     }
    | |_____^
    = note: expected `<FluidSimIterator<'a> as Iterator>`
               found `<FluidSimIterator<'_> as Iterator>`


error: aborting due to previous error


For more information about this error, try `rustc --explain E0495`.

full source code is here: https://github.com/bit-shift-io/fluidic-space/blob/main/crates/physics/src/fluid_sim.rs with this above snippet right at the bottom of the file.

Seems it is something to do with lifetimes which I am still wrapping my head around. SO not exactly sure what the error is saying or how to resolve it.

EDIT:

I managed to get working how I want it to, although I'm not sure how 'ideal' the solution is:


pub struct Iter<'a> {
    pub fluid_sim: &'a FluidSim,
    pub ix: isize,
    pub iy: isize
}

impl<'a> Iterator for Iter<'a> {
    type Item = Iter<'a>; //Cell<'a>; //&'a Cell;

    fn next(&mut self) -> Option<Self::Item> {
        self.ix += 1;
        if self.ix >= self.fluid_sim.x_size as isize {
            self.iy += 1;
            if self.iy >= self.fluid_sim.y_size as isize {
                return None
            }

            self.ix = 0;
        }

        let dup = Iter{
            fluid_sim: self.fluid_sim,
            ix: self.ix,
            iy: self.iy
        };
        Some(dup)
    }
}

impl FluidSim {
    pub fn iter(&self) -> Iter {
        Iter {
            fluid_sim: &self,
            ix: -1,
            iy: 0
        }
    }
}

And a basic example of the usage looks like:

let mut h1 = FluidSim::new(3, 3);

for cell in h1.iter() {
        println!("x: {:?}, y: {:?}", cell.ix, cell.iy)
}

gives me the following output:

x: 0, y: 0
x: 1, y: 0
x: 2, y: 0
x: 3, y: 0
x: 0, y: 1
x: 1, y: 1
x: 2, y: 1
x: 3, y: 1
x: 0, y: 2
x: 1, y: 2
x: 2, y: 2
x: 3, y: 2
x: 0, y: 3
x: 1, y: 3
x: 2, y: 3
x: 3, y: 3

So I can now add other functions on my Iter struct to read and write into the correct cell of my fluid_sim struct.

rust

iterator

0 Answers

Your Answer

Accepted video resources