无法定义适当的锈蚀寿命要求

Cannot define appropriate rust lifetime requirements

长话短说;博士 嵌套对象的生命周期存在问题。代码如下。

长版:

我正在使用 ggez 编写多人游戏,我正在尝试为输入创建一个抽象层(以允许本地和远程玩家一起玩)。

为此,我创建了一个 Input 特征,并为本地输入实现了 KeyboardInput,它使用 ggez 键盘状态查询方法。

现在是棘手的部分:ggez 在启动时创建 Context 对象,并期望在公开的大多数函数中引用它。

因为我的 KeyboardInput 实现使用 ggez 输入法(具​​体来说,is_key_pressed),它必须将 &Context 传递给此方法。但是,由于 trait 本身应该是通用的,因此它不需要任何其他实现的 Context 引用(例如,NetworkInput)。

我的解决方案是在 KeyboardInput 结构中添加对 Context 作为字段的引用。但是,这导致了我仍然无法解决的终生错误。

我也试过让生命周期'static,但是也没用。

相关代码如下:

pub trait Input {
    fn get_direction(&self) -> Direction;
}

pub struct KeyboardInput<'a> {
    left_key: KeyCode,
    right_key: KeyCode,
    _ctx: &'a Context
}

impl KeyboardInput<'_> {
    pub fn new(_ctx: &Context, left_key: KeyCode, right_key: KeyCode) -> KeyboardInput {
        KeyboardInput{
            _ctx,
            left_key,
            right_key
        }
    }
}

impl Input for KeyboardInput<'_> {
    fn get_direction(&self) -> Direction {
        if ggez::input::keyboard::is_key_pressed(self._ctx, self.left_key) {
            return Direction::Left;
        }
        if ggez::input::keyboard::is_key_pressed(self._ctx, self.right_key) {
            return Direction::Right;
        }
        Direction::Unchanged
    }
}

struct Player {
    angle: f32,
    pos_x: f32,
    pos_y: f32,
    input_manager: Box<dyn Input>,
}

impl <'a>MainState {
    fn new(ctx: &'a Context) -> GameResult<MainState> {

        let kbd_input = KeyboardInput::new(ctx, KeyCode::Left, KeyCode::Right);
        let kbd_input = Box::new(kbd_input);

        let s = MainState { 
            last_update: Instant::now(),
            players: vec![
                Player::new(kbd_input)
            ]
        };
        Ok(s)
    }

}

pub fn main() -> GameResult {
    let cb = ggez::ContextBuilder::new("My game", "ggez");
    let (ctx, event_loop) = &mut cb.build()?;
    let state = &mut MainState::new(&ctx)?;
    event::run(ctx, event_loop, state)
}

和编译器错误:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src\main.rs:75:25
   |
75 |         let kbd_input = KeyboardInput::new(ctx, KeyCode::Left, KeyCode::Right);
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 72:7...
  --> src\main.rs:72:7
   |
72 | impl <'a>MainState {
   |       ^^
note: ...so that reference does not outlive borrowed content
  --> src\main.rs:75:44
   |
75 |         let kbd_input = KeyboardInput::new(ctx, KeyCode::Left, KeyCode::Right);
   |                                            ^^^
   = note: but, the lifetime must be valid for the static lifetime...
   = note: ...so that the expression is assignable:
           expected std::boxed::Box<(dyn input_manager::Input + 'static)>
              found std::boxed::Box<dyn input_manager::Input>

此错误几乎总是意味着您正在尝试以一种可以比其生命周期更长的方式存储值。

让我们看一段特定的代码,用显式类型和生命周期注释:

impl<'a> MainState {
    fn new(ctx: &'a Context) -> GameResult<MainState> {
        let kbd_input: KeyboardInput<'a> = KeyboardInput::new(ctx, KeyCode::Left, KeyCode::Right);
        let kbd_input: Box<dyn Input + 'a> = Box::new(kbd_input);

        let s: MainState = MainState {
            last_update: Instant::now(),
            players: vec![
                Player::new(kbd_input as Box<dyn Input + 'static>)
            ]
        };
        Ok(s)
    }
}

在第 9 行,您试图将 kbd_input 分配给 Box<dyn Input>。但是 Box<dyn Input> 没有明确的生命周期,它隐含地等同于 Box<dyn Input + 'static>。因此,您试图将生命周期为 'a 的值分配给具有静态生命周期的类型,这是不允许的。

解决方案是显式设置特征对象类型的生命周期:Box<dyn Input + 'a>。这种级联意味着您还需要向 MainState 结构添加生命周期,因为它现在将包含一个具有非静态生命周期的类型:

struct MainState<'a> {
  /* ... */
  players: Vec<Box<dyn Input + 'a>>,
}