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
Game
struct owns the players and the teams (allowing me to easily perform operations overPlayer
s or overTeam
s, and then - the
Player
s have a reference to theirTeam
, and - each
Team
has a vector of references to theirPlayer
s:
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?