[Merged by Bors] - remove QF generics from all Query/State methods and types#5170
[Merged by Bors] - remove QF generics from all Query/State methods and types#5170BoxyUwU wants to merge 2 commits intobevyengine:mainfrom
Query/State methods and types#5170Conversation
james7132
left a comment
There was a problem hiding this comment.
I really like how this cleans up this area, but there are some pressing questions about how as_whatever works.
| pub fn iter_combinations<'w, 's, const K: usize>( | ||
| &'s mut self, | ||
| world: &'w World, | ||
| ) -> QueryCombinationIter<'w, 's, Q, F, K> { |
There was a problem hiding this comment.
this is a soundness fix, but it would be possible to make a much smaller PR solely fixing this soundness bug if we wanted (I would rather just do this PR though)
|
I like this a lot. It simplifies the trait soup substantially and will make contributing simple things (like Query methods) much less painful. |
| >( | ||
| &self, | ||
| ) -> &QueryState<NewQ, NewF> { | ||
| &*(self as *const QueryState<Q, F> as *const QueryState<NewQ, NewF>) |
There was a problem hiding this comment.
This does not spark joy.
I am however reasonably convinced that this is sound (I haven't dared look at the mess of query traits otherwise, but I don't think this API can ever have language level UB).
I feel like it should be possible to seperate the implementation of WorldQuery from the state in WorldQueryState, somehow.
At the very least, we could split out all the non-Q/F state fields into a sub-struct, so that they are not forced into the pessimisation of repr(C).
There was a problem hiding this comment.
oh splitting into a separate struct is really smart thanks
There was a problem hiding this comment.
I don't know what you mean by WorldQueryState theres no item named that anywhere in bevy_ecs.
There was a problem hiding this comment.
My apologies. I meant QueryState.
james7132
left a comment
There was a problem hiding this comment.
Just one final nit. This looks generally workable. Preferably I would have liked for the transmute-esque code to stay localized to bevy_ecs::query, but likely unavoidable given the current structure.
bdfcc0c to
f946a59
Compare
f946a59 to
8c03dfa
Compare
cart
left a comment
There was a problem hiding this comment.
This looks correct to me and I love the improved clarity of the apis, but I'd like to have one last conversation about the transmute behavior.
|
bors r+ |
# Objective remove `QF` generics from a bunch of types and methods on query related items. this has a few benefits: - simplifies type signatures `fn iter(&self) -> QueryIter<'_, 's, Q::ReadOnly, F::ReadOnly>` is (imo) conceptually simpler than `fn iter(&self) -> QueryIter<'_, 's, Q, ROQueryFetch<'_, Q>, F>` - `Fetch` is mostly an implementation detail but previously we had to expose it on every `iter` `get` etc method - Allows us to potentially in the future simplify the `WorldQuery` trait hierarchy by removing the `Fetch` trait ## Solution remove the `QF` generic and add a way to (unsafely) turn `&QueryState<Q1, F1>` into `&QueryState<Q2, F2>` --- ## Changelog/Migration Guide The `QF` generic was removed from various `Query` iterator types and some methods, you should update your code to use the type of the corresponding worldquery of the fetch type that was being used, or call `as_readonly`/`as_nop` to convert a querystate to the appropriate type. For example: `.get_single_unchecked_manual::<ROQueryFetch<Q>>(..)` -> `.as_readonly().get_single_unchecked_manual(..)` `my_field: QueryIter<'w, 's, Q, ROQueryFetch<'w, Q>, F>` -> `my_field: QueryIter<'w, 's, Q::ReadOnly, F::ReadOnly>`
|
Pull request successfully merged into main. Build succeeded: |
Query/State methods and typesQuery/State methods and types
…ne#5170) # Objective remove `QF` generics from a bunch of types and methods on query related items. this has a few benefits: - simplifies type signatures `fn iter(&self) -> QueryIter<'_, 's, Q::ReadOnly, F::ReadOnly>` is (imo) conceptually simpler than `fn iter(&self) -> QueryIter<'_, 's, Q, ROQueryFetch<'_, Q>, F>` - `Fetch` is mostly an implementation detail but previously we had to expose it on every `iter` `get` etc method - Allows us to potentially in the future simplify the `WorldQuery` trait hierarchy by removing the `Fetch` trait ## Solution remove the `QF` generic and add a way to (unsafely) turn `&QueryState<Q1, F1>` into `&QueryState<Q2, F2>` --- ## Changelog/Migration Guide The `QF` generic was removed from various `Query` iterator types and some methods, you should update your code to use the type of the corresponding worldquery of the fetch type that was being used, or call `as_readonly`/`as_nop` to convert a querystate to the appropriate type. For example: `.get_single_unchecked_manual::<ROQueryFetch<Q>>(..)` -> `.as_readonly().get_single_unchecked_manual(..)` `my_field: QueryIter<'w, 's, Q, ROQueryFetch<'w, Q>, F>` -> `my_field: QueryIter<'w, 's, Q::ReadOnly, F::ReadOnly>`
…ne#5170) # Objective remove `QF` generics from a bunch of types and methods on query related items. this has a few benefits: - simplifies type signatures `fn iter(&self) -> QueryIter<'_, 's, Q::ReadOnly, F::ReadOnly>` is (imo) conceptually simpler than `fn iter(&self) -> QueryIter<'_, 's, Q, ROQueryFetch<'_, Q>, F>` - `Fetch` is mostly an implementation detail but previously we had to expose it on every `iter` `get` etc method - Allows us to potentially in the future simplify the `WorldQuery` trait hierarchy by removing the `Fetch` trait ## Solution remove the `QF` generic and add a way to (unsafely) turn `&QueryState<Q1, F1>` into `&QueryState<Q2, F2>` --- ## Changelog/Migration Guide The `QF` generic was removed from various `Query` iterator types and some methods, you should update your code to use the type of the corresponding worldquery of the fetch type that was being used, or call `as_readonly`/`as_nop` to convert a querystate to the appropriate type. For example: `.get_single_unchecked_manual::<ROQueryFetch<Q>>(..)` -> `.as_readonly().get_single_unchecked_manual(..)` `my_field: QueryIter<'w, 's, Q, ROQueryFetch<'w, Q>, F>` -> `my_field: QueryIter<'w, 's, Q::ReadOnly, F::ReadOnly>`
…ne#5170) # Objective remove `QF` generics from a bunch of types and methods on query related items. this has a few benefits: - simplifies type signatures `fn iter(&self) -> QueryIter<'_, 's, Q::ReadOnly, F::ReadOnly>` is (imo) conceptually simpler than `fn iter(&self) -> QueryIter<'_, 's, Q, ROQueryFetch<'_, Q>, F>` - `Fetch` is mostly an implementation detail but previously we had to expose it on every `iter` `get` etc method - Allows us to potentially in the future simplify the `WorldQuery` trait hierarchy by removing the `Fetch` trait ## Solution remove the `QF` generic and add a way to (unsafely) turn `&QueryState<Q1, F1>` into `&QueryState<Q2, F2>` --- ## Changelog/Migration Guide The `QF` generic was removed from various `Query` iterator types and some methods, you should update your code to use the type of the corresponding worldquery of the fetch type that was being used, or call `as_readonly`/`as_nop` to convert a querystate to the appropriate type. For example: `.get_single_unchecked_manual::<ROQueryFetch<Q>>(..)` -> `.as_readonly().get_single_unchecked_manual(..)` `my_field: QueryIter<'w, 's, Q, ROQueryFetch<'w, Q>, F>` -> `my_field: QueryIter<'w, 's, Q::ReadOnly, F::ReadOnly>`
Objective
remove
QFgenerics from a bunch of types and methods on query related items. this has a few benefits:fn iter(&self) -> QueryIter<'_, 's, Q::ReadOnly, F::ReadOnly>is (imo) conceptually simpler thanfn iter(&self) -> QueryIter<'_, 's, Q, ROQueryFetch<'_, Q>, F>Fetchis mostly an implementation detail but previously we had to expose it on everyitergetetc methodWorldQuerytrait hierarchy by removing theFetchtraitSolution
remove the
QFgeneric and add a way to (unsafely) turn&QueryState<Q1, F1>into&QueryState<Q2, F2>Changelog/Migration Guide
The
QFgeneric was removed from variousQueryiterator types and some methods, you should update your code to use the type of the corresponding worldquery of the fetch type that was being used, or callas_readonly/as_nopto convert a querystate to the appropriate type. For example:.get_single_unchecked_manual::<ROQueryFetch<Q>>(..)->.as_readonly().get_single_unchecked_manual(..)my_field: QueryIter<'w, 's, Q, ROQueryFetch<'w, Q>, F>->my_field: QueryIter<'w, 's, Q::ReadOnly, F::ReadOnly>