Game object as mutable

struct Ball {}

impl Ball {
    fn update(&mut self, g: &mut Game) {}
}

struct Paddle {}

struct Game {
    ball: Ball,
    paddle: Paddle,
}

fn main() {
    let mut game = Game {
        ball: Ball {},
        paddle: Paddle {},
    };
    game.ball.update(&mut game)
}

i need to be able to access the whole game object as mutable in the update method but since the object is in the game object itself it errors... what can i do? i need to access the paddle object from the ball object.

One solution is to create a Game::update method that calls Ball::update, passing the paddle as a parameter. Game::update could also do other parts of the update that don't involve the ball.

Or you could just pass the paddle as a parameter from main:

        impl Ball {
            fn update(&mut self, p: &mut Paddle) {}
        }

        fn main() {
            let mut game = Game { ball: Ball {}, paddle: Paddle {} };
            game.ball.update(&mut game.paddle)
        }

In general it doesn't work to have a mutable reference to a struct, as well as a mutable reference to one field in that struct. This breaks the very basic rule in Rust that there can only be one mutable reference to an object at a time.

(Also, please always post the full compiler error you get from cargo build. This helps to see the context for the error. I've pasted it below.)

error[E0499]: cannot borrow `game.ball` as mutable more than once at a time
  --> src/lib.rs:28:13
   |
28 |             game.ball.update(&mut game)
   |             ^^^^^^^^^^------^---------^
   |             |         |      |
   |             |         |      first mutable borrow occurs here
   |             |         first borrow later used by call
   |             second mutable borrow occurs here

error[E0499]: cannot borrow `game` as mutable more than once at a time
  --> src/lib.rs:28:30
   |
28 |             game.ball.update(&mut game)
   |             --------- ------ ^^^^^^^^^ second mutable borrow occurs here
   |             |         |
   |             |         first borrow later used by call
   |             first mutable borrow occurs here

I finally got rid of the method update and used an associated function instead passing my mutable game object and accessing the "self" via the game object... its ugly but it works. I do it this way instead of passing the paddle by parameter because the game object will grow and i need to access all its fields.

That doesn't sound bad, if I'm understanding you. In fact there is nothing wrong with free functions (not in an impl block), when they're not logically associated with any one struct.

i kept the function in the ball impl block since its mostly moving the ball and handling collisions with the paddle. I just changed it from a method to a function since i can access the ball from the game object parameter i dont really need the "self", If that makes any sense,

1 Like

This is a classic problem described in this blog post, it also contains a couple of ways to solve it After NLL: Interprocedural conflicts · baby steps

As for a game orienter alternative solution, many Rust game engines adopt the ECS pattern, which has the nice advantage of being able to give you multiple borrows of (disjoint) data in the game world.

2 Likes