Skip to content

Instantly share code, notes, and snippets.

@vadixidav
Created April 29, 2018 18:39
Show Gist options
  • Save vadixidav/3836ca64b2eb389797d0fb94f1733f37 to your computer and use it in GitHub Desktop.
Save vadixidav/3836ca64b2eb389797d0fb94f1733f37 to your computer and use it in GitHub Desktop.
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src\grid.rs:199:9
|
198 | self.step();
| ---- first mutable borrow occurs here
199 | self.update();
| ^^^^ second mutable borrow occurs here
200 | }
| - first borrow ends here
error[E0506]: cannot assign to `self.diffs` because it is borrowed
--> src\grid.rs:203:9
|
203 | self.diffs = self.make_diffs();
| ^^^^^^^^^^^^^----^^^^^^^^^^^^^
| | |
| | borrow of `self.diffs` occurs here
| assignment to borrowed `self.diffs` occurs here
error: aborting due to 2 previous errors
/// Represents the state of the simulation.
#[derive(Clone, Debug)]
pub struct SquareGrid<S: Sim> {
cells: Vec<S::Cell>,
diffs: Vec<ManuallyDrop<(S::Diff, S::MoveNeighbors)>>,
width: usize,
height: usize,
}
...
impl<'a, S, C, D, M, N, MN> SquareGrid<S>
where
S: Sim<Cell = C, Diff = D, Move = M, Neighbors = N, MoveNeighbors = MN>,
S::Cell: Sync + Send,
S::Diff: Sync + Send,
S::Move: Sync + Send,
S::Neighbors: Sync + Send,
S::MoveNeighbors: Sync + Send,
Self: GetNeighbors<'a, usize, N>,
Self: TakeMoveNeighbors<usize, MN>,
{
/// Run the Grid for one cycle and parallelize the simulation.
pub fn cycle(&'a mut self) {
self.step();
self.update();
}
fn step(&'a mut self) {
self.diffs = self.make_diffs();
}
fn make_diffs(&'a self) -> Vec<ManuallyDrop<(S::Diff, S::MoveNeighbors)>> {
self.cells[..]
.par_iter()
.enumerate()
.map(|(ix, c)| S::step(c, self.get_neighbors(ix)))
.map(ManuallyDrop::new)
.collect()
}
fn update(&'a mut self) {
self.cells[..]
.par_iter()
.enumerate()
.for_each(|(ix, cell)| unsafe {
S::update(
transmute(cell),
self.take_diff(ix),
(self as &Self).take_move_neighbors(ix),
);
});
// This wont call any `drop()` because of the `ManuallyDrop`.
self.diffs.clear();
}
}
@vadixidav
Copy link
Author

impl<'a, C, S> GetNeighbors<'a, usize, Neighbors<&'a C>> for SquareGrid<S>
where
    S: Sim<Cell = C>,
{
    fn get_neighbors(&'a self, ix: usize) -> Neighbors<&'a C> {
        Neighbors::new(|dir| self.get_cell(self.delta_index(ix, dir.delta())))
    }
}

@vadixidav
Copy link
Author

[rustc]
cannot infer an appropriate lifetime for autoref due to conflicting requirements

note: ...so that the types are compatible:
      expected neighborhood::GetNeighbors<'_, usize, N>
         found neighborhood::GetNeighbors<'a, usize, N>

@vadixidav
Copy link
Author

vadixidav commented Apr 29, 2018

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
   --> src\grid.rs:208:44
    |
208 |             .map(|(ix, c)| S::step(c, self.get_neighbors(ix)))
    |                                            ^^^^^^^^^^^^^
    |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 204:5...
   --> src\grid.rs:204:5
    |
204 | /     fn make_diffs(&self) -> Vec<ManuallyDrop<(S::Diff, S::MoveNeighbors)>> {
205 | |         self.cells[..]
206 | |             .par_iter()
207 | |             .enumerate()
...   |
210 | |             .collect()
211 | |     }
    | |_____^
note: ...so that reference does not outlive borrowed content
   --> src\grid.rs:208:39
    |
208 |             .map(|(ix, c)| S::step(c, self.get_neighbors(ix)))
    |                                       ^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 183:1...
   --> src\grid.rs:183:1
    |
183 | / impl<'a, S, C, D, M, N, MN> SquareGrid<S>
184 | | where
185 | |     S: Sim<Cell = C, Diff = D, Move = M, Neighbors = N, MoveNeighbors = MN>,
186 | |     S::Cell: Sync + Send,
...   |
226 | |     }
227 | | }
    | |_^
    = note: ...so that the types are compatible:
            expected neighborhood::GetNeighbors<'_, usize, N>
               found neighborhood::GetNeighbors<'a, usize, N>

@vadixidav
Copy link
Author

/// Defines a simulation for complicated things that have too much state to abandon on the next cycle.
///
/// This enforces a rule in that all new cells are only produced from old board state. This prevents the
/// update order from breaking the simulation.
pub trait Sim {
    /// The type of cells on the grid
    type Cell;
    /// Represents all information necessary to modify a cell in the previous grid to produce the version in the next
    type Diff;
    /// Data that moves between cells
    type Move;

    /// Neighborhood of cells.
    type Neighbors;
    /// Nighborhood of moving data
    type MoveNeighbors;

    /// Performs one step of the simulation.
    fn step(&Self::Cell, Self::Neighbors) -> (Self::Diff, Self::MoveNeighbors);

    /// Updates a cell with a diff and movements into this cell.
    fn update(&mut Self::Cell, Self::Diff, Self::MoveNeighbors);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment