Skip to content

SystemParam: lifetime may not live long enough #8192

Closed

Description

@mbolt35

Bevy version

v0.10.0

What you did

Upgrading a bevy 0.9 project to the latest and greatest. I have a few #[derive(SystemParam)] implementations that were working great with 0.9, but now give me an error: lifetime may not live long enough which appears to all occur within the SystemParam attribute itself. Here's the struct definition in question:

/// TileEntities is a helper system parameter that provides pulling
/// component references directly from the tile positions.
#[allow(clippy::complexity)]
#[derive(SystemParam)]
pub struct TileEntities<'w, 's, T: EntityRef + Component>
    where <T as EntityRef>::ComponentType: Component,
{
    references: ParamSet<'w, 's, (
        Query<'w, 's, &'static mut T>,
        Query<'w, 's, &'static T>)>,
    component: ParamSet<'w, 's, (
        Query<'w, 's, &'static mut T::ComponentType>,
        Query<'w, 's, &'static T::ComponentType>)>,
    map: TileQuery<'w, 's, SimulationLayer>,
}

The TileQuery itself is also a SystemParam:

#[derive(SystemParam)]
pub struct TileQuery<'w, 's, T: Component + Layer> {
    map: Query<'w, 's, &'static TileStorage, With<T>>,
    world_manager: Res<'w, WorldManager>,
    tile_mapper: TileMapper<'w>,
}

/// TileMapper can be included in systems and used to map tile positions back into world
/// coordinates and other tile related conversions.
#[derive(SystemParam)]
pub struct TileMapper<'w> {
    config: Res<'w, MapConfig>
}

The EntityRef trait is defined as:

/// EntityRef is a trait used to reference a single entity from multiple tiles
pub trait EntityRef {
    /// The `ComponentType` refers to the internal type of component the `Entity`
    /// refers to. This is especially useful information to have for building
    /// generic bevy `Query` parameters for systems.
    type ComponentType;

    /// This method returns the `UVec2` tile position of the entity set.
    fn tile(&self) -> UVec2;

    /// This method returns the `Entity` identifier.
    fn get(&self) -> Entity;
}

What went wrong

I'm getting 4 nearly identical errors all pointing to the #[derive(SystemParam)].

Here's the first error, followed by the 3 differences

error: lifetime may not live long enough
   --> src\tiles\tile_entities.rs:155:10
    |
155 | #[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`
    |
    = help: consider adding the following bound: `'w: 'w2`
    = note: requirement occurs because of the type `tile_entities::TileEntities<'_, '_, T>`, which makes the generic argument `'_` invariant
    = note: the struct `tile_entities::TileEntities<'w, 's, T>` is invariant over the parameter `'w`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
    = note: this error originates in the derive macro `SystemParam` (in Nightly builds, run with -Z macro-backtrace for more info)

Second:

...
155 | #[derive(SystemParam)]
    |          ^^^^^^^^^^^
    |          |
    |          lifetime `'s` defined here
    |          lifetime `'s2` defined here
    |          associated function was supposed to return data with lifetime `'s2` but it is returning data with lifetime `'s`
    |
    = help: consider adding the following bound: `'s: 's2`
...

Third:

...
155 | #[derive(SystemParam)]
    |          ^^^^^^^^^^^
    |          |
    |          lifetime `'s2` defined here
    |          lifetime `'s` defined here
    |          associated function was supposed to return data with lifetime `'s` but it is returning data with lifetime `'s2`
    |
    = help: consider adding the following bound: `'s2: 's`
...

Fourth:

...
155 | #[derive(SystemParam)]
    |          ^^^^^^^^^^^
    |          |
    |          lifetime `'w2` defined here
    |          lifetime `'w` defined here
    |          associated function was supposed to return data with lifetime `'w` but it is returning data with lifetime `'w2`
    |
    = help: consider adding the following bound: `'w2: 'w`
...

Additional information

I will work to see if I can get a reproducible case with less dependencies than the current project I am working in. Apologies if this is unclear in anyway. Will be happy to assist anyway possible!

Thanks for an incredible open source project

Activity

  1. added
    C-BugAn unexpected or incorrect behavior
    S-Needs-TriageThis issue needs to be labelled
    on Mar 24, 2023
  2. alice-i-cecile commented on Mar 24, 2023

    @alice-i-cecile
    Member

    What happens if you change those lifetimes to 'static?

  3. added
    A-ECSEntities, components, systems, and events
    and removed
    S-Needs-TriageThis issue needs to be labelled
    on Mar 24, 2023
  4. mbolt35 commented on Mar 24, 2023

    @mbolt35
    Author

    What happens if you change those lifetimes to 'static?

    @alice-i-cecile Just to be clear, do you mean a 'static constraint on 'w and 's? Or do you mean dropping the 'w and 's in my type and replacing with 'static? (I'm assuming there could be a difference there do to the way the param parses the struct body)

    Will give this a shot ASAP! Thanks for the response

  5. joseph-gio commented on Mar 24, 2023

    @joseph-gio
    Member

    Ah, seems like this issue pops up when a SystemParam has invariant lifetimes. This used to work, but it must have regressed during the 0.9-0.10 cycle (likely my fault) since none of our tests use invariant lifetimes.

    Here's a minimum reproducible example:

    #[derive(SystemParam)]
    pub struct InvariantParam<'w, 's> {
        set: ParamSet<'w, 's, (Query<'w, 's, ()>,)>,
    }

    Seems like this will be fixed by #8030.

  6. mbolt35 commented on Mar 25, 2023

    @mbolt35
    Author

    @alice-i-cecile Adding the 'static constraint on 'w and 's did seem to solve 2 of the errors, but looks as if now it's expecting a lifetime to outlive static:

    error[E0478]: lifetime bound not satisfied
       --> src\tiles\tile_entities.rs:155:10
        |
    155 | #[derive(SystemParam)]
        |          ^^^^^^^^^^^
        |
    note: lifetime parameter instantiated with the lifetime `'_w` as defined here
       --> src\tiles\tile_entities.rs:155:10
        |
    155 | #[derive(SystemParam)]
        |          ^^^^^^^^^^^
        = note: but lifetime parameter must outlive the static lifetime
        = note: this error originates in the derive macro `SystemParam` 
    

    and

    error[E0478]: lifetime bound not satisfied
       --> src\tiles\tile_entities.rs:155:10
        |
    155 | #[derive(SystemParam)]
        |          ^^^^^^^^^^^
        |
    note: lifetime parameter instantiated with the lifetime `'_s` as defined here
       --> src\tiles\tile_entities.rs:155:10
        |
    155 | #[derive(SystemParam)]
        |          ^^^^^^^^^^^
        = note: but lifetime parameter must outlive the static lifetime
        = note: this error originates in the derive macro `SystemParam`
    

    @JoJoJet Thanks for chiming in here, do you have any insight on when we might expect #8030 ? Possible there will be a patch release, or are we talking 0.11?

  7. joseph-gio commented on Mar 25, 2023

    @joseph-gio
    Member

    #8030 has a breaking change, so in order for the fix to land in a patch release I'd have to make a new PR with just that fix and nothing else. I can look into that later but I'm not sure how that would work out.

    As a temporary workaround, try changing just the lifetimes inside of the ParamSet to 'static:

    Meaning if you have a struct like this: ParamSet<'w, 's, Query<'w, 's, ...>>
    Change it to this: ParamSet<'w, 's, Query<'static, 'static, ...>>

    Changing the lifetimes in this specific way seems to make it compile.

  8. mbolt35 commented on Mar 25, 2023

    @mbolt35
    Author

    Meaning if you have a struct like this: ParamSet<'w, 's, Query<'w, 's, ...>> Change it to this: ParamSet<'w, 's, Query<'static, 'static, ...>>

    Changing the lifetimes in this specific way seems to make it compile.

    @JoJoJet Thank you, that works. Appreciate the help 👍

  9. joseph-gio commented on Mar 25, 2023

    @joseph-gio
    Member

    Happy I could help :)

  10. added this to the 0.10.1 milestone on Mar 28, 2023
  11. added a commit that references this issue on Mar 31, 2023
    218c30c
  12. added a commit that references this issue on Mar 31, 2023
    42732c0
  13. added a commit that references this issue on Sep 10, 2023
    7400f40
  14. added a commit that references this issue on Feb 5, 2024
    d9113cc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-BugAn unexpected or incorrect behavior

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions