Mutability problem with Option<&T>


#1

I have the following snippet of code:

        let mut scene = Scene::new(32);
        let mut entity_id = scene.create_entity();
        {
            let mut e = scene.get_entity(entity_id);
            let mut ic = ImageComponent::new();
            ic.texture = Some(tm.get(&String::from("wabbit")));
            match e {
                Some(entity) => {
                    entity.add(Rc::new(ic));
                },
                None => {
                    sdl2::log::log("Something went wrong with the entity")
                },
            }
        }

The signature for get_entity is the following:

pub fn get_entity(&self, entity_id: u32) -> Option<&Entity>

I thought that I would just get that Option<&Entity> object, match it and call it’s add function that has the following signature:

pub fn add(&mut self, component: Rc<Component>)

but it looks like entity is immutable and I cannot borrow it as mutable.

The actual error is the following:

error[E0596]: cannot borrow immutable borrowed content `*entity` as mutable
   --> src/engine.rs:350:21
    |
350 |                     entity.add(Rc::new(ic));
    |                     ^^^^^^ cannot borrow as mutable

error: aborting due to previous error

Any help is kindly appreciated :slight_smile:


#2

What if you change get_entity to pub fn get_entity(&mut self, entity_id: u32) -> Option<&mut Entity> and return a mutable reference?


#3

It sounds like a good idea. It makes everything simpler than trying to get a mutable reference from the immutable one :stuck_out_tongue:


#4

Yeah, there isn’t really a question here - you need a mutable reference to, well, mutate it :slight_smile: (leaving interior mutability aside).

Also, it’s canonical to append a _mut suffix to functions/methods returning mutable references. So get_entity_mut here.


#5

Good to know about the _mut suffix. Now I could still use some help with locating the element in the array.

I know that I can use an iterator to compare the id of my element with the one I’m passing to the function, but how do I actually get a reference to that element once found?

    pub fn get_entity_mut(&mut self, entity_id: u32) -> Option<&mut Entity> {
        let entities_contains = self.entities.iter().any(|e| e.get_id() == entity_id);
        if entities_contains {
            // TODO: how do you get the entity here?
            return Some(entity);
        }
        return None;
    }

#6
pub fn get_entity_mut(&mut self, entity_id: u32) -> Option<&mut Entity> {
    self.entities.iter_mut().find(|e| e.get_id() == entity_id)
}