Параметры времени жизни в связанных типах с изменчивостью

Пытаюсь написать систему сущностей-компонентов на Rust (версия rustc 1.19.0-nightly (557967766 2017-05-26)) без использования даункастинга, а желательно еще и без макросов. Общая архитектура представляет собой свободное объединение specs и calx-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]);
}

Я также опубликовал полную реализацию.

Определение ViewTrait можно найти в этом минимальном рабочем примере, который мне удалось заставить работать благодаря параметрам времени жизни в связанном типе.

Хотя приведенный выше пример работает правильно, я продолжаю получать ошибки времени жизни для метода 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))
    |                                                ^^^^^^^^

person E Y    schedule 27.05.2017    source источник
comment
Можете ли вы также указать определение остальных соответствующих типов в вопросе? В частности, здесь должны быть Scheduler, AssemblyTrait и ViewTrait. Эта проблема очень похожа на stackoverflow.com/q/24574741/1233251 (хотя и не с итераторами, а с вашей собственной чертой): время жизни &mut self несовместимо со временем жизни 'a.   -  person E_net4 the curator    schedule 27.05.2017
comment
@E_net4: я вижу сходство со связанным вопросом. Хотя я не совсем знаю, как бы я применил его решение к моей проблеме. Тем временем я добавил определения, которые вы просили.   -  person E Y    schedule 27.05.2017
comment
Я заметил, что вы использовали 'a ViewTrait<'a>, что, вероятно, завышает время жизни, как в этом вопросе: stackoverflow.com/questions/44081272.   -  person zstewart    schedule 27.05.2017
comment
На самом деле я ввел дополнительное время жизни, связанное с универсальным типом A, потому что структура World содержит поле std::marker::PhantomData, которое, в свою очередь, использует ложно неиспользуемый параметр времени жизни. Я обновлю вопрос, включив в него определение структуры World.   -  person E Y    schedule 27.05.2017
comment
Я должен бежать; но я начал ответ, который содержит несколько MCVE, если кто-то хочет его подобрать.   -  person Shepmaster    schedule 27.05.2017
comment
@Shepmaster, спасибо за незавершенный ответ. Основываясь на вашем, я самостоятельно воссоздал MCVE и понял, что у меня несколько одновременных проблем. с моим кодом: у меня не только пожизненная проблема с ViewTrait::View (т.е. изменяемые ссылки в качестве возвращаемого типа), но я также многократно заимствую World несколько раз. Я думаю, что я спрашиваю; как мне все это упорядочить?   -  person E Y    schedule 27.05.2017
comment
Можете ли вы объяснить, почему вы решили определить 'a на уровне черты?   -  person Shepmaster    schedule 28.05.2017
comment
Я следовал предложениям, сделанным параметрами времени жизни в связанном типе. Вариант включения его на уровне трейта, казалось, работал проще, чем реализация трейта для ссылочного типа. Я открыт для альтернативных предложений!   -  person E Y    schedule 28.05.2017
comment
Наконец, мне удалось решить проблему множественного изменяемого заимствования World (и его членов). Но я до сих пор не знаю, как решить проблему взаимодействия между SystemTrait и ViewTrait в отношении времени жизни. В целях более подробного описания фактической проблемы, должен ли я изменить свой первоначальный вопрос или задать новый?   -  person E Y    schedule 31.05.2017