Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I pass multiple elements from a collection into a function with one or more of the elements being mutable?

When passing two elements from the same vector to a function, the borrow checker will not allow one of the elements to be mutable.

struct Point {
    x: i32,
    y: i32,
}
fn main() {
    let mut vec: Vec<Point> = Vec::new();
    foo(&mut vec[0], &vec[1]);
}
fn foo(pnt_1: &mut Point, pnt_2: &Point) {
}

error: cannot borrow vec as immutable because it is also borrowed as mutable

vec is never borrowed by foo though, vec[0] is borrowed and vec[0] is a Point.

How can I pass multiple elements from the same collection into a function with one or more of the elements being mutable?

like image 564
HiDefender Avatar asked Sep 29 '16 19:09

HiDefender


1 Answers

How can I pass multiple elements from the same collection into a function with one or more of the elements being mutable?

The short answer is that you cannot, at least not without support from the collection itself.

Rust disallows mutable aliases - multiple names for the same thing, one of which allows mutation.

It would be far too complicated (with the current state of programming languages) to verify that (&mut vec[0], &vec[1]) does not introduce aliasing but (&mut vec[0], &vec[0]) does. Adding to the complexity is the fact that the [] operator can be overloaded, which allows creating a type such that foo[0] and foo[1] actually point at the same thing.

So, how can a collection help out? Each collection will have (or not have) a specific way of subdivision in an aliasing-safe manner.

There can be methods like slice::split_at_mut which verify that that two halves cannot overlap and thus no aliasing can occur.

Unfortunately, there's no HashMap::get_two_things(&a, &b) that I'm aware of. It would be pretty niche, but that doesn't mean it couldn't exist.

vec is never borrowed by foo though

It most certainly is. When you index a Vec, you are getting a reference to some chunk of memory inside the Vec. If the Vec were to change underneath you, such as when someone adds or removes a value, then the underlying memory may need to be reallocated, invalidating the reference. This is a prime example of why mutable aliasing is a bad thing.

like image 131
Shepmaster Avatar answered Nov 15 '22 05:11

Shepmaster