Pregunta

To learn rust I've tried implementing a simple game. The problem I have is that I keep running into an error about use of partially moved values, and I have no idea why it is happening.

The complete error is:

test.rs:74:58: 74:63 error: use of partially moved value: `state`
test.rs:74   let b = state.map[1][1].feature.unwrap().interact(&mut state.player);
                                                                    ^~~~~
test.rs:74:11: 74:34 note: `state.map[..][..].feature` moved here because it has type `std::option::Option<~Feature<no-bounds>>`, which is non-copyable (perhaps you meant to use clone()?)
test.rs:74   let b = state.map[1][1].feature.unwrap().interact(&mut state.player);
                     ^~~~~~~~~~~~~~~~~~~~~~~
test.rs:75:14: 75:19 error: use of partially moved value: `state`
test.rs:75   assert_eq!(state.player.health, 100);
                        ^~~~~
<std macros>:1:1: 14:2 note: in expansion of assert_eq!
test.rs:75:3: 75:40 note: expansion site
test.rs:74:11: 74:34 note: `state.map[..][..].feature` moved here because it has type `std::option::Option<~Feature<no-bounds>>`, which is non-copyable (perhaps you meant to use clone()?)
test.rs:74   let b = state.map[1][1].feature.unwrap().interact(&mut state.player);
                     ^~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors

Here is a minimally working example picked out of the game:

trait Feature {
  fn interact(&self, &mut Player) -> bool;
}

#[deriving(Eq, Show)]
struct Fountain {
  name: &'static str
}

impl Fountain {
  fn new() -> ~Feature {
    ~Fountain{name: "Fountain of health"} as ~Feature
  }
}

impl Feature for Fountain {
  fn interact(&self, player: &mut Player) -> bool {
    if player.health < player.max_health {
      player.health = player.max_health;
      println!("You feel your wounds closing.");
    }
    false
  }
}

struct Tile {
  feature: Option<~Feature>
}

impl Tile {
  fn new(feature: Option<~Feature>) -> Tile {
    Tile{feature: feature}
  }
}

struct Player {
  health: int,
  max_health: int,
}

impl Player {
  fn new() -> Player {
    Player{max_health: 100, health: 100}
  }
}

struct GameState {
  map: [[Tile, ..2], ..2],
  player: Player,
}

impl GameState {
  fn new() -> GameState {
    GameState{
      player: Player::new(),
      map: [
        [
          Tile::new(None),
          Tile::new(None)
        ],
        [
          Tile::new(None),
          Tile::new(Some(Fountain::new()))
        ]
      ]
    }
  }
}

#[test]
fn test_fountain_interact_50() {
  let mut state = GameState::new();
  state.player.health = 50;
  let b = state.map[1][1].feature.unwrap().interact(&mut state.player);
  assert_eq!(state.player.health, 100);
  assert!(!b);
}
¿Fue útil?

Solución

That is because you are calling unwrap on a feature:

let b = state.map[1][1].feature.unwrap().interact(&mut state.player);

Signature of unwrap is:

fn unwrap(self) -> T

That means you are moving the value out of that Option (but you don't want that), what you want is take a reference and call interact of that:

let b = state.map[1][1].feature.get_ref().interact(&mut state.player);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top