Is it possible to borrow parts of a struct as mutable, and another part as immutable - if the struct's fields are private.
fn main() {
let mut ecs = EntityComponentSystem::new();
for e_id in ecs.get_entities_with_component::<Velocity>().unwrap() {
let components = ecs.get_mut_components(e_id);
...
}
impl EntityComponentSystem {
...
pub fn get_entities_with_component<K: Key>(&self) -> Option<&HashSet<u64>> {
self.entities_with_components.get(&TypeId::of::<K>())
}
pub fn get_mut_components(&mut self, entity_id: u64) -> &mut TypeMap {
let entity = self.entities.get_mut(&entity_id).unwrap();
&mut entity.components
}
}
pub struct EntityComponentSystem {
entities: HashMap<u64, Entity>, <------- I would like to modify this.
entities_with_components: HashMap<TypeId, HashSet<u64>>, <---- while reading from this!
}
The compiler is giving me:
error[E0502]: cannot borrow `*ecs` as mutable because it is also borrowed as immutable
--> physics.rs:19:26
|
18 | for e_id in ecs.get_entities_with_component::<Velocity>() {
| --- immutable borrow occurs here
19 | let components = ecs.get_mut_components(*e_id);
| ^^^ mutable borrow occurs here
...
26 | }
| - immutable borrow ends here
What I'm not grasping, is how the &self
reference in get_entities_with_component
is still borrowed after we've essentially returned a part of the entities_with_components
field.
Shouldn't just that part be borrowed? Is there any way to enforce this?
You can only borrow the entire struct as immutable or mutable, there is no concept of borrowing only parts of it. When this becomes a problem, you can use interior mutability in the form of a RefCell
:
pub struct EntityComponentSystem {
entities: RefCell<HashMap<u64, Entity>>,
entities_with_components: HashMap<TypeId, HashSet<u64>>,
}
Now you can borrow the entire struct as immutable and borrow the contents of the RefCell
independently as mutable:
pub fn get_mut_components(&self, entity_id: u64) -> &mut TypeMap {
let mut entities = self.entities.borrow_mut();
let entity = entities.get_mut(&entity_id).unwrap();
&mut entity.components
}
No, a function cannot return a reference to a part of the structure and leave the structure partially borrowed.
However you can return tuple of immutable and mutable borrows like this
#[derive(Debug)]
struct AB(u32, u32);
impl AB {
fn borrow_parts(&mut self) -> (&u32, &mut u32) {
(&self.0, &mut self.1)
}
}
fn main() {
let mut ab = AB(0, 2);
{
let (a, b) = ab.borrow_parts();
*b = *a;
}
println!("{:?}", ab);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With