“参数类型'C'可能没有足够长的寿命",当它不需要 [英] "The parameter type `C` may not live long enough", when it doesn't need to
问题描述
我正在Rust中编写非常基本的AI系统.它的主要组成部分是:
I'm writing very basic AI system in Rust. It's main components are:
-
Action
s,可以由库用户实现以用于特定用途, - 通用
Context
,它传递给所有动作,并且只需要在动作执行期间存在, -
ActionsContainer
,全局"存储所有可能的操作, -
System
,它选择正确的操作并运行它.有许多系统,每个代理一个.但是,它们共享相同的行为集,因此它们都引用相同的ActionsContainer
.
Action
s, 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 commonActionsContainer
.
这是一个说明我问题的最小示例.
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屋!