rustbevy

Understanding Lifetimes in Bevy SystemParam Queries


In bevy, we can define custom SystemParams like in this example

/// The [`SystemParam`] struct can contain any types that can also be included in a
/// system function signature.
///
/// In this example, it includes a query and a mutable resource.
#[derive(SystemParam)]
struct PlayerCounter<'w, 's> {
    players: Query<'w, 's, &'static Player>,
    count: ResMut<'w, PlayerCount>,
}

The SystemParam docs explain that

Derived SystemParam structs may have two lifetimes: 'w for data stored in the World, and 's for data stored in the parameter’s state.

Consider the &static lifetime on Player though...

I would understand this as "The Player must exist for the whole duration the program is running", but that is clearly untrue, as a Query can also be used without any Player Entity... instead, it seems more like this 'static lifetime only refers to the type itself having to exist. But these are just guesses.

What is the meaning of the &'static lifetime on the Player here and why/when is it required?


Solution

  • The use of 'static here is mostly a placeholder. It doesn't mean that Players you get through the query live forever. This is specific to Query and not SystemParams as a whole - QueryData has more examples with 'static.

    The &'static Player type ultimately get used as a WorldQuery by the Query within which the Items that it yields are &'w Player where 'w is the lifetime of the world. It is done this way because the QueryData trait that the query type needs to satisfy isn't bound directly to the life of the world - it only gets that lifetime when needed. You can't actually express the real lifetime of the Players you'd get from that position, so 'static is used as a placeholder.

    It may also be done to improve system ergonomics: the lifetime in fn update_players(q: Query<&Player>) doesn't need to be bound to anything specifically (but not sure if this was a motivation).