我想不通如何让下面的代码编译成功。第一步是在 lifetime 的注释中苦苦挣扎,不过,我觉得终于成功了。
下一步是围绕着借用和寿命的 HashMap
进入。我觉得自己已经在兔子洞里陷得太深了,需要一些指导才能出来。
use std::collections::HashMap;
struct Player {
id: u32,
}
struct Game<'a> {
black: &'a Player,
white: &'a Player,
win: bool,
timestamp: u32,
}
struct Base<'b> {
games: &'b mut Vec<Game<'b>>,
players: &'b mut HashMap<u32, Player>,
}
impl<'c> Base<'c> {
fn create_game(self, black_id: u32, white_id: u32, win: bool, timestamp: u32) -> &'c Game<'c> {
let black_player = self
.players
.entry(black_id)
.or_insert(Player { id: black_id });
let white_player = self
.players
.entry(white_id)
.or_insert(Player { id: white_id });
let game = Game {
black: &black_player,
white: &white_player,
win: win,
timestamp: timestamp,
};
self.games.push(game);
&self.games[0]
}
}
error[E0499]: cannot borrow `*self.players` as mutable more than once at a time
--> src/lib.rs:25:28
|
19 | impl<'c> Base<'c> {
| -- lifetime `'c` defined here
20 | fn create_game(self, black_id: u32, white_id: u32, win: bool, timestamp: u32) -> &'c Game<'c> {
21 | let black_player = self
| ____________________________-
| |____________________________|
| ||
22 | || .players
| ||____________________- first mutable borrow occurs here
23 | | .entry(black_id)
| |_____________________________- argument requires that `*self.players` is borrowed for `'c`
24 | .or_insert(Player { id: black_id });
25 | let white_player = self
| _____________________________^
26 | | .players
| |_____________________^ second mutable borrow occurs here
error[E0597]: `black_player` does not live long enough
--> src/lib.rs:31:20
|
19 | impl<'c> Base<'c> {
| -- lifetime `'c` defined here
...
31 | black: &black_player,
| ^^^^^^^^^^^^^ borrowed value does not live long enough
...
37 | self.games.push(game);
| --------------------- argument requires that `black_player` is borrowed for `'c`
38 | &self.games[0]
39 | }
| - `black_player` dropped here while still borrowed
error[E0597]: `white_player` does not live long enough
--> src/lib.rs:32:20
|
19 | impl<'c> Base<'c> {
| -- lifetime `'c` defined here
...
32 | white: &white_player,
| ^^^^^^^^^^^^^ borrowed value does not live long enough
...
37 | self.games.push(game);
| --------------------- argument requires that `white_player` is borrowed for `'c`
38 | &self.games[0]
39 | }
| - `white_player` dropped here while still borrowed
如果你只是想让代码 "编译"(某种意义上说是 "可用于进一步的开发"),而不是想 "学习如何在Rust中做复杂的生命周期",那么我建议你用下面这个更简单的代码版本。
#[derive(Copy, Clone)]
struct Player {
id: u32,
}
#[derive(Copy, Clone)]
struct Game {
black: Player,
white: Player,
win: bool,
timestamp: u32
}
struct Base {
games: Vec<Game>,
players: HashMap<u32, Player>
}
impl Base {
fn create_game(&mut self, black_id: u32, white_id: u32, win: bool, timestamp: u32) -> Game {
self.players.entry(black_id).or_insert(Player {id: black_id });
self.players.entry(white_id).or_insert(Player {id: white_id });
let black_player: &Player = self.players.get(&black_id).unwrap(); // Should be safe to unwrap here
let white_player: &Player = self.players.get(&white_id).unwrap(); // Should be safe to unwrap here
let game = Game {
black: *black_player,
white: *white_player,
win: win,
timestamp: timestamp
};
self.games.push(game);
self.games[0]
}
}