I'm trying to represent a basic game in Rust, in which there are multiple players and each of those players is in a team. I'm trying to represent this in Rust, but struggling with the borrow checker. What I've got so far is a setup where
- the
Gamestruct owns the players and the teams (allowing me to easily perform operations overPlayers or overTeams, and then - the
Players have a reference to theirTeam, and - each
Teamhas a vector of references to theirPlayers:
pub struct Game<'a> {
players: Vec<Player<'a>>,
teams: Vec<Team<'a>>,
}
pub struct Player<'a> {
team: Option<&'a Team<'a>>,
}
pub struct Team<'a> {
players: Vec<&'a Player<'a>>,
}
I'm writing the game as a telegram chat bot, so using teloxide I've got a bunch of handlers and then a DB which persists the entire Game struct. Each time a handler is called, the Game struct is recreated from the DB, and is potentially mutated to add new players or teams. Something like:
pub fn handler1() {
let mut g = get_game_from_db();
let p = Player::new();
g.players.push(p);
let t = Team::new();
g.teams.push(t);
write_game_to_db(g)
}
But the issue comes when I want to add a new team and a new player, and then add that player to the new team. I tried to do this, but the borrow checker complained:
1 pub fn handler2() {
2 let mut game = get_game();
3 // Add a player to the game
4 game.players.push(mock_player());
5 // Add a team to the game
6 game.teams.push(mock_team());
7
8 // Borrow the team
9 let team = &mut game.teams[0];
10 // Borrow the player
11 let player = &mut game.players[0];
12
13 // Add the team to the player
>> 14 player.team = Some(team); // immutable borrow occurs here
15 // Add the player to the team
>> 16 team.players.push(player); // cannot borrow `team.players` as mutable because it is also borrowed as immutable \ mutable borrow occurs here|immutable borrow later used by call
17 }
The full error is:
error[E0502]: cannot borrow `team.players` as mutable because it is also borrowed as immutable
--> src/so.rs:65:5
|
63 | player.team = Some(team);
| ---- immutable borrow occurs here
64 | // Add the player to the team
65 | team.players.push(player);
| ^^^^^^^^^^^^^----^^^^^^^^
| | |
| | immutable borrow later used by call
| mutable borrow occurs here
Is there any way to represent this sort of relationship in Rust?