0

I am trying to receive some input, and then either return the value if it's valid or get input again if it's not. However, I'm running into borrow checker issues trying to both check the value and return it (new to Rust). Here's the code snippet:

fn get_move(&self) -> (String, String) {
    let player = self.current_player();

    let mut mv;
    let mut is_valid = false;

    loop {
        mv = player.make_move();
        {
            is_valid = self.move_valid(mv);
        }
        match is_valid {
            true => return mv,
            _ => continue,
        }
    }
}

fn move_valid(&self, (_from,_to): (String, String)) -> bool {
    false
}

Error returned is

error[E0382]: use of moved value: `mv`
  --> src/game.rs:75:32
   |
72 |                 is_valid = self.move_valid(mv);
   |                                            -- value moved here
...
75 |                 true => return mv,
   |                                ^^ value used here after move
   |
   = note: move occurs because `mv` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait

I tried adding the scope around self.move_valid, but it the move_valid method still appears to be owning mv when I try and return it.

Is there a standard Rust pattern for repeated input until the value is valid? How can I get this to work?

UsAndRufus
  • 385
  • 5
  • 14
  • FYI it's an implementation of Nine Men's Morris (hence the references to player and move). You can see the full code [here](https://github.com/UsAndRufus/nineman). – UsAndRufus Dec 26 '17 at 17:37
  • Interesting thing: you know a thing called borrow checker but you don't know what it is? :) You should re-read the rust book, especially the ownership chapter. – VP. Dec 26 '17 at 18:19
  • Possible duplicate of [How to prevent a value from being moved?](https://stackoverflow.com/questions/41664099/how-to-prevent-a-value-from-being-moved) In your case, you're already taking `self` by reference; all you need to do is take `mv` by reference too. – trent Dec 26 '17 at 20:13
  • Read the [rust book](https://doc.rust-lang.org/book/second-edition/) and you'll never have to ask this question again~ it's a must read – cozyconemotel Dec 27 '17 at 12:40
  • I have been chugging through the Rust book, but juggling it in spare-time jobs etc means I forget bits. In my mind once the method was done with the value it would give up ownership - clearly you need references for this which I didn't realise! – UsAndRufus Dec 27 '17 at 13:41

1 Answers1

1

When you just pass an unadorned parameter (like (String,String)) to a function, you are moving the value into that function. You don't have it anymore, you've given it to the function.

You probably just want to change the parameter type to &(String,String) to pass a reference instead. Then the function will be able to look at the data, but no ownership change will take place.

NovaDenizen
  • 5,089
  • 14
  • 28
  • Thanks, that works! I changed the method signature to `fn move_valid(&self, mv: &(String, String)) -> bool {`, and decomposed the tuple inside the method. Now to read more... – UsAndRufus Dec 27 '17 at 13:42