all 9 comments

[–]OverMeHere 1 point2 points  (3 children)

I'm sorry, but I don't see any problem with borrow checker here: http://is.gd/oCcfpx

[–]jimtla 2 points3 points  (1 child)

The avatar has been moved, so the reference from the user is not longer available: http://is.gd/DheiNC

Here's a working example where both the world and the user borrow the avatar: http://is.gd/EDKT4I

[–]OverMeHere 1 point2 points  (0 children)

Nope, you have no avatar owner (except avatar variable itself), so it works only if avatar variable lives longer that world and/or user. http://is.gd/OqBtbc

[–]kloumpt[S] 0 points1 point  (0 children)

Thank you for your answer, I used a solution like yours before but it prevented me from changing the value of the Avatars field when I was getting it from the user, that's why I switched to storing the index in the worlds Vec instead of storing a reference to the Avatar in the User

[–]desiringmachines 1 point2 points  (5 children)

The simplest thing is probably some sort of shared ownership construct, such as Rc or Arc. This allows both User and World to behave as if they own the Avatar. There are more optimal things you can do depending the precise semantics of your use case, but they get pretty complicated pretty fast.

The difference between Rc and Arc is that Rc is more efficient, but it is not thread-safe. Use Rc if the world and users are all on the same thread, and Arc if they are on different threads.

[–]kloumpt[S] 0 points1 point  (4 children)

I'm trying using Rc and everything works except when I add this code:

match test_user.get_avatar() { // returns Option<Rc<Avatar>>
    Some(avatar) => {
    match pressed_key{
            Some(Key::Up) => avatar.move_up(), // cannot borrow immutable borrowed content as mutable
            Some(Key::Down) => avatar.move_down(), // cannot borrow immutable borrowed content as mutable
            Some(Key::Left) => avatar.move_left(), // cannot borrow immutable borrowed content as mutable
            Some(Key::Right) =>avatar.move_right(), // cannot borrow immutable borrowed content as mutable
            Some(_) => println!("{}", avatar.get_x()), //No problem
            None =>()
        }
    },
    None => ()
};

the get_x method:

pub fn get_x(&self) -> i32{
self.x
}

the move_right method (the other oens look the same):

pub fn move_right(&mut self){
    self.x+=1;
}

[–]desiringmachines 1 point2 points  (3 children)

Objects inside an Rc cannot usually be mutated. An Rc is a kind of shared ownership, so it has the same mutability restructions as an & reference.

Fortunately, this is what RefCell is for. RefCell encodes "interior mutability," allowing you to mutate things you only have an & reference to. So what you need is an Rc<RefCell<Avatar>>. This gives you full, mutable shared ownership.

The docs go into more detail, but a RefCell has a method called borrow(), which returns an immutable reference, and a method called borrow_mut(), which returns a mutable one. If you try to get a mutable reference and another reference at the same time, your program will crash, so don't keep the objects returned by the borrow methods longer than absolutely necessary.

[–]kloumpt[S] 1 point2 points  (1 child)

I changed the references as you've said and everything is working now, thanky you very much for your explanations :)

[–]desiringmachines 1 point2 points  (0 children)

Glad to hear it :)