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] - Implement WorldQuery derive macro #2713

Closed
wants to merge 14 commits into from

Conversation

vladbat00
Copy link
Contributor

@vladbat00 vladbat00 commented Aug 22, 2021

Objective

This PR implements a derive macro that allows users to define their queries as structs with named fields.

Example

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct NumQuery<'w, T: Component, P: Component> {
    entity: Entity,
    u: UNumQuery<'w>,
    generic: GenericQuery<'w, T, P>,
}

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct UNumQuery<'w> {
    u_16: &'w u16,
    u_32_opt: Option<&'w u32>,
}

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct GenericQuery<'w, T: Component, P: Component> {
    generic: (&'w T, &'w P),
}

#[derive(WorldQuery)]
#[world_query(filter)]
struct NumQueryFilter<T: Component, P: Component> {
    _u_16: With<u16>,
    _u_32: With<u32>,
    _or: Or<(With<i16>, Changed<u16>, Added<u32>)>,
    _generic_tuple: (With<T>, With<P>),
    _without: Without<Option<u16>>,
    _tp: PhantomData<(T, P)>,
}

fn print_nums_readonly(query: Query<NumQuery<u64, i64>, NumQueryFilter<u64, i64>>) {
    for num in query.iter() {
        println!("{:#?}", num);
    }
}

#[derive(WorldQuery)]
#[world_query(mutable, derive(Debug))]
struct MutNumQuery<'w, T: Component, P: Component> {
    i_16: &'w mut i16,
    i_32_opt: Option<&'w mut i32>,
}

fn print_nums(mut query: Query<MutNumQuery, NumQueryFilter<u64, i64>>) {
    for num in query.iter_mut() {
        println!("{:#?}", num);
    }
}

TODOs:

  • Add support for &T and &mut T
    • Test
  • Add support for optional types
    • Test
  • Add support for Entity
    • Test
  • Add support for nested WorldQuery
    • Test
  • Add support for tuples
    • Test
  • Add support for generics
    • Test
  • Add support for query filters
    • Test
  • Add support for PhantomData
    • Test
  • Refactor read_world_query_field_type_info
  • Properly document readonly attribute for nested queries and the static assertions that guarantee safety
    • Test that we never implement ReadOnlyFetch for types that need mutable access
    • Test that we insert static assertions for nested WorldQuery that a user marked as readonly

@github-actions github-actions bot added the S-Needs-Triage This issue needs to be labelled label Aug 22, 2021
@vladbat00 vladbat00 force-pushed the derive-world-query branch 3 times, most recently from 248296b to 6add635 Compare August 23, 2021 19:26
@vladbat00 vladbat00 changed the title Implement WorldQuery derive macro Implement Fetch and FetchFilter derive macros Aug 23, 2021
@vladbat00 vladbat00 changed the title Implement Fetch and FetchFilter derive macros Implement Fetch and FilterFetch derive macros Aug 23, 2021
@vladbat00 vladbat00 force-pushed the derive-world-query branch 2 times, most recently from 02312ef to 30a3891 Compare August 23, 2021 20:19
@vladbat00 vladbat00 marked this pull request as ready for review August 23, 2021 20:19
examples/README.md Outdated Show resolved Hide resolved
@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible and removed S-Needs-Triage This issue needs to be labelled labels Aug 24, 2021
@vladbat00 vladbat00 force-pushed the derive-world-query branch 2 times, most recently from 0d1dbe3 to e33a2b0 Compare August 24, 2021 11:33
@vladbat00
Copy link
Contributor Author

Thanks for gist! I'll try to finish it. I've also noticed that you commented out the dead_code workaround, just wanted to clarify: did you comment it out cause it got broken or did you try to get rid of it completely?

@cart
Copy link
Member

cart commented Feb 7, 2022

I was planning on testing whether it was still necessary under the new impl. It feels like we shouldn't need it, given that we're using the same pattern as the built in Fetch impls.

@vladbat00
Copy link
Contributor Author

vladbat00 commented Feb 9, 2022

@cart done. I was even able to get rid of the TODO that I had previously left for the ReadOnly impl.
The dead_code workaround is still needed though, as original struct's fields are never read by anything (the Item types are used by the user's code instead).

crates/bevy_ecs/macros/src/fetch.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/macros/src/fetch.rs Show resolved Hide resolved
crates/bevy_ecs/macros/src/fetch.rs Outdated Show resolved Hide resolved
@cart
Copy link
Member

cart commented Feb 24, 2022

Looks good to me! Fantastic work!

@cart
Copy link
Member

cart commented Feb 24, 2022

bors r+

bors bot pushed a commit that referenced this pull request Feb 24, 2022
# Objective

- Closes #786
- Closes #2252
- Closes #2588

This PR implements a derive macro that allows users to define their queries as structs with named fields.

## Example

```rust
#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct NumQuery<'w, T: Component, P: Component> {
    entity: Entity,
    u: UNumQuery<'w>,
    generic: GenericQuery<'w, T, P>,
}

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct UNumQuery<'w> {
    u_16: &'w u16,
    u_32_opt: Option<&'w u32>,
}

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct GenericQuery<'w, T: Component, P: Component> {
    generic: (&'w T, &'w P),
}

#[derive(WorldQuery)]
#[world_query(filter)]
struct NumQueryFilter<T: Component, P: Component> {
    _u_16: With<u16>,
    _u_32: With<u32>,
    _or: Or<(With<i16>, Changed<u16>, Added<u32>)>,
    _generic_tuple: (With<T>, With<P>),
    _without: Without<Option<u16>>,
    _tp: PhantomData<(T, P)>,
}

fn print_nums_readonly(query: Query<NumQuery<u64, i64>, NumQueryFilter<u64, i64>>) {
    for num in query.iter() {
        println!("{:#?}", num);
    }
}

#[derive(WorldQuery)]
#[world_query(mutable, derive(Debug))]
struct MutNumQuery<'w, T: Component, P: Component> {
    i_16: &'w mut i16,
    i_32_opt: Option<&'w mut i32>,
}

fn print_nums(mut query: Query<MutNumQuery, NumQueryFilter<u64, i64>>) {
    for num in query.iter_mut() {
        println!("{:#?}", num);
    }
}
```

## TODOs:
- [x] Add support for `&T` and `&mut T`
  - [x] Test
- [x] Add support for optional types
  - [x] Test
- [x] Add support for `Entity`
  - [x] Test
- [x] Add support for nested `WorldQuery`
  - [x] Test
- [x] Add support for tuples
  - [x] Test
- [x] Add support for generics
  - [x] Test
- [x] Add support for query filters
  - [x] Test
- [x] Add support for `PhantomData`
  - [x] Test
- [x] Refactor `read_world_query_field_type_info`
- [x] Properly document `readonly` attribute for nested queries and the static assertions that guarantee safety
  - [x] Test that we never implement `ReadOnlyFetch` for types that need mutable access
  - [x] Test that we insert static assertions for nested `WorldQuery` that a user marked as readonly
@bors bors bot changed the title Implement WorldQuery derive macro [Merged by Bors] - Implement WorldQuery derive macro Feb 24, 2022
@bors bors bot closed this Feb 24, 2022
kurtkuehnert pushed a commit to kurtkuehnert/bevy that referenced this pull request Mar 6, 2022
# Objective

- Closes bevyengine#786
- Closes bevyengine#2252
- Closes bevyengine#2588

This PR implements a derive macro that allows users to define their queries as structs with named fields.

## Example

```rust
#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct NumQuery<'w, T: Component, P: Component> {
    entity: Entity,
    u: UNumQuery<'w>,
    generic: GenericQuery<'w, T, P>,
}

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct UNumQuery<'w> {
    u_16: &'w u16,
    u_32_opt: Option<&'w u32>,
}

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct GenericQuery<'w, T: Component, P: Component> {
    generic: (&'w T, &'w P),
}

#[derive(WorldQuery)]
#[world_query(filter)]
struct NumQueryFilter<T: Component, P: Component> {
    _u_16: With<u16>,
    _u_32: With<u32>,
    _or: Or<(With<i16>, Changed<u16>, Added<u32>)>,
    _generic_tuple: (With<T>, With<P>),
    _without: Without<Option<u16>>,
    _tp: PhantomData<(T, P)>,
}

fn print_nums_readonly(query: Query<NumQuery<u64, i64>, NumQueryFilter<u64, i64>>) {
    for num in query.iter() {
        println!("{:#?}", num);
    }
}

#[derive(WorldQuery)]
#[world_query(mutable, derive(Debug))]
struct MutNumQuery<'w, T: Component, P: Component> {
    i_16: &'w mut i16,
    i_32_opt: Option<&'w mut i32>,
}

fn print_nums(mut query: Query<MutNumQuery, NumQueryFilter<u64, i64>>) {
    for num in query.iter_mut() {
        println!("{:#?}", num);
    }
}
```

## TODOs:
- [x] Add support for `&T` and `&mut T`
  - [x] Test
- [x] Add support for optional types
  - [x] Test
- [x] Add support for `Entity`
  - [x] Test
- [x] Add support for nested `WorldQuery`
  - [x] Test
- [x] Add support for tuples
  - [x] Test
- [x] Add support for generics
  - [x] Test
- [x] Add support for query filters
  - [x] Test
- [x] Add support for `PhantomData`
  - [x] Test
- [x] Refactor `read_world_query_field_type_info`
- [x] Properly document `readonly` attribute for nested queries and the static assertions that guarantee safety
  - [x] Test that we never implement `ReadOnlyFetch` for types that need mutable access
  - [x] Test that we insert static assertions for nested `WorldQuery` that a user marked as readonly
@vladbat00 vladbat00 deleted the derive-world-query branch April 12, 2022 20:33
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-Feature A new feature, making something new possible S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Named Queries Component Bundle Queries #[derive(Query)]
7 participants