Compile-time alternative to Vec<RefCell<Poly>>?

Suppose I have a struct that hols polynomials, and I want to access some mutably, and other non mutably:

pub struct Poly{}

pub struct PolyCollection{
    polys: Vec<Poly>
}

impl PolyCollection {
    fn get_poly(&self, index: usize) -> Option<&Poly>{
        self.polys.get(index)
    }
    
    fn get_poly_mut(&mut self, index: usize) -> Option<&mut Poly>{
        self.polys.get_mut(index)
    }
}


fn use_polys(poly1: &Poly, poly2: &mut Poly) {
    todo!()
}

fn do_something(poly_collection: &mut PolyCollection) {
    use_polys(poly_collection.get_poly(0).unwrap(), 
        poly_collection.get_poly_mut(1).unwrap())
}

I obviously get:

error[E0502]: cannot borrow `*poly_collection` as mutable because it is also borrowed as immutable
  --> src/lib.rs:24:9
   |
23 |     use_polys(poly_collection.get_poly(0).unwrap(), 
   |     --------- --------------------------- immutable borrow occurs here
   |     |
   |     immutable borrow later used by call
24 |         poly_collection.get_poly_mut(1).unwrap())
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here

which could have, as a solution, doing:

polys: Vec<RefCell<Poly>>

but is there a more elegant way of doing so, without having to deal with potential panics on borrow mut + borrow?

I was thinking about something like slice.chunks_mut(), but chunks_mut is for iterators.

In this case, you would probably be better off exposing the polys field directly as a mutable slice. The standard solution to the problem of accessing several disjoint elements of a slice when at least one of them needs to be mutable is to use split_at, which is easier to do if the field itself is exposed (you don't need to replicate the method on the wrapper type).

I'd have to manually split them every time I need?

Well, I'm not sure what you mean by "manually", but the code wouldn't be more complicated than what you have right now:

fn do_something(poly_collection: &mut PolyCollection) {
    let (head, tail) = poly_collections.polys.split_at_mut(1);
    use_polys(head.last().unwrap(), tail.first().unwrap())
}

hmmm, it's because I was thinking about a case with 3 or 4 polynomials also. Maybe 1 borrow mut, and others borrow

well you only need split_at_mut for the mutable case. Once you have two (disjoint) mutable slices, you can borrow from them immutably directly, by using indexing, since you are allowed to have multiple simultaneous immutable borrows into the same slice. You could also write a helper function that wraps these operations if you need to perform them frequently.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.