leudz / shipyard

Entity Component System focused on usability and flexibility.
Other
750 stars 45 forks source link

How to use generic ViewMut with_id? #191

Open SSSxCCC opened 9 months ago

SSSxCCC commented 9 months ago

https://github.com/leudz/shipyard/issues/157 use some bounds to make generic ViewMut iterator work, but I still can not make generic ViewMut with_id work:

trait MutTrait {
    fn mutmut(&mut self);
}

fn expected<T: Component + MutTrait>(mut v: ViewMut<T>)
where
    for<'a, 'b> &'a mut ViewMut<'b, T>: IntoIter,
    for<'a, 'b> <<&'a mut ViewMut<'b, T> as IntoIter>::IntoIter as Iterator>::Item: std::ops::DerefMut<Target = T>,
{
    for mut x in (&mut v).iter() {
        x.mutmut();
    }
}

fn weird<T: Component + MutTrait>(mut v: ViewMut<T>)
where
    for<'a, 'b> &'a mut ViewMut<'b, T>: IntoIter,
    for<'a, 'b> <<&'a mut ViewMut<'b, T> as IntoIter>::IntoIter as Iterator>::Item: std::ops::DerefMut<Target = T>,
    for<'a, 'b> <&'a mut ViewMut<'b, T> as shipyard::IntoIter>::IntoIter: IntoWithId,
    for<'a, 'b> WithId<<&'a mut ViewMut<'b, T> as shipyard::IntoIter>::IntoIter>: Iterator,
    for<'a, 'b> <WithId<<&'a mut ViewMut<'b, T> as shipyard::IntoIter>::IntoIter> as Iterator>::Item: std::ops::DerefMut<Target = (EntityId, dyn std::ops::DerefMut<Target = T>)>
{
    for (id, x) in (&mut v).iter().with_id() { // error: expected associated type, found `(_, _)`
        x.mutmut();
    }
}

I try to add bounds but I still can not make it work. Please help me, thanks!

leudz commented 8 months ago

This should work but doesn't for some lifetime reason.

// `IntoAbstract` would have to be implemented for the type `&'0 mut shipyard::ViewMut<'1, Component1>`, for any two lifetimes `'0` and `'1`...
// ...but `IntoAbstract` is actually implemented for the type `&mut shipyard::ViewMut<'2, Component1>`, for some specific lifetime `'2` 
fn weird<T: Component + MutTrait>(mut v: ViewMut<T>)
where
    for<'a, 'b> &'a mut ViewMut<'b, T>: IntoIter,
    for<'a, 'b> <<&'a mut ViewMut<'b, T> as IntoIter>::IntoIter as Iterator>::Item:
        std::ops::DerefMut<Target = T>,
    for<'a, 'b> <&'a mut ViewMut<'b, T> as IntoIter>::IntoIter: Iterator + LastId,
{
    for (id, mut x) in WithId((&mut v).iter()) {
        x.mutmut();
    }
}

And turns out the code in the issue you linked has the same issue. So I'm not sure it ever worked 😰


In theory something like this should also work:


fn weird<T: Component + MutTrait>(mut v: ViewMut<T>)
where
    for<'a, 'b> &'a mut ViewMut<'b, T>: IntoIter,
    for<'a, 'b> <<&'a mut ViewMut<'b, T> as IntoIter>::IntoIter as Iterator>::Item:
        std::ops::DerefMut<Target = T>,
    // binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types
    // binding for associated type `Item` references lifetime `'b`, which does not appear in the trait input types
    for<'a, 'b> WithId<<&'a mut ViewMut<'b, T> as IntoIter>::IntoIter>: Iterator<
        Item = (
            EntityId,
            <<&'a mut ViewMut<'b, T> as IntoIter>::IntoIter as Iterator>::Item,
        ),
    >,
{
    for (id, mut x) in (&mut v).iter().with_id() {
        x.mutmut();
    }
}

But it triggers this issue https://github.com/rust-lang/rust/issues/49601. And I think it would also trigger the other one. So in conclusion I don't know how to write a generic ViewMut iterator, sorry.