Accessing different fields of the same struct simultaneously and mutably

384 views Asked by At

I'm trying to write a card game in Rust but ran into some trouble with the borrow checker. My main struct is the Game, which looks like this

struct Game {
    players: HashMap<String, Player>,
    deck: Vec<Card>,
}

Player is something like

struct Player {
    hand: Vec<Card>,
}

and for simplicity we may assume, that Card looks like

struct Card {
    text: String,
}

Now naturally I would like to draw cards from Game.deck

impl Game {
    fn draw_cards(&mut self, num: usize) -> Option<Vec<Card>> {
        if self.deck.len() >= num {
            let mut cards: Vec<Card> = Vec::new();
            for _ in 0..num {
                cards.push(self.deck.pop().unwrap());
            }
            Some(cards)
        } else {
            None
        }
    }
}

and append them to a player's hand

impl Game {
    fn draw_to_player(&mut self, name: &String, num: usize) -> Result<(), ()> {
        let cards = self.draw_cards(num);
        match cards {
            Some(mut cards) => {
                let player = self.players.get_mut(name);
                match player {
                    Some(player) => {
                        player.hand.append(&mut cards);
                        Ok(())
                    },
                    None => Err(()),
                }
            },
            None => Err(()),
        }
}

Complete playground example

Up to this point, everything works quite fine. When starting the game, I want to iterate over all players and let them draw their starting hand:

fn draw_for_all(&mut self) {
    for name in self.players.keys() {
        self.draw_to_player(name, 2);
    }
}

Complete playground example

This does not work, as self is borrowed when iterating over the keys, but has to be borrowed mutably to call draw_to_player:

error[E0502]: cannot borrow `*self` as mutable because `self.players` is also borrowed as immutable
  --> src/main.rs:48:13
   |
47 |         for name in self.players.keys() {
   |                     ------------ immutable borrow occurs here
48 |             self.draw_to_player(name, 2);
   |             ^^^^ mutable borrow occurs here
49 |         }
   |         - immutable borrow ends here

How could I approach this problem?

0

There are 0 answers