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

iter_combinations and family does not work on custom derived WorldQuery #5284

Closed
harudagondi opened this issue Jul 11, 2022 · 1 comment
Closed
Labels
A-ECS Entities, components, systems, and events C-Bug An unexpected or incorrect behavior

Comments

@harudagondi
Copy link
Member

Bevy version

main, 0.7

What you did

use bevy::{prelude::*, ecs::query::WorldQuery};

fn main() {}

#[derive(Component)]
struct Foo;

#[derive(WorldQuery)]
struct FooQuery<'a> {
    foo: &'a Foo,
}

fn system(query: Query<FooQuery>) {
    for [_, _] in query.iter_combinations::<2>() {}
}

What went wrong

I expected: no compiler error.

What actually happened: throws this error.

error[E0277]: the trait bound `FooQueryFetch<'_>: Clone` is not satisfied
  --> src\main.rs:14:19
   |
14 |     for [_, _] in query.iter_combinations::<2>() {}
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `FooQueryFetch<'_>`
   |
   = note: required because of the requirements on the impl of `Iterator` for `QueryCombinationIter<'_, '_, FooQuery<'_>, FooQueryFetch<'_>, (), 2_usize>`    
   = note: required because of the requirements on the impl of `IntoIterator` for `QueryCombinationIter<'_, '_, FooQuery<'_>, FooQueryFetch<'_>, (), 2_usize>`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `bevy_test_code` due to previous error
@harudagondi harudagondi added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Jul 11, 2022
@harudagondi
Copy link
Member Author

I think the solution is to derive Clone here:

#[doc(hidden)]
#visibility struct #fetch_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
#(#field_idents: #path::query::#fetch_type_alias::<'__w, #field_types>,)*
#(#ignored_field_idents: #ignored_field_types,)*
}

However, this would throw errors here:

