HashMap Entry API的Lifetimeborrow问题 [重复]

问题描述 投票:1回答:1

我想不通如何让下面的代码编译成功。第一步是在 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 lifetime borrow-checker
1个回答
2
投票

如果你只是想让代码 "编译"(某种意义上说是 "可用于进一步的开发"),而不是想 "学习如何在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]
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.