-
So I have the following code which compiles and works: use bevy_ecs::prelude::*;
use bevy_ecs::query::{Fetch, WorldQuery, WorldQueryGats};
pub trait Foo: Component {
/// Components that `FooReader` should query for alongside the one implementing this trait
type Q: WorldQuery;
/// Do some computation depending on this component and the components in `Self::Q`
/// and then mutate `reader`. `data` is conceptually of type `Self::Q`, but
/// the lifetimes differ because the impl block has no way to spell the correct lifetime.
/// Introducing a lifetime parameter on `Foo` would allow the impl to specify lifetimes
/// so that `Self::Q` is identical to the type for `data` spelled out here, but there's no way
/// to promise to the compiler that all impls will actually do so
fn read_me<'w>(&self, reader: &mut FooReader, data: <<<Self::Q as WorldQuery>::ReadOnly as WorldQueryGats<'w>>::Fetch as Fetch<'w>>::Item);
}
pub struct FooReader(Vec<u32>);
impl FooReader {
/// Call `read_me` on all the `T`s and have them mutate this `FooReader`
fn read_all<T: Foo>(&mut self, world: &World, query: &mut QueryState<(&T, T::Q)>)
where
Self: Sized,
{
query.for_each(world, |(t, data)| {
t.read_me(self, data);
})
}
}
#[derive(Component)]
pub struct A(u32);
#[derive(Component)]
pub struct B(u32);
#[derive(Component)]
pub struct C(u32);
impl Foo for A {
// Lifetimes are 'static because there's no way to specify the correct lifetime
type Q = (&'static B, &'static C);
// Lifetime 'w here can actually be elided but I spell it out to show that the lifetimes don't match `Self::Q`
fn read_me<'w>(&self, reader: &mut FooReader, data: (&'w B, &'w C)) {
// compute A + B + C, store result in `reader`
reader.0.push(self.0 + data.0.0 + data.1.0);
}
} My question is if this is idiomatic or if there's a better way, and if I'm "allowed" to specify the type of
so I assume if GATS are added to Rust, the API would change, but in general this is an intended use of the public API? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
It's part of the more "advanced" public API, I think it's legitimate to use it. There is a helper type alias called pub type QueryItem<'w, Q> = <<Q as WorldQueryGats<'w>>::Fetch as Fetch<'w>>::Item; It is likely that bevy will take advantage of GATs as soon as they are stabilized, and change the API. Which is fine, bevy explicitly states that it will make major API breaking changes in the near future. |
Beta Was this translation helpful? Give feedback.
It's part of the more "advanced" public API, I think it's legitimate to use it. There is a helper type alias called
QueryItem
which you can take advantage of:It is likely that bevy will take advantage of GATs as soon as they are stabilized, and change the API. Which is fine, bevy explicitly states that it will make major API breaking changes in the near future.