Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler will infer incorrect life time for system param in system closure with inferred type #269

Open
Multirious opened this issue Feb 22, 2024 · 0 comments
Labels
C-enhancement New content that isn't covered already S-pitfalls Content in the Pitfalls chapter Z-medium medium task that needs moderate time investment

Comments

@Multirious
Copy link

Multirious commented Feb 22, 2024

Background

The problem started when I have:

fn system_a(query: Query<&MyComponent>) -> Option<i32> { ... }

which I wish to pipe to another system system_b if the output of system_a is Some(...):

fn system_b(input: In(i32)) { ... }

Afaik, there's currently no built in way in bevy for doing this so I tried to create a wrapper system closure:

|q| if let Some(x) = system_a(q) {
        system_b(In(x));
}

At first I thought this should work but this actually doesn't compiles and took me a whole day with another Bevy discord user _urben to figure out why.

The problem

After tinkering around, I found out that

// This compiles
|q: Query<&MyComponent>| if let Some(x) = system_a(q) {
        system_b(In(x));
}

// This also compiles
|q: Query<_>| if let Some(x) = system_a(q) {
        system_b(In(x));
}

// This doesn't compiles 
|q| if let Some(x) = system_a(q) {
        system_b(In(x));
}

The compiler error output is very hard to read though I figured that:
One that compiles:
fn (Query<&MyComponent>) has the life time for<'a> fn(Query<'_, '_, &'a MyComponent>).
One that doesn't compiles:
fn (_) has the life time fn(Query<'_, '_, &'_ MyComponent>).

We've tried to create a mockup in the playground but it doesn't work so we replicate it directly in Bevy with:

use bevy::prelude::*;

#[derive(Component)]
struct A;

fn my_system(a: Query<&A>) {}

fn main() {
    App::new()
        .add_systems(Update, my_system)
        .add_systems(Update, my_system as fn(Query<&A>))
        .add_systems(Update, my_system as fn(_)); // same error with closure
}

This problem seems to arise with other SystemParam too such as Res or ResMut and possibly others that have some lifetime in their type.

I can't find this problem to be documented any where so I submit this issue for it to be at least recorded for other user to see!

I've solved the original problem using CombinatorSystem, created my own PipeOrBreak type that took system that returns ControlFlow which I could map my Option into.
Here is the code that I'd like to share.

@inodentry inodentry added C-enhancement New content that isn't covered already S-pitfalls Content in the Pitfalls chapter Z-medium medium task that needs moderate time investment labels Mar 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement New content that isn't covered already S-pitfalls Content in the Pitfalls chapter Z-medium medium task that needs moderate time investment
Projects
None yet
Development

No branches or pull requests

2 participants