Skip to content

Using derive SystemParam with lifetimes <'w, 's> and not using 's is difficult #2711

Closed
@payload

Description

@payload

Bevy version

main Aug 21, 96e396fdd4e3d389c82680b5f8926ef8dbaabd76

What you did

I want to derive SystemParam for a struct which bundles resources but was not fully aware what the struct needs to adhere to.

#[derive(SystemParam)]
pub struct EntityAssets<'w> {
    boulder: Res<'w, BoulderAssets>,
    imp: Res<'w, ImpAssets>,
    smithery: Res<'w, SmitheryAssets>,
    storage: Res<'w, StorageAssets>,
}

What you expected to happen

It should compile.

What actually happened

Now it gets complicated. First of all I forget the second lifetime parameter in the struct, which is apparently needed.
Error message hints in the right direction but looks off in the placement hint:

use of undeclared lifetime name `'s`
undeclared lifetime rustcE0261
assets.rs(8, 25): consider introducing lifetime `'s` here: `'s, `

Next try pub struct EntityAssets<'w, 's> { raised the error message

parameter `'s` is never used
consider removing `'s`, referring to it in a field, or using a marker such as `PhantomData`

which is difficult to understand how to actually use PhantomData in this place.
This issue has the necessary hint how to use it in deriving SystemParam.

Next try:

#[derive(SystemParam)]
pub struct AllAssets<'w, 's> {
    #[system_param(ignore)]
    _secret: PhantomData<&'s ()>,

    boulder: Res<'w, BoulderAssets>,
    imp: Res<'w, ImpAssets>,
    smithery: Res<'w, SmitheryAssets>,
    storage: Res<'w, StorageAssets>,
}

But this will produce an absurde error message since the deriving macro is producing bad code:

mismatched types
expected mutable reference `&mut ResState<boulder::BoulderAssets>`
   found mutable reference `&mut ResState<imp::ImpAssets>`rustcE0308
mismatched types
expected mutable reference `&mut ResState<imp::ImpAssets>`
   found mutable reference `&mut ResState<smithery::SmitheryAssets>`rustcE0308
mismatched types
expected mutable reference `&mut ResState<smithery::SmitheryAssets>`
   found mutable reference `&mut ResState<entities::storage::StorageAssets>`rustcE0308
no field `4` on type `(ResState<boulder::BoulderAssets>, ResState<imp::ImpAssets>, ResState<smithery::SmitheryAssets>, ResState<entities::storage::StorageAssets>)`rustcE0609

The next try produced an actually compiling version:

#[derive(SystemParam)]
pub struct EntityAssets<'w, 's> {
    boulder: Res<'w, BoulderAssets>,
    imp: Res<'w, ImpAssets>,
    smithery: Res<'w, SmitheryAssets>,
    storage: Res<'w, StorageAssets>,

    #[system_param(ignore)]
    _secret: PhantomData<&'s ()>,
}

Additional information

I would suggest to make the second lifetime parameter optional in the processing macro, if possible for the resulting type.
The absurde error message hints to an order dependent processing in the derive macro. The processing of struct fields should be order independent.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-UsabilityA targeted quality-of-life change that makes Bevy easier to useS-Needs-DesignThis issue requires design work to think about how it would best be accomplished

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions