“参数类型'C'可能没有足够长的寿命",当它不需要 [英] "The parameter type `C` may not live long enough", when it doesn't need to

查看:75
本文介绍了“参数类型'C'可能没有足够长的寿命",当它不需要的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Rust中编写非常基本的AI系统.它的主要组成部分是:

I'm writing very basic AI system in Rust. It's main components are:

  • Action s,可以由库用户实现以用于特定用途,
  • 通用Context,它传递给所有动作,并且只需要在动作执行期间存在,
  • ActionsContainer,全局"存储所有可能的操作,
  • System,它选择正确的操作并运行它.有许多系统,每个代理一个.但是,它们共享相同的行为集,因此它们都引用相同的ActionsContainer.
  • Actions, which can be implemented by library user, for specific use,
  • Generic Context, which is passed to all actions, and only needs to live during the action execution,
  • ActionsContainer, which "globally" stores all possible actions,
  • System, which chooses the correct action and runs it. There are many systems, one for each agent. However, they share the same set of behaviours, so they all reference a common ActionsContainer.

这是一个说明我问题的最小示例.

Here is a minimum example which illustrates my problem.

// Generic system

trait Context {}

trait Action<C: Context> {
    fn run(&self, context: &mut C);
}

struct ActionsContainer<C: Context> {
    actions: Vec<Box<Action<C>>>,
}

struct System<'a, C: Context> {
    actions: &'a ActionsContainer<C>,
}

impl<'a, C: Context> System<'a, C> {
    fn run(&self, c: &mut C) {
        self.actions.actions[0].run(c);
    }
}

// Implementation

struct ContextImpl<'a> {
    x: &'a i32,
    y: i32,
}

impl<'a> Context for ContextImpl<'a> {}

struct ActionImpl {}

impl<'a> Action<ContextImpl<'a>> for ActionImpl {
    fn run(&self, c: &mut ContextImpl) {
        println!("Action!");
        c.y = c.x;
    }
}

// usage
fn main() {
    let container = ActionsContainer {
        actions: vec![Box::new(ActionImpl {})],
    };

    {
        let system = System {
            actions: &container,
        };

        {
            let x = 8;
            let mut context = ContextImpl { x: &x, y: 0 };

            system.run(&context);

            assert_eq!(context.y, context.x)
        }
    }
}

游乐场

编译器抱怨:

error[E0309]: the parameter type `C` may not live long enough
  --> src/main.rs:14:5
   |
13 | struct System<'a, C: Context> {
   |                   -- help: consider adding an explicit lifetime bound `C: 'a`...
14 |     actions: &'a ActionsContainer<C>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: ...so that the reference type `&'a ActionsContainer<C>` does not outlive the data it points at
  --> src/main.rs:14:5
   |
14 |     actions: &'a ActionsContainer<C>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

但是,C未存储在Action中.它只需要在执行run时运行.另一方面,Action的生存期必须与整个System一样长.有什么方法可以对此进行注释吗?

However, C is not stored in Action. It only needs to live while run is executing. On the other hand, the Action does need to live as long as whole System. Is there any way to annotate this?

我怀疑,这与高阶特质界线有关,但我在这里看不到如何使用它们.

I suspect, it has something to do with Higher-Rank Trait Bounds, but I don't see how to use them here.

我还试图摆脱Action作为特征对象,而只使用普通的函数引用:

I've also tried to get rid of Action as a trait object and just use plain function references:

type Action<C> = fn(&mut C);

struct ActionsContainer<C: Context> {
    actions: Vec<&'static Action<C>>,
}

但是编译器错误几乎相同.

But the compiler error was pretty much the same.

推荐答案

我找到了解决方法:

// Generic system

trait Context {}

trait Action<C: Context> {
    fn run(&self, context: &mut C);
}

struct ActionsContainer<A> {
    actions: Vec<Box<A>>,
}

struct System<'a, A: 'a> {
    actions: &'a ActionsContainer<A>,
}

impl<'a, A> System<'a, A> {
    fn run<C>(&self, c: &mut C)
    where
        C: Context,
        A: Action<C>,
    {
        self.actions.actions[0].run(c);
    }
}

// Implementation

struct ContextImpl<'a> {
    x: &'a i32,
    y: i32,
}

impl<'a> Context for ContextImpl<'a> {}

struct ActionImpl {}

impl<'a> Action<ContextImpl<'a>> for ActionImpl {
    fn run(&self, c: &mut ContextImpl) {
        println!("Action!");
        c.y = *c.x;
    }
}

// usage
fn main() {
    let container = ActionsContainer {
        actions: vec![Box::new(ActionImpl {})],
    };

    {
        let system = System {
            actions: &container,
        };

        {
            let x = 8;
            let mut context = ContextImpl { x: &x, y: 0 };

            system.run(&mut context);

            assert_eq!(context.y, *context.x)
        }
    }
}

游乐场

Rust始终假定通用结构中提到的特征将存储在该结构中(因此,我将遇到终身问题).如果您不打算存储特征,请不要在结构定义中提及它.相反,请使用更多一般性界限,并在定义适当生命周期的方法上进行澄清.

Rust always assumes that traits mentioned in generic struct will be stored in that struct (hence my lifetime problems). If you are not intending to store the trait, do not mention it in struct definition. Instead, use more general bounds, and clarify them on the method, which defines appropriate lifetime.

这篇关于“参数类型'C'可能没有足够长的寿命",当它不需要的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