-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
[Merged by Bors] - remove QF generics from all Query/State
methods and types
#5170
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like how this cleans up this area, but there are some pressing questions about how as_whatever
works.
@@ -526,12 +561,13 @@ impl<Q: WorldQuery, F: WorldQuery> QueryState<Q, F> { | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh splitting into a separate struct is really smart thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My apologies. I meant QueryState
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
QF
generics 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>
Fetch
is mostly an implementation detail but previously we had to expose it on everyiter
get
etc methodWorldQuery
trait hierarchy by removing theFetch
traitSolution
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 variousQuery
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 callas_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>