#[test]
fn derived_worldqueries() {
let mut world = World::new();
world.spawn().insert_bundle((A(10), B(18), C(3), Sparse(4)));
world.spawn().insert_bundle((A(101), B(148), C(13)));
world.spawn().insert_bundle((A(51), B(46), Sparse(72)));
world.spawn().insert_bundle((A(398), C(6), Sparse(9)));
world.spawn().insert_bundle((B(11), C(28), Sparse(92)));
world.spawn().insert_bundle((C(18348), Sparse(101)));
world.spawn().insert_bundle((B(839), Sparse(5)));
world.spawn().insert_bundle((B(6721), C(122)));
world.spawn().insert_bundle((A(220), Sparse(63)));
world.spawn().insert_bundle((A(1092), C(382)));
world.spawn().insert_bundle((A(2058), B(3019)));
world.spawn().insert_bundle((B(38), C(8), Sparse(100)));
world.spawn().insert_bundle((A(111), C(52), Sparse(1)));
world.spawn().insert_bundle((A(599), B(39), Sparse(13)));
world.spawn().insert_bundle((A(55), B(66), C(77)));
world.spawn();
{
#[derive(WorldQuery)]
struct CustomAB {
a: &'static A,
b: &'static B,
}
let custom_param_data = world
.query::<CustomAB>()
.iter(&world)
.map(|item| (*item.a, *item.b))
.collect::<Vec<_>>();
let normal_data = world
.query::<(&A, &B)>()
.iter(&world)
.map(|(a, b)| (*a, *b))
.collect::<Vec<_>>();
assert_eq!(custom_param_data, normal_data);
}
{
#[derive(WorldQuery)]
struct FancyParam {
e: Entity,
b: &'static B,
opt: Option<&'static Sparse>,
}
let custom_param_data = world
.query::<FancyParam>()
.iter(&world)
.map(|fancy| (fancy.e, *fancy.b, fancy.opt.copied()))
.collect::<Vec<_>>();
let normal_data = world
.query::<(Entity, &B, Option<&Sparse>)>()
.iter(&world)
.map(|(e, b, opt)| (e, *b, opt.copied()))
.collect::<Vec<_>>();
assert_eq!(custom_param_data, normal_data);
}
{
#[derive(WorldQuery)]
struct MaybeBSparse {
blah: Option<(&'static B, &'static Sparse)>,
}
#[derive(WorldQuery)]
struct MatchEverything {
abcs: AnyOf<(&'static A, &'static B, &'static C)>,
opt_bsparse: MaybeBSparse,
}
let custom_param_data = world
.query::<MatchEverything>()
.iter(&world)
.map(
|MatchEverythingItem {
abcs: (a, b, c),
opt_bsparse: MaybeBSparseItem { blah: bsparse },
}| {
(
(a.copied(), b.copied(), c.copied()),
bsparse.map(|(b, sparse)| (*b, *sparse)),
)
},
)
.collect::<Vec<_>>();
let normal_data = world
.query::<(AnyOf<(&A, &B, &C)>, Option<(&B, &Sparse)>)>()
.iter(&world)
.map(|((a, b, c), bsparse)| {
(
(a.copied(), b.copied(), c.copied()),
bsparse.map(|(b, sparse)| (*b, *sparse)),
)
})
.collect::<Vec<_>>();
assert_eq!(custom_param_data, normal_data);
}
{
#[derive(WorldQuery)]
struct AOrBFilter {
a: Or<(With<A>, With<B>)>,
}
#[derive(WorldQuery)]
struct NoSparseThatsSlow {
no: Without<Sparse>,
}
let custom_param_entities = world
.query_filtered::<Entity, (AOrBFilter, NoSparseThatsSlow)>()
.iter(&world)
.collect::<Vec<_>>();
let normal_entities = world
.query_filtered::<Entity, (Or<(With<A>, With<B>)>, Without<Sparse>)>()
.iter(&world)
.collect::<Vec<_>>();
assert_eq!(custom_param_entities, normal_entities);
}
{
#[derive(WorldQuery)]
struct CSparseFilter {
tuple_structs_pls: With<C>,
ugh: With<Sparse>,
}
let custom_param_entities = world
.query_filtered::<Entity, CSparseFilter>()
.iter(&world)
.collect::<Vec<_>>();
let normal_entities = world
.query_filtered::<Entity, (With<C>, With<Sparse>)>()
.iter(&world)
.collect::<Vec<_>>();
assert_eq!(custom_param_entities, normal_entities);
}
{
#[derive(WorldQuery)]
struct WithoutComps {
_1: Without<A>,
_2: Without<B>,
_3: Without<C>,
}
let custom_param_entities = world
.query_filtered::<Entity, WithoutComps>()
.iter(&world)
.collect::<Vec<_>>();
let normal_entities = world
.query_filtered::<Entity, (Without<A>, Without<B>, Without<C>)>()
.iter(&world)
.collect::<Vec<_>>();
assert_eq!(custom_param_entities, normal_entities);
}
}

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events and removed S-Needs-Triage This issue needs to be labelled labels Jul 11, 2022
bors bot pushed a commit that referenced this issue Jul 13, 2022
# Objective

- `.iter_combinations_*()` cannot be used on custom derived `WorldQuery`, so this fixes that
- Fixes #5284

## Solution

- `#[derive(Clone)]` on the `Fetch` of the proc macro derive.
- `#[derive(Clone)]` for `AnyOf` to satisfy tests.
bors bot pushed a commit that referenced this issue Jul 13, 2022
# Objective

- `.iter_combinations_*()` cannot be used on custom derived `WorldQuery`, so this fixes that
- Fixes #5284

## Solution

- `#[derive(Clone)]` on the `Fetch` of the proc macro derive.
- `#[derive(Clone)]` for `AnyOf` to satisfy tests.
@bors bors bot closed this as completed in 1dbb1f7 Jul 13, 2022
inodentry pushed a commit to IyesGames/bevy that referenced this issue Aug 8, 2022
# Objective

- `.iter_combinations_*()` cannot be used on custom derived `WorldQuery`, so this fixes that
- Fixes bevyengine#5284

## Solution

- `#[derive(Clone)]` on the `Fetch` of the proc macro derive.
- `#[derive(Clone)]` for `AnyOf` to satisfy tests.
james7132 pushed a commit to james7132/bevy that referenced this issue Oct 28, 2022
# Objective

- `.iter_combinations_*()` cannot be used on custom derived `WorldQuery`, so this fixes that
- Fixes bevyengine#5284

## Solution

- `#[derive(Clone)]` on the `Fetch` of the proc macro derive.
- `#[derive(Clone)]` for `AnyOf` to satisfy tests.
ItsDoot pushed a commit to ItsDoot/bevy that referenced this issue Feb 1, 2023
# Objective

- `.iter_combinations_*()` cannot be used on custom derived `WorldQuery`, so this fixes that
- Fixes bevyengine#5284

## Solution

- `#[derive(Clone)]` on the `Fetch` of the proc macro derive.
- `#[derive(Clone)]` for `AnyOf` to satisfy tests.
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-Bug An unexpected or incorrect behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants