I am implementing matrices in Rust. The code is adapted for the example, but there might be minor mistakes:
#[derive(Debug, PartialEq)] pub struct Matrix<T> { inner: Vec<Vec<T>>, } impl<T> Matrix<T> { pub fn dim(&self) -> (usize, usize) { if self.inner.len() == 0 { (0, 0) } else { (self.inner.len(), self.inner[0].len()) } } } I want to have the ability to get quadrants of the matrix:
+----+----+ | Q1 | Q2 | +----+----+ | Q3 | Q4 | +----+----+ I introduced the Slice and SliceMut structures to borrow a part of the matrix:
pub struct Slice<'a, T: 'a> { matrix: &'a Matrix<T>, start: (usize, usize), end: (usize, usize), } pub struct SliceMut<'a, T: 'a> { matrix: &'a mut Matrix<T>, start: (usize, usize), end: (usize, usize), } Now I want to implement two functions:
quadrants- to get a tuple of four slicesquadrants_mut- to get a tuple of four mutable slices
I cannot mutably borrow one matrix several times in quadrants_mut:
fn quadrants_mut<'a, T>(matrix: &'a mut Matrix<T>) -> (SliceMut<'a, T>, SliceMut<'a, T>, SliceMut<'a, T>, SliceMut<'a, T>) { let (rows, cols) = matrix.dim(); let mid_rows = rows / 2; let mid_cols = cols / 2; let a = SliceMut { matrix: matrix, start: (0, 0), end: (mid_rows, mid_cols) }; let b = SliceMut { matrix: matrix, start: (0, mid_rows), end: (mid_cols, cols) }; let c = SliceMut { matrix: matrix, start: (mid_rows, rows), end: (0, mid_cols) }; let d = SliceMut { matrix: matrix, start: (mid_rows, rows), end: (mid_cols, cols) }; (a, b, c, d) } When I try to compile that, I have an error:
error[E0499]: cannot borrow `*matrix` as mutable more than once at a time --> src/matrix/slice.rs:62:13 | 59 | let a = SliceMut { matrix: matrix, start: (0, 0), end: (mid_rows, mid_cols) }; | ------ first mutable borrow occurs here ... 60 | let b = SliceMut { matrix: matrix, start: (0, mid_rows), end: (mid_cols, cols) }; | ^^^^^^ second mutable borrow occurs here ... 66 | } I am trying to mutably borrow a matrix four times. How should I change the code to make it compile?
a,b,canddinside it, and then have that struct hold the reference? There may well be a more idiomatic way to implement this, though.Vec::split_at_mutwill be a first step.Vec<Vec<T>>, instead they use aVec<T>to avoid extra indirection.