I'm attempting to store a reference to an element of a mutable vector to use later. However, once I mutate the vector, I can no longer use the stored reference. I understand that this is because borrowing reference to the element also requires borrowing a reference to the vector itself. Therefore, the vector cannot be modified, because that would require borrowing a mutable reference, which is disallowed when another reference to the vector is already borrowed.
Here's a simple example
struct Person {
name: String,
}
fn main() {
// Create a mutable vector
let mut people: Vec<Person> = ["Joe", "Shavawn", "Katie"]
.iter()
.map(|&s| Person {
name: s.to_string(),
})
.collect();
// Borrow a reference to an element
let person_ref = &people[0];
// Mutate the vector
let new_person = Person {
name: "Tim".to_string(),
};
people.push(new_person);
// Attempt to use the borrowed reference
assert!(person_ref.name == "Joe");
}
which produces the following error
error[E0502]: cannot borrow `people` as mutable because it is also borrowed as immutable
--> src/main.rs:21:5
|
15 | let person_ref = &people[0];
| ------ immutable borrow occurs here
...
21 | people.push(new_person);
| ^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
...
24 | assert!(person_ref.name == "Joe");
| --------------- immutable borrow later used here
I've also tried boxing the vector elements as suggested here, but that doesn't help. I thought it might allow me to drop the reference to the vector while maintaining a reference to the element, but apparently not.
struct Person {
name: String,
}
fn main() {
// Create a mutable vector
let mut people: Vec<Box<Person>> = ["Joe", "Shavawn", "Katie"]
.iter()
.map(|&s| {
Box::new(Person {
name: s.to_string(),
})
})
.collect();
// Borrow a reference to an element
let person_ref = people[0].as_ref();
// Mutate the vector
let new_person = Box::new(Person {
name: "Tim".to_string(),
});
people.push(new_person);
// Attempt to use the borrowed reference
assert!(person_ref.name == "Joe");
}
This still produces the same error
error[E0502]: cannot borrow `people` as mutable because it is also borrowed as immutable
--> src/main.rs:23:5
|
17 | let person_ref = people[0].as_ref();
| ------ immutable borrow occurs here
...
23 | people.push(new_person);
| ^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
...
26 | assert!(person_ref.name == "Joe");
| --------------- immutable borrow later used here
Is there a way to do this, or am I trying to do something impossible?
assert!(people[0].name == "Joe");
is implicitly discarded, it's not clear if the question is theoretical, or it's a real-world one with a bigger picture that prevents the solution mentioned. – Italicizepeople[0].name
. The question does come from a real-world example of attempting to fill a mutable vector in a loop while storing references to the elements in a hash map. Context. – Minter