user122831
user122831

Reputation: 31

Use of moved value from function implemented on a struct in Rust

I have a struct for a Player with a method. I create a new player and try calling the method:

#[derive(Debug, Default, Clone)]
pub struct Player(pub Vec<i32>, i32, String);

impl Player {
    /// Create the player
    pub fn new_player() -> Self {
        Player(Vec::new(), 0, String::new())
    }
}

impl Player {
    pub fn add_to_hand(mut self, card: i32) -> Self {
        //push to hand
        self.0.push(card);
        self
    }
}

fn main() {
    let mut player = Player::new_player();

    while (get_total(&player.0) <= 21) && (hit == 'y') {
        println!("Want another card? y/n");
        hit = read!();
        player.add_to_hand(deck.draw());
        player.show_hand();
    }
}

I get this:

error[E0382]: borrow of moved value: `player`
let mut player = Player::new_player();
   |         ---------- move occurs because `player` has type `high_low::player::Player`, which does not implement the `Copy` trait
...
60 |         while(get_total(&player.0) <= 21) && (hit == 'y') {
   |                         ^^^^^^^^^ value borrowed here after move
...
63 |             player.add_to_hand(deck.draw());
   |             ------ value moved here, in previous iteration of loop

This is just one example, I call functions many times throughout the program, and thus get this same error every time.

I know it's because the struct Player doesn't derive the Copy trait, but I can't do that because of String and Vec<i32>. Is there a fix for this?

Upvotes: 0

Views: 5255

Answers (1)

loganfsmyth
loganfsmyth

Reputation: 161457

Since add_to_hand takes ownership of the Player, because it uses mut self, not &mut self, you'd either need to:

Leave add_to_hand and use its return value, e.g.

player = player.add_to_hand(deck.draw());

but that's pretty weird since there is no reason to mutate and then return the player, so instead you should do

pub fn add_to_hand(&mut self, card: i32) {
    //push to hand
    self.0.push(card);
}

and your code should work as-is.

Upvotes: 2

Related Questions