Reputation: 1853
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);
}
Upvotes: 1
Views: 1597
Reputation: 21505
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);
Upvotes: 1