2014-04-23 37 views
1

學習生鏽我嘗試過一個簡單的遊戲。我遇到的問題是,我一直遇到有關使用部分移動值的錯誤,並且我不知道它爲什麼會發生。奇怪的錯誤:使用部分移動的值

完整的錯誤是:

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 

這裏是一個最低限度的工作示例挑選出來的遊戲:

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); 
} 

回答

2

那是因爲你調用unwrap上的一個特徵:

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

unwrap的簽名是:

fn unwrap(self) -> T 

這意味着你的是Option的移動值(但你不希望出現這種情況),你想要的是採取參考,並調用該interact

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

謝謝!這樣一個小東西... –

+0

fwiw,「構圖」的方式是從'&選項 - >選項<&T>'通過['as_ref'](http://static.rust-lang.org/doc/master/ STD /選項/ enum.Option.html#method.as_ref)。 ('.get_ref()'只是'.as_ref()。unwrap()'的簡寫。) – huon

+0

但在這種情況下你不能執行'as-ref()。map(...)',因爲因爲「交互」需要一個狀態,但已經借用了 – Arjan