`Option` and `Has` ignore sparse components in transmuted dense queries
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## Bevy version
[e155fe1d86](https://github.com/bevyengine/bevy/commit/e155fe1d86e3a21dd32832f2f1f6253593a4688f)
## What you did
Transmuted a `QueryState` to either `QueryState>` or `QueryState>`, where `S` is a sparse set component.
```rust
#[derive(Component)]
#[component(storage = "SparseSet")]
struct S;
let mut world = World::new();
world.spawn(S);
let mut query = world
.query::()
.transmute::<(Option<&S>, Has)>(&world);
let (option, has) = query.single(&world);
assert!(option.is_some());
assert!(has);
```
## What went wrong
The matched entity has an `S` component, but `Option<&S>` yields `None` and `Has` yields `false`.
## Additional information
`Option` and `Has` cache whether the component exists in `set_table` or `set_archetype`. To make this work for sparse set components, they set `IS_DENSE = false` and require sparse iteration. But `EntityMut` performs dense iteration, so the transmuted query is dense and calls `set_table`. `Option` and `Has` don't find the component in the table, since sparse set components are not stored in tables, and return `None` or `false` for the entire table.
#16396 would make this also occur in cases involving `FilteredEntityMut`.
Contributor guide
Assessment
This issue has not been assessed yet.