具有可变性的关联类型中的生命周期参数

时间:2017-05-27 08:47:51

标签: rust lifetime mutability

我正在尝试在Rust(版本rustc 1.19.0-nightly (557967766 2017-05-26))中编写实体组件系统而不使用向下转换,最好也不使用宏。一般架构是specscalx-ecs的松散合并。

我正在努力定义一个基于所选组件执行系统操作的工作run方法。要求是系统可以可变地借用每个相关实体的组成部分。但是,我真的和借阅检查员打架,我有点迷茫。

run方法由Scheduler结构实现,该结构拥有World结构和盒装系统特征对象的向量。

pub type ComponentMask = u8;
pub trait AssemblyTrait {
    fn new() -> Self;
    fn match_mask(&self, entity: &Entity, mask: ComponentMask) -> bool;
    fn remove(&mut self, entity: &Entity);
}
pub trait ViewTrait<'a> {
    type View;
    fn get_view(&'a mut self, entity: &Entity) -> Self::View;
}
pub struct World<'a, A: 'a + AssemblyTrait + ViewTrait<'a>> {
    next_idx: usize,
    next_uuid:  UUID,
    free_indices: Vec<usize>,
    entities: ComponentContainer<bool>,
    pub components: A,
    phantom: marker::PhantomData<&'a A>,
}
pub struct Scheduler<'a, A> where A: 'a + AssemblyTrait + ViewTrait<'a> {
    world: World<'a, A>,
    systems: Vec<Box<'static + SystemTrait<'a, A>>>,
}
impl<'a, A> Scheduler<'a, A> where A: 'a + AssemblyTrait + ViewTrait<'a> {
    // Some methods ommitted.
    pub fn run(&'a mut self) {
        for system in self.systems.iter() {
            let mask = system.get_mask();
            let mut components: Vec<A::View> = self.world.iter()
                .filter(|e| self.world.match_mask(e, mask))
                .map(|e| self.world.components.get_view(e))
                .collect();
            if components.len() > 0 {
                system.run(&components);
            }
        }
    }
}

系统特征定义如下:

pub trait SystemTrait<'a, A> where A: AssemblyTrait + ViewTrait<'a> {
    fn get_name(&self) -> &'static str;
    fn get_mask(&self) -> ComponentMask;
    fn run(&mut self, components: &mut [A::View]);
}

我也发布了the full implementation

ViewTrait的定义可以在this minimal working example中找到,由于Lifetime parameters in associated type,我设法开始工作。

虽然上面的示例工作正常,但我仍然会为Scheduler::run方法获取生命周期错误:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
   --> src\lib.rs:261:48
    |
261 |                 .map(|e| self.world.components.get_view(e))
    |                                                ^^^^^^^^
    |
note: first, the lifetime cannot outlive the lifetime  as defined on the body at 261:22...
   --> src\lib.rs:261:22
    |
261 |                 .map(|e| self.world.components.get_view(e))
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `self`
   --> src\lib.rs:261:26
    |
261 |                 .map(|e| self.world.components.get_view(e))
    |                          ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 244:1...
   --> src\lib.rs:244:1
    |
244 | / impl<'a, A> Scheduler<'a, A> where A: 'a + AssemblyTrait + ViewTrait<'a> {
245 | |     pub fn new(world: World<'a, A>) -> Scheduler<'a, A> {
246 | |         Scheduler {
247 | |             world: world,
...   |
267 | |     }
268 | | }
    | |_^
note: ...so that types are compatible (expected &'a mut A, found &mut A)
   --> src\lib.rs:261:48
    |
261 |                 .map(|e| self.world.components.get_view(e))
    |                                                ^^^^^^^^

0 个答案:

没有答案