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

[Merged by Bors] - remove QF generics from all Query/State methods and types #5170

Closed
wants to merge 2 commits into from

Conversation

BoxyUwU
Copy link
Member

@BoxyUwU BoxyUwU commented Jul 1, 2022

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>

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Code-Quality A section of code that is hard to understand or change labels Jul 1, 2022
@alice-i-cecile alice-i-cecile self-requested a review July 1, 2022 19:04
Copy link
Member

@james7132 james7132 left a 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.

crates/bevy_ecs/src/query/fetch.rs Show resolved Hide resolved
crates/bevy_ecs/src/query/fetch.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/query/state.rs Show resolved Hide resolved
crates/bevy_ecs/src/query/state.rs Outdated Show resolved Hide resolved
@alice-i-cecile alice-i-cecile added the P-Unsound A bug that results in undefined compiler behavior label Jul 1, 2022
@@ -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> {
Copy link
Member Author

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)

@alice-i-cecile
Copy link
Member

I like this a lot. It simplifies the trait soup substantially and will make contributing simple things (like Query methods) much less painful.

@alice-i-cecile alice-i-cecile requested a review from cart July 1, 2022 19:58
@alice-i-cecile alice-i-cecile added the X-Controversial There is active debate or serious implications around merging this PR label Jul 1, 2022
crates/bevy_ecs/src/query/fetch.rs Outdated Show resolved Hide resolved
>(
&self,
) -> &QueryState<NewQ, NewF> {
&*(self as *const QueryState<Q, F> as *const QueryState<NewQ, NewF>)
Copy link
Member

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).

Copy link
Member Author

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

Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Member

@james7132 james7132 left a 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.

crates/bevy_ecs/src/query/iter.rs Outdated Show resolved Hide resolved
@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Jul 3, 2022
Copy link
Member

@cart cart left a 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.

crates/bevy_ecs/src/query/state.rs Show resolved Hide resolved
crates/bevy_ecs/src/query/fetch.rs Show resolved Hide resolved
@cart
Copy link
Member

cart commented Jul 19, 2022

bors r+

bors bot pushed a commit that referenced this pull request Jul 19, 2022
# 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>`
@bors bors bot changed the title remove QF generics from all Query/State methods and types [Merged by Bors] - remove QF generics from all Query/State methods and types Jul 19, 2022
@bors bors bot closed this Jul 19, 2022
inodentry pushed a commit to IyesGames/bevy that referenced this pull request Aug 8, 2022
…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>`
james7132 pushed a commit to james7132/bevy that referenced this pull request Oct 28, 2022
…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>`
ItsDoot pushed a commit to ItsDoot/bevy that referenced this pull request Feb 1, 2023
…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>`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Code-Quality A section of code that is hard to understand or change P-Unsound A bug that results in undefined compiler behavior S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it X-Controversial There is active debate or serious implications around merging this PR
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

6 participants