#ParamSet in #[derive(SystemParam)] in Bevy 0.10

6 messages · Page 1 of 1 (latest)

tropic drum
#

After updating to Bevy 0.10 several of my SystemParams broke, due to a lifetime issue. I traced it down and it seems like using ParamSet within a #[derive(SystemParam)] struct doesn't work like expected, and I'm kinda lost on how to approach this.

This is a rather contrived minimal reproduction, but in theory this should compile right? It did in 0.9.1 at least.

#[derive(SystemParam)]
struct DoesNotWork<'w, 's> {
    pub nope: ParamSet<'w, 's, (Commands<'w, 's>,)>,
}

My attempts to gather what is going on:

The error message is rather cryptic - as expected when dealing with macros:

80 | #[derive(SystemParam)]
   |          ^^^^^^^^^^^
   |          |
   |          lifetime `'w` defined here
   |          lifetime `'w2` defined here
   |          associated function was supposed to return data with lifetime `'w2` but it is returning data with lifetime `'w`

SOLUTION
The solution seems to remove all references to the lifetimes from the generic type parameter of ParamSet:

#[derive(SystemParam)]
struct WorksNow<'w, 's> {
    pub yess: ParamSet<'w, 's, (Commands<'static, 'static>,)>,
}

But I don't quite understand a few of the things that are going on, so if anyone knows that stuff better than me, i'd be verryy glad to get some answers 😛

#

Running cargo expand shows that the problem lies here within the generated Impl SystemParam:

        unsafe fn get_param<'w2, 's2>(
            state: &'s2 mut Self::State,
            system_meta: &bevy::ecs::system::SystemMeta,
            world: &'w2 bevy::ecs::world::World,
            change_tick: u32,
        ) -> Self::Item<'w2, 's2> {
            let (f0,) = <(
                ParamSet<'w, 's, (Commands<'w, 's>,)>,
            ) as bevy::ecs::system::SystemParam>::get_param(
                &mut state.state,
                system_meta,
                world,
                change_tick,
            );
            DoesNotWork { blubb: f0 }
        }

This errors as:

25 |     unsafe impl<'w, 's> bevy::ecs::system::SystemParam for DoesNotWork<'w, 's> {
   |                 -- lifetime `'w` defined here
...
63 |         unsafe fn get_param<'w2, 's2>(
   |                             --- lifetime `'w2` defined here
...
77 |             DoesNotWork { nope: f0 }
   |             ^^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'w` but it is returning data with lifetime `'w2`
#

.#

The derive seems to work for other things as expected like

#[derive(SystemParam)]
struct Works<'w, 's> {
    pub c: Commands<'w, 's>,
}
tropic drum
#

As for now i am 100% bamboozled by what is going on and appreciate any info about where I went wrong, or if this is even a regression in bevy... In the meanwhile I'll dig deeper...

tropic drum
#

Buuut now it seems like it shouldn't work at all? Why does it work for Commands for example, but not for ParamSet. Probably because of some variance weirdness, because ParamSet has a &mut T::State which makes it invariant over T ? and T includes 'w... therefore 'w2 cannot be supplied in its place... Hmmmmm... this all is somewhat fishy to me