How to resolve lifetime iterator impl error [duplicate] - rust

This question already has answers here:
How do I write an iterator that returns references to itself?
(4 answers)
How can I create my own data structure with an iterator that returns mutable references?
(1 answer)
Closed 11 months ago.
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.

Related

Implement mutable enumeration method on 2D grid

I have a mostly working implementation of a 2D grid in rust:
use itertools::Itertools;
#[derive(Debug)]
pub struct Grid<T> {
width: usize,
height: usize,
items: Vec<T>,
}
impl<T> Grid<T> {
pub fn new(width: usize, height: usize, initializer: impl Fn() -> T) -> Self {
Self {
width,
height,
items: (0..height * width).map(|_| initializer()).collect(),
}
}
pub fn width(&self) -> usize {
self.width
}
pub fn height(&self) -> usize {
self.height
}
pub fn size(&self) -> usize {
self.width * self.height
}
pub fn get(&self, x: usize, y: usize) -> Result<&T, &str> {
if self.on_grid(x as isize, y as isize) {
Ok(&self.items[self.coordinate_to_index(x, y)])
} else {
Err("coordinate not on grid")
}
}
pub fn get_mut(&mut self, x: usize, y: usize) -> Result<&mut T, &str> {
if self.on_grid(x as isize, y as isize) {
let index = self.coordinate_to_index(x, y);
Ok(&mut self.items[index])
} else {
Err("coordinate not on grid")
}
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.items.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.items.iter_mut()
}
pub fn enumerate(&self) -> impl Iterator<Item = (usize, usize, &T)> {
self.items.iter().enumerate().map(|(index, item)| {
let (x, y) = self.index_to_coordinate(index);
(x, y, item)
})
}
pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut T)> {
self.items.iter_mut().enumerate().map(move |(index, item)| {
let (x, y) = self.index_to_coordinate(index);
(x, y, item)
})
}
pub fn neighbors(&self, x: usize, y: usize) -> impl Iterator<Item = (usize, usize, &T)> {
self.neighbor_indices(x, y)
.map(|(x, y)| (x, y, &self.items[self.coordinate_to_index(x, y)]))
}
fn coordinate_to_index(&self, x: usize, y: usize) -> usize {
y * self.width + x
}
fn index_to_coordinate(&self, index: usize) -> (usize, usize) {
let x = index % self.width;
let y = (index - x) / self.width;
(x, y)
}
fn neighbor_indices(&self, x: usize, y: usize) -> impl Iterator<Item = (usize, usize)> + '_ {
neighbor_offsets(2)
.map(move |item| (x as isize + item[0], y as isize + item[1]))
.filter(|&(x, y)| self.on_grid(x, y))
.map(|(dx, dy)| (dx as usize, dy as usize))
}
fn on_grid(&self, x: isize, y: isize) -> bool {
0 <= x && x < self.width as isize && 0 <= y && y < self.height as isize
}
}
fn neighbor_offsets(dimension: usize) -> impl Iterator<Item = Vec<isize>> {
(-1..1)
.map(|index| index as isize)
.combinations_with_replacement(dimension)
// skip zero offset
.filter(|items| !items.iter().all(|&item| item == 0))
}
Cargo.toml
[package]
name = "grid"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
itertools = "*"
However, with enumerate_mut() the compilation currently fails with
$ cargo build
Compiling either v1.8.0
Compiling itertools v0.10.5
Compiling grid v0.1.0 (/home/neumann/Projekte/grid)
error[E0505]: cannot move out of `self` because it is borrowed
--> src/lib.rs:64:47
|
63 | pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut T)> {
| - let's call the lifetime of this reference `'1`
64 | self.items.iter_mut().enumerate().map(move |(index, item)| {
| --------------------- ^^^^^^^^^^^^^^^^^^^^ move out of `self` occurs here
| |
| _________borrow of `self.items` occurs here
| |
65 | | let (x, y) = self.index_to_coordinate(index);
| | ---- move occurs due to use in closure
66 | | (x, y, item)
67 | | })
| |__________- returning this value requires that `self.items` is borrowed for `'1`
For more information about this error, try `rustc --explain E0505`.
error: could not compile `grid` due to previous error
warning: build failed, waiting for other jobs to finish...
I know that I could write the method index_to_coordinate() as a pure function, but I would like a solution, that uses the member function similarly to enumerate().
Can this be done? If so, how?
I would like a solution, that uses the member function similarly to enumerate(). Can this be done? If so, how?
It cannot be done. You cannot borrow self while self.items is mutably borrowed. Full stop. Consider this formulation that does work without a member function:
pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut T)> {
self.items.iter_mut().enumerate().map(|(index, item)| {
let x = index % self.width;
let y = (index - x) / self.width;
(x, y, item)
})
}
The only way this works is because of disjoint borrows, i.e. the compiler knows that .width and .height are completely separate objects from .items (and actually this only works in 2021 edition since the disjoint borrows happen both inside and outside the closure). If you use a member of self though, the compiler has lost that knowledge and has to consider that self can access items within that member function, which wouldn't be allowed since the mutable borrow earlier must stay exclusive. Using the member function in the enumerate() method works since immutable borrows can be shared.
Function signatures are the contracts that borrow-checking, type-checking, and type-inference build off of. If the member function has access to self, it must be assumed that it will access all of self. There is no syntax for partial-borrows across a function interface.
It cannot be done at all? Even if I used unsafe?
Even with unsafe, you are not allowed to violate Rust's borrowing rules, so you can't have a &Self while its .items is mutably borrowed. You can access the .width and .height but it must be done via a pointer: *const Self. Here's what that'd look like (tested with Miri on the playground):
pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut T)> {
let this = self as *const Self;
self.items.iter_mut().enumerate().map(move |(index, item)| {
let (x, y) = unsafe { Self::index_to_coordinate(this, index) };
(x, y, item)
})
}
unsafe fn index_to_coordinate(this: *const Self, index: usize) -> (usize, usize) {
let width = *std::ptr::addr_of!((*this).width);
let height = *std::ptr::addr_of!((*this).height);
let x = index % width;
let y = (index - x) / width;
(x, y)
}
However, I hope we can agree that this wouldn't be a member function anymore since it is lacking the self.index_to_coordinate syntax. Of course I'm not advocating you use this at all, it's just a demonstration that even going to the absurd it is not possible.
Just use a free function. :)

Rust mutable iterator problem - how do I fix the 'cannot infer an appropriate lifetime' error?

I'm having a problem with the code below. The immutable iterator works fine, but the mutable one gives me the following error:
cannot infer an appropriate lifetime for lifetime parameter in
function call due to conflicting requirements.
Is it possible to somehow fix this error without using unsafe rust and sticking to the Iterator trait?
Link to the playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ae0b3f4c5c7749b130fe0b0142beb9e7
Code:
struct Collection<T, const S: usize> {
data: Vec<T>
}
struct CollectionIterator<'a, T, const S: usize> {
item_index: usize,
collection: &'a Collection<T, S>
}
struct CollectionIteratorMut<'a, T, const S: usize> {
item_index: usize,
collection: &'a mut Collection<T, S>
}
impl<T: Clone, const S: usize> Collection<T, S> {
fn new(num_items: usize, default_value: T) -> Collection<T, S> {
Collection {
data: vec![default_value; num_items * S]
}
}
fn iter(&self) -> CollectionIterator<T, S> {
CollectionIterator {
item_index: 0,
collection: self
}
}
fn iter_mut(&mut self) -> CollectionIterator<T, S> {
CollectionIterator {
item_index: 0,
collection: self
}
}
}
impl<'a, T, const S: usize> Iterator for CollectionIterator<'a, T, S> {
type Item = &'a [T];
fn next(&mut self) -> Option<Self::Item> {
if self.item_index < self.collection.data.len() {
self.item_index += S;
Some(&self.collection.data[self.item_index - S .. self.item_index])
} else {
None
}
}
}
impl<'a, T, const S: usize> Iterator for CollectionIteratorMut<'a, T, S> {
type Item = &'a mut [T];
fn next(&mut self) -> Option<Self::Item> {
if self.item_index < self.collection.data.len() {
self.item_index += S;
Some(&mut self.collection.data[self.item_index - S .. self.item_index])
} else {
None
}
}
}
fn main() {
let mut c: Collection<f64, 3> = Collection::new(5, 0.0);
for x in c.iter_mut() {
x[0] = 100.0;
}
for x in c.iter() {
println!("{} {} {}", x[0], x[1], x[2]);
}
}
Error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:52:23
|
52 | Some(&mut self.collection.data[self.item_index - S .. self.item_index])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 49:13...
--> src/main.rs:49:13
|
49 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:52:23
|
52 | Some(&mut self.collection.data[self.item_index - S .. self.item_index])
| ^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 47:6...
--> src/main.rs:47:6
|
47 | impl<'a, T, const S: usize> Iterator for CollectionIteratorMut<'a, T, S> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:49:46
|
49 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
50 | | if self.item_index < self.collection.data.len() {
51 | | self.item_index += S;
52 | | Some(&mut self.collection.data[self.item_index - S .. self.item_index])
... |
55 | | }
56 | | }
| |_____^
= note: expected `Iterator`
found `Iterator`
fn next(&mut self) -> Option<Self::Item> {
if self.item_index < self.collection.data.len() {
self.item_index += S;
Some(&mut self.collection.data[self.item_index - S .. self.item_index])
} else {
None
}
}
You have written code that will produce a series of mutable references to different parts of self.collection. But the compiler (borrow checker) does not do any analysis of the index arithmetic to determine that they are in fact non-overlapping. So, this code is rejected. In general, iterators producing mutable references into a collection cannot be written without unsafe code, because the only kind of non-overlapping references the borrow checker understands are distinct struct/tuple fields.
However, you don't need to write unsafe code to solve this particular problem, because the iterator std::slice::ChunksMut, returned by <[T]>::chunks_mut, already contains the implementation you need. The non-mutable chunks() can replace your other iterator implementation, too.
impl<T: Clone, const S: usize> Collection<T, S> {
fn new(num_items: usize, default_value: T) -> Collection<T, S> {
Collection {
data: vec![default_value; num_items * S]
}
}
fn iter(&self) -> impl Iterator<Item = &[T]> + '_ {
self.data.chunks(S)
}
fn iter_mut(&mut self) -> impl Iterator<Item = &mut [T]> + '_ {
self.data.chunks_mut(S)
}
}

Non-consuming mutable iterator over variable sized slices within vec [duplicate]

This question already has answers here:
How can I create my own data structure with an iterator that returns mutable references?
(1 answer)
How to implement Iterator yielding mutable references [duplicate]
(2 answers)
Closed 2 years ago.
I have a struct (Lines) containing a vec of Coordinates.
I'm trying to implement a non-consuming mutable iterator over non-overlapping sub-slices into this vector as &mut [Coordinate]. Each sub-slice would represent 1 line stored in Lines.
-edit: Additionally the lists of indices may be reordered without the vertices being moved. As such the lines in vertices cannot be assumed to be in the same order as the indices.
The implementation works for the immutable iterator (same implementation as below, but without muts)
https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=dc03530c82e8113ea532e5345dda4142
use std::ops::{Index, IndexMut};
#[derive(Debug)]
pub struct Coordinate {
x: u32,
y: u32,
}
/// SOA containing multiple line geometries
/// All coordinates of all the lines are stored contiguously in vertices
/// start_indices & end_indices both contain 1 entry for every geometry
#[derive(Debug)]
struct Lines {
vertices: Vec<Coordinate>,
start_indices: Vec<usize>,
end_indices: Vec<usize>,
}
impl Lines {
pub fn len(&self) -> usize {
self.start_indices.len()
}
fn iter_mut(&mut self) -> LinesIterMut {
LinesIterMut {
lines: self,
next_index: 0,
}
}
}
impl Index<usize> for Lines {
type Output = [Coordinate];
fn index(&self, index: usize) -> &Self::Output {
&self.vertices[self.start_indices[index]..self.end_indices[index]]
}
}
impl IndexMut<usize> for Lines {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.vertices[self.start_indices[index]..self.end_indices[index]]
}
}
pub struct LinesIterMut<'a> {
lines: &'a mut Lines,
next_index: usize,
}
impl<'a> Iterator for LinesIterMut<'a> {
type Item = &'a mut [Coordinate];
fn next(&mut self) -> Option<Self::Item> {
if self.next_index < self.lines.len() {
let current_index = self.next_index;
self.next_index += 1;
Some(&mut self.lines[current_index])
} else {
None
}
}
}
fn main() {
let mut my_lines = Lines {
vertices: vec![
Coordinate {
x: 1,
y: 2,
},
Coordinate {
x: 4,
y: 5,
},
],
start_indices: vec![0],
end_indices: vec![2],
};
for line in my_lines.iter_mut() {
line[0].y = 33;
println!("=> {:?}", line);
}
}
I get the following lifetime error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:54:23
|
54 | Some(&mut self.lines[current_index])
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 50:5...
--> src/main.rs:50:5
|
50 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:54:23
|
54 | Some(&mut self.lines[current_index])
| ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 47:6...
--> src/main.rs:47:6
|
47 | impl<'a> Iterator for LinesIterMut<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:50:46
|
50 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
51 | | if self.next_index < self.lines.len() {
52 | | let current_index = self.next_index;
53 | | self.next_index += 1;
... |
57 | | }
58 | | }
| |_____^
= note: expected `Iterator`
found `Iterator`
How do I tell the compiler that the lifetime of the reference is related to Lines?
-edit: Using the link provided by #kmdreko : https://stackoverflow.com/a/60072822/13138916
I wrote this.
It works, but is this safe? How can I tell?
pub struct LinesIterMut<'a> {
lines: &'a mut Lines,
next_index: usize,
}
impl<'a> Iterator for LinesIterMut<'a> {
type Item = &'a mut [Coordinate];
fn next(&mut self) -> Option<Self::Item> {
if self.next_index < self.lines.len() {
let current_index = self.next_index;
self.next_index += 1;
Some(unsafe { std::mem::transmute(&mut self.lines[current_index]) }) // <<--- Only changed this line
} else {
None
}
}
}

How to push a item from a function parameter to a vector from a function parameter - Different lifetime issue

I need to push an item to a vector. But both of item and vector are function parameters.
Simple code to reproduce:-
struct Point {
x: i32,
y: i32
}
fn main(){
let points: Vec<&Point> = vec!();
let start_point = Point {x: 1, y:2};
fn fill_points<F>(points: &mut Vec<&F>, point: &F ){
// Some conditions and loops
points.push(point);
}
fill_points(&mut points, & start_point);
}
Error:-
|
13 | fn fill_points<F>(points: &mut Vec<&F>, point: &F ){
| -- -- these two types are declared with different lifetimes...
14 | // Some conditions
15 | points.push(point);
| ^^^^^ ...but data from `point` flows into `points` here
Playground URL:- https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e1f2d738a22795ae11aab01ad8d00d96
You need to add a lifetime parameter:
struct Point {
x: i32,
y: i32,
}
fn main() {
let start_point = Point { x: 1, y: 2 };
let mut points: Vec<&Point> = vec![];
fn fill_points<'a, F>(points: &mut Vec<&'a F>, point: &'a F) {
// Some conditions
points.push(point);
}
fill_points(&mut points, &start_point);
}
(code simplified based the comment from #Stargateur)

Issues with a second borrow in rust

I started with Rust recently and I working on small game, unfortunately, I'm having issues on implementing a simple mechanic due an error of multiple mutable borrows, for instance, the following code has an issue with a second mutable borrow
struct Margin {
x: f32,
y: f32,
h: f32,
w: f32,
}
struct Level {
margins: Vec<Margin>,
}
impl Level {
fn new() -> Self {
Level{
margins: vec![]
}
}
fn update(&mut self) {
// Add a new margin on each tick
self.margins.push(Margin {
x:0., y:0., w:100., h:0.5,
});
// Iterate over margins moving each one down a little
for (i, m) in self.margins.iter_mut().enumerate() {
m.y += 1.;
// Remove margins outside of the screen
if m.y > 640. {
self.margins.remove(i);
}
}
}
}
fn main() {
let mut l = Level::new();
l.update();
}
Error
Compiling playground v0.0.1 (/playground)
error[E0499]: cannot borrow `self.margins` as mutable more than once at a time
--> src/main.rs:31:17
|
26 | for (i, m) in self.margins.iter_mut().enumerate() {
| -----------------------------------
| |
| first mutable borrow occurs here
| first borrow later used here
...
31 | self.margins.remove(i);
| ^^^^^^^^^^^^ second mutable borrow occurs here
Found the useful method retain on the Vec and the code is fixed as follows:
struct Margin {
x: f32,
y: f32,
h: f32,
w: f32,
}
struct Level {
margins: Vec<Margin>,
}
impl Level {
fn new() -> Self {
Level{
margins: vec![]
}
}
fn update(&mut self) {
// Add a new margin on each tick
self.margins.push(Margin {
x:0., y:0., h:100., w:0.5,
});
// Iterate over margins moving each one down a little
for m in self.margins.iter_mut() {
m.y += 1.;
}
// Retains only the elements where y is lower than 640.
self.margins.retain(|v| v.y < 640.);
}
}
fn main() {
let mut l = Level::new();
l.update();
}
Answered based on a previous answer here Remove an element while iterationg over it

Resources