Let query items borrow from query state to avoid needing to clone (#15396)

# Objective

Improve the performance of `FilteredEntity(Ref|Mut)` and
`Entity(Ref|Mut)Except`.

`FilteredEntityRef` needs an `Access<ComponentId>` to determine what
components it can access. There is one stored in the query state, but
query items cannot borrow from the state, so it has to `clone()` the
access for each row. Cloning the access involves memory allocations and
can be expensive.


## Solution

Let query items borrow from their query state.  

Add an `'s` lifetime to `WorldQuery::Item` and `WorldQuery::Fetch`,
similar to the one in `SystemParam`, and provide `&'s Self::State` to
the fetch so that it can borrow from the state.

Unfortunately, there are a few cases where we currently return query
items from temporary query states: the sorted iteration methods create a
temporary state to query the sort keys, and the
`EntityRef::components<Q>()` methods create a temporary state for their
query.

To allow these to continue to work with most `QueryData`
implementations, introduce a new subtrait `ReleaseStateQueryData` that
converts a `QueryItem<'w, 's>` to `QueryItem<'w, 'static>`, and is
implemented for everything except `FilteredEntity(Ref|Mut)` and
`Entity(Ref|Mut)Except`.

`#[derive(QueryData)]` will generate `ReleaseStateQueryData`
implementations that apply when all of the subqueries implement
`ReleaseStateQueryData`.

This PR does not actually change the implementation of
`FilteredEntity(Ref|Mut)` or `Entity(Ref|Mut)Except`! That will be done
as a follow-up PR so that the changes are easier to review. I have
pushed the changes as chescock/bevy#5.

## Testing

I ran performance traces of many_foxes, both against main and against
chescock/bevy#5, both including #15282. These changes do appear to make
generalized animation a bit faster:

(Red is main, yellow is chescock/bevy#5)

![image](https://github.com/user-attachments/assets/de900117-0c6a-431d-ab62-c013834f97a9)


## Migration Guide

The `WorldQuery::Item` and `WorldQuery::Fetch` associated types and the
`QueryItem` and `ROQueryItem` type aliases now have an additional
lifetime parameter corresponding to the `'s` lifetime in `Query`. Manual
implementations of `WorldQuery` will need to update the method
signatures to include the new lifetimes. Other uses of the types will
need to be updated to include a lifetime parameter, although it can
usually be passed as `'_`. In particular, `ROQueryItem` is used when
implementing `RenderCommand`.

Before: 

```rust
fn render<'w>(
    item: &P,
    view: ROQueryItem<'w, Self::ViewQuery>,
    entity: Option<ROQueryItem<'w, Self::ItemQuery>>,
    param: SystemParamItem<'w, '_, Self::Param>,
    pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult;
```

After: 

```rust
fn render<'w>(
    item: &P,
    view: ROQueryItem<'w, '_, Self::ViewQuery>,
    entity: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
    param: SystemParamItem<'w, '_, Self::Param>,
    pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult;
```

---

Methods on `QueryState` that take `&mut self` may now result in
conflicting borrows if the query items capture the lifetime of the
mutable reference. This affects `get()`, `iter()`, and others. To fix
the errors, first call `QueryState::update_archetypes()`, and then
replace a call `state.foo(world, param)` with
`state.query_manual(world).foo_inner(param)`. Alternately, you may be
able to restructure the code to call `state.query(world)` once and then
make multiple calls using the `Query`.

Before:
```rust
let mut state: QueryState<_, _> = ...;
let d1 = state.get(world, e1);
let d2 = state.get(world, e2); // Error: cannot borrow `state` as mutable more than once at a time
println!("{d1:?}");
println!("{d2:?}");
```

After: 
```rust
let mut state: QueryState<_, _> = ...;

state.update_archetypes(world);
let d1 = state.get_manual(world, e1);
let d2 = state.get_manual(world, e2);
// OR
state.update_archetypes(world);
let d1 = state.query(world).get_inner(e1);
let d2 = state.query(world).get_inner(e2);
// OR
let query = state.query(world);
let d1 = query.get_inner(e1);
let d1 = query.get_inner(e2);

println!("{d1:?}");
println!("{d2:?}");
```
This commit is contained in:
Chris Russell 2025-06-16 17:05:41 -04:00 committed by GitHub
parent e610badf6c
commit f7e112a3c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
56 changed files with 1166 additions and 626 deletions

View File

@ -847,7 +847,7 @@ impl ViewNode for SmaaNode {
view_smaa_uniform_offset, view_smaa_uniform_offset,
smaa_textures, smaa_textures,
view_smaa_bind_groups, view_smaa_bind_groups,
): QueryItem<'w, Self::ViewQuery>, ): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let pipeline_cache = world.resource::<PipelineCache>(); let pipeline_cache = world.resource::<PipelineCache>();

View File

@ -150,20 +150,22 @@ pub struct AssetChangedState<A: AsAssetId> {
#[expect(unsafe_code, reason = "WorldQuery is an unsafe trait.")] #[expect(unsafe_code, reason = "WorldQuery is an unsafe trait.")]
/// SAFETY: `ROQueryFetch<Self>` is the same as `QueryFetch<Self>` /// SAFETY: `ROQueryFetch<Self>` is the same as `QueryFetch<Self>`
unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> { unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> {
type Fetch<'w> = AssetChangedFetch<'w, A>; type Fetch<'w, 's> = AssetChangedFetch<'w, A>;
type State = AssetChangedState<A>; type State = AssetChangedState<A>;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
fetch: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort, 's> {
fetch fetch
} }
unsafe fn init_fetch<'w>( unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
state: &Self::State, state: &'s Self::State,
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) -> Self::Fetch<'w> { ) -> Self::Fetch<'w, 's> {
// SAFETY: // SAFETY:
// - `AssetChanges` is private and only accessed mutably in the `AssetEventSystems` system set. // - `AssetChanges` is private and only accessed mutably in the `AssetEventSystems` system set.
// - `resource_id` was obtained from the type ID of `AssetChanges<A::Asset>`. // - `resource_id` was obtained from the type ID of `AssetChanges<A::Asset>`.
@ -201,9 +203,9 @@ unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> {
const IS_DENSE: bool = <&A>::IS_DENSE; const IS_DENSE: bool = <&A>::IS_DENSE;
unsafe fn set_archetype<'w>( unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
state: &Self::State, state: &'s Self::State,
archetype: &'w Archetype, archetype: &'w Archetype,
table: &'w Table, table: &'w Table,
) { ) {
@ -215,7 +217,11 @@ unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> {
} }
} }
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) { unsafe fn set_table<'w, 's>(
fetch: &mut Self::Fetch<'w, 's>,
state: &Self::State,
table: &'w Table,
) {
if let Some(inner) = &mut fetch.inner { if let Some(inner) = &mut fetch.inner {
// SAFETY: We delegate to the inner `set_table` for `A` // SAFETY: We delegate to the inner `set_table` for `A`
unsafe { unsafe {
@ -265,7 +271,7 @@ unsafe impl<A: AsAssetId> QueryFilter for AssetChanged<A> {
#[inline] #[inline]
unsafe fn filter_fetch( unsafe fn filter_fetch(
fetch: &mut Self::Fetch<'_>, fetch: &mut Self::Fetch<'_, '_>,
entity: Entity, entity: Entity,
table_row: TableRow, table_row: TableRow,
) -> bool { ) -> bool {

View File

@ -121,7 +121,7 @@ impl ViewNode for BloomNode {
bloom_settings, bloom_settings,
upsampling_pipeline_ids, upsampling_pipeline_ids,
downsampling_pipeline_ids, downsampling_pipeline_ids,
): QueryItem<'w, Self::ViewQuery>, ): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
if bloom_settings.intensity == 0.0 { if bloom_settings.intensity == 0.0 {

View File

@ -227,7 +227,7 @@ impl ExtractComponent for Bloom {
type QueryFilter = With<Hdr>; type QueryFilter = With<Hdr>;
type Out = (Self, BloomUniforms); type Out = (Self, BloomUniforms);
fn extract_component((bloom, camera): QueryItem<'_, Self::QueryData>) -> Option<Self::Out> { fn extract_component((bloom, camera): QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
match ( match (
camera.physical_viewport_rect(), camera.physical_viewport_rect(),
camera.physical_viewport_size(), camera.physical_viewport_size(),

View File

@ -31,7 +31,7 @@ impl ViewNode for MainOpaquePass2dNode {
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
(camera, view, target, depth): QueryItem<'w, Self::ViewQuery>, (camera, view, target, depth): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let (Some(opaque_phases), Some(alpha_mask_phases)) = ( let (Some(opaque_phases), Some(alpha_mask_phases)) = (

View File

@ -28,7 +28,7 @@ impl ViewNode for MainTransparentPass2dNode {
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
(camera, view, target, depth): bevy_ecs::query::QueryItem<'w, Self::ViewQuery>, (camera, view, target, depth): bevy_ecs::query::QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let Some(transparent_phases) = let Some(transparent_phases) =

View File

@ -45,7 +45,7 @@ impl ViewNode for MainOpaquePass3dNode {
skybox_pipeline, skybox_pipeline,
skybox_bind_group, skybox_bind_group,
view_uniform_offset, view_uniform_offset,
): QueryItem<'w, Self::ViewQuery>, ): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let (Some(opaque_phases), Some(alpha_mask_phases)) = ( let (Some(opaque_phases), Some(alpha_mask_phases)) = (

View File

@ -36,7 +36,7 @@ impl ViewNode for EarlyDeferredGBufferPrepassNode {
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
view_query: QueryItem<'w, Self::ViewQuery>, view_query: QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
run_deferred_prepass( run_deferred_prepass(
@ -74,7 +74,7 @@ impl ViewNode for LateDeferredGBufferPrepassNode {
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
view_query: QueryItem<'w, Self::ViewQuery>, view_query: QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let (_, _, _, _, occlusion_culling, no_indirect_drawing) = view_query; let (_, _, _, _, occlusion_culling, no_indirect_drawing) = view_query;
@ -107,6 +107,7 @@ fn run_deferred_prepass<'w>(
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
(camera, extracted_view, view_depth_texture, view_prepass_textures, _, _): QueryItem< (camera, extracted_view, view_depth_texture, view_prepass_textures, _, _): QueryItem<
'w, 'w,
'_,
<LateDeferredGBufferPrepassNode as ViewNode>::ViewQuery, <LateDeferredGBufferPrepassNode as ViewNode>::ViewQuery,
>, >,
is_late: bool, is_late: bool,

View File

@ -352,7 +352,7 @@ impl ViewNode for DepthOfFieldNode {
view_bind_group_layouts, view_bind_group_layouts,
depth_of_field_uniform_index, depth_of_field_uniform_index,
auxiliary_dof_texture, auxiliary_dof_texture,
): QueryItem<'w, Self::ViewQuery>, ): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let pipeline_cache = world.resource::<PipelineCache>(); let pipeline_cache = world.resource::<PipelineCache>();

View File

@ -61,7 +61,7 @@ impl ViewNode for MsaaWritebackNode {
&self, &self,
_graph: &mut RenderGraphContext, _graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
(target, blit_pipeline_id, msaa): QueryItem<'w, Self::ViewQuery>, (target, blit_pipeline_id, msaa): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
if *msaa == Msaa::Off { if *msaa == Msaa::Off {

View File

@ -352,7 +352,7 @@ impl ViewNode for PostProcessingNode {
&self, &self,
_: &mut RenderGraphContext, _: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
(view_target, pipeline_id, chromatic_aberration, post_processing_uniform_buffer_offsets): QueryItem<'w, Self::ViewQuery>, (view_target, pipeline_id, chromatic_aberration, post_processing_uniform_buffer_offsets): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let pipeline_cache = world.resource::<PipelineCache>(); let pipeline_cache = world.resource::<PipelineCache>();
@ -485,7 +485,7 @@ impl ExtractComponent for ChromaticAberration {
type Out = ChromaticAberration; type Out = ChromaticAberration;
fn extract_component( fn extract_component(
chromatic_aberration: QueryItem<'_, Self::QueryData>, chromatic_aberration: QueryItem<'_, '_, Self::QueryData>,
) -> Option<Self::Out> { ) -> Option<Self::Out> {
// Skip the postprocessing phase entirely if the intensity is zero. // Skip the postprocessing phase entirely if the intensity is zero.
if chromatic_aberration.intensity > 0.0 { if chromatic_aberration.intensity > 0.0 {

View File

@ -36,7 +36,7 @@ impl ViewNode for EarlyPrepassNode {
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
view_query: QueryItem<'w, Self::ViewQuery>, view_query: QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
run_prepass(graph, render_context, view_query, world, "early prepass") run_prepass(graph, render_context, view_query, world, "early prepass")
@ -73,7 +73,7 @@ impl ViewNode for LatePrepassNode {
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
query: QueryItem<'w, Self::ViewQuery>, query: QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
// We only need a late prepass if we have occlusion culling and indirect // We only need a late prepass if we have occlusion culling and indirect
@ -112,7 +112,7 @@ fn run_prepass<'w>(
_, _,
_, _,
has_deferred, has_deferred,
): QueryItem<'w, <LatePrepassNode as ViewNode>::ViewQuery>, ): QueryItem<'w, '_, <LatePrepassNode as ViewNode>::ViewQuery>,
world: &'w World, world: &'w World,
label: &'static str, label: &'static str,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {

View File

@ -113,7 +113,9 @@ impl ExtractComponent for Skybox {
type QueryFilter = (); type QueryFilter = ();
type Out = (Self, SkyboxUniforms); type Out = (Self, SkyboxUniforms);
fn extract_component((skybox, exposure): QueryItem<'_, Self::QueryData>) -> Option<Self::Out> { fn extract_component(
(skybox, exposure): QueryItem<'_, '_, Self::QueryData>,
) -> Option<Self::Out> {
let exposure = exposure let exposure = exposure
.map(Exposure::exposure) .map(Exposure::exposure)
.unwrap_or_else(|| Exposure::default().exposure()); .unwrap_or_else(|| Exposure::default().exposure());

View File

@ -76,6 +76,7 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
let user_generics_with_world = { let user_generics_with_world = {
let mut generics = ast.generics; let mut generics = ast.generics;
generics.params.insert(0, parse_quote!('__w)); generics.params.insert(0, parse_quote!('__w));
generics.params.insert(0, parse_quote!('__s));
generics generics
}; };
let (user_impl_generics_with_world, user_ty_generics_with_world, user_where_clauses_with_world) = let (user_impl_generics_with_world, user_ty_generics_with_world, user_where_clauses_with_world) =
@ -256,11 +257,11 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
for #read_only_struct_name #user_ty_generics #user_where_clauses { for #read_only_struct_name #user_ty_generics #user_where_clauses {
const IS_READ_ONLY: bool = true; const IS_READ_ONLY: bool = true;
type ReadOnly = #read_only_struct_name #user_ty_generics; type ReadOnly = #read_only_struct_name #user_ty_generics;
type Item<'__w> = #read_only_item_struct_name #user_ty_generics_with_world; type Item<'__w, '__s> = #read_only_item_struct_name #user_ty_generics_with_world;
fn shrink<'__wlong: '__wshort, '__wshort>( fn shrink<'__wlong: '__wshort, '__wshort, '__s>(
item: Self::Item<'__wlong> item: Self::Item<'__wlong, '__s>
) -> Self::Item<'__wshort> { ) -> Self::Item<'__wshort, '__s> {
#read_only_item_struct_name { #read_only_item_struct_name {
#( #(
#field_idents: <#read_only_field_types>::shrink(item.#field_idents), #field_idents: <#read_only_field_types>::shrink(item.#field_idents),
@ -278,16 +279,28 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
/// SAFETY: we call `fetch` for each member that implements `Fetch`. /// SAFETY: we call `fetch` for each member that implements `Fetch`.
#[inline(always)] #[inline(always)]
unsafe fn fetch<'__w>( unsafe fn fetch<'__w, '__s>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>, _fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
_entity: #path::entity::Entity, _entity: #path::entity::Entity,
_table_row: #path::storage::TableRow, _table_row: #path::storage::TableRow,
) -> Self::Item<'__w> { ) -> Self::Item<'__w, '__s> {
Self::Item { Self::Item {
#(#field_idents: <#read_only_field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)* #(#field_idents: <#read_only_field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)*
} }
} }
} }
impl #user_impl_generics #path::query::ReleaseStateQueryData
for #read_only_struct_name #user_ty_generics #user_where_clauses
// Make these HRTBs with an unused lifetime parameter to allow trivial constraints
// See https://github.com/rust-lang/rust/issues/48214
where #(for<'__a> #field_types: #path::query::QueryData<ReadOnly: #path::query::ReleaseStateQueryData>,)* {
fn release_state<'__w>(_item: Self::Item<'__w, '_>) -> Self::Item<'__w, 'static> {
Self::Item {
#(#field_idents: <#read_only_field_types>::release_state(_item.#field_idents),)*
}
}
}
} }
} else { } else {
quote! {} quote! {}
@ -301,11 +314,11 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
for #struct_name #user_ty_generics #user_where_clauses { for #struct_name #user_ty_generics #user_where_clauses {
const IS_READ_ONLY: bool = #is_read_only; const IS_READ_ONLY: bool = #is_read_only;
type ReadOnly = #read_only_struct_name #user_ty_generics; type ReadOnly = #read_only_struct_name #user_ty_generics;
type Item<'__w> = #item_struct_name #user_ty_generics_with_world; type Item<'__w, '__s> = #item_struct_name #user_ty_generics_with_world;
fn shrink<'__wlong: '__wshort, '__wshort>( fn shrink<'__wlong: '__wshort, '__wshort, '__s>(
item: Self::Item<'__wlong> item: Self::Item<'__wlong, '__s>
) -> Self::Item<'__wshort> { ) -> Self::Item<'__wshort, '__s> {
#item_struct_name { #item_struct_name {
#( #(
#field_idents: <#field_types>::shrink(item.#field_idents), #field_idents: <#field_types>::shrink(item.#field_idents),
@ -323,17 +336,29 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
/// SAFETY: we call `fetch` for each member that implements `Fetch`. /// SAFETY: we call `fetch` for each member that implements `Fetch`.
#[inline(always)] #[inline(always)]
unsafe fn fetch<'__w>( unsafe fn fetch<'__w, '__s>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>, _fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
_entity: #path::entity::Entity, _entity: #path::entity::Entity,
_table_row: #path::storage::TableRow, _table_row: #path::storage::TableRow,
) -> Self::Item<'__w> { ) -> Self::Item<'__w, '__s> {
Self::Item { Self::Item {
#(#field_idents: <#field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)* #(#field_idents: <#field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)*
} }
} }
} }
impl #user_impl_generics #path::query::ReleaseStateQueryData
for #struct_name #user_ty_generics #user_where_clauses
// Make these HRTBs with an unused lifetime parameter to allow trivial constraints
// See https://github.com/rust-lang/rust/issues/48214
where #(for<'__a> #field_types: #path::query::ReleaseStateQueryData,)* {
fn release_state<'__w>(_item: Self::Item<'__w, '_>) -> Self::Item<'__w, 'static> {
Self::Item {
#(#field_idents: <#field_types>::release_state(_item.#field_idents),)*
}
}
}
#read_only_data_impl #read_only_data_impl
} }
}; };

View File

@ -23,6 +23,7 @@ pub fn derive_query_filter_impl(input: TokenStream) -> TokenStream {
let user_generics_with_world = { let user_generics_with_world = {
let mut generics = ast.generics; let mut generics = ast.generics;
generics.params.insert(0, parse_quote!('__w)); generics.params.insert(0, parse_quote!('__w));
generics.params.insert(0, parse_quote!('__s));
generics generics
}; };
let (user_impl_generics_with_world, user_ty_generics_with_world, user_where_clauses_with_world) = let (user_impl_generics_with_world, user_ty_generics_with_world, user_where_clauses_with_world) =
@ -101,8 +102,8 @@ pub fn derive_query_filter_impl(input: TokenStream) -> TokenStream {
#[allow(unused_variables)] #[allow(unused_variables)]
#[inline(always)] #[inline(always)]
unsafe fn filter_fetch<'__w>( unsafe fn filter_fetch<'__w, '__s>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>, _fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
_entity: #path::entity::Entity, _entity: #path::entity::Entity,
_table_row: #path::storage::TableRow, _table_row: #path::storage::TableRow,
) -> bool { ) -> bool {

View File

@ -34,14 +34,14 @@ pub(crate) fn item_struct(
#derive_macro_call #derive_macro_call
#item_attrs #item_attrs
#visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world { #visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
#(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::QueryData>::Item<'__w>,)* #(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::QueryData>::Item<'__w, '__s>,)*
} }
}, },
Fields::Unnamed(_) => quote! { Fields::Unnamed(_) => quote! {
#derive_macro_call #derive_macro_call
#item_attrs #item_attrs
#visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world( #visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world(
#( #field_visibilities <#field_types as #path::query::QueryData>::Item<'__w>, )* #( #field_visibilities <#field_types as #path::query::QueryData>::Item<'__w, '__s>, )*
); );
}, },
Fields::Unit => quote! { Fields::Unit => quote! {
@ -78,8 +78,8 @@ pub(crate) fn world_query_impl(
)] )]
#[automatically_derived] #[automatically_derived]
#visibility struct #fetch_struct_name #user_impl_generics_with_world #user_where_clauses_with_world { #visibility struct #fetch_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
#(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w>,)* #(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w, '__s>,)*
#marker_name: &'__w (), #marker_name: (&'__w(), &'__s()),
} }
impl #user_impl_generics_with_world Clone for #fetch_struct_name #user_ty_generics_with_world impl #user_impl_generics_with_world Clone for #fetch_struct_name #user_ty_generics_with_world
@ -87,7 +87,7 @@ pub(crate) fn world_query_impl(
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
#(#named_field_idents: self.#named_field_idents.clone(),)* #(#named_field_idents: self.#named_field_idents.clone(),)*
#marker_name: &(), #marker_name: (&(), &()),
} }
} }
} }
@ -96,26 +96,26 @@ pub(crate) fn world_query_impl(
unsafe impl #user_impl_generics #path::query::WorldQuery unsafe impl #user_impl_generics #path::query::WorldQuery
for #struct_name #user_ty_generics #user_where_clauses { for #struct_name #user_ty_generics #user_where_clauses {
type Fetch<'__w> = #fetch_struct_name #user_ty_generics_with_world; type Fetch<'__w, '__s> = #fetch_struct_name #user_ty_generics_with_world;
type State = #state_struct_name #user_ty_generics; type State = #state_struct_name #user_ty_generics;
fn shrink_fetch<'__wlong: '__wshort, '__wshort>( fn shrink_fetch<'__wlong: '__wshort, '__wshort, '__s>(
fetch: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wlong> fetch: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wlong, '__s>
) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wshort> { ) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wshort, '__s> {
#fetch_struct_name { #fetch_struct_name {
#( #(
#named_field_idents: <#field_types>::shrink_fetch(fetch.#named_field_idents), #named_field_idents: <#field_types>::shrink_fetch(fetch.#named_field_idents),
)* )*
#marker_name: &(), #marker_name: (&(), &()),
} }
} }
unsafe fn init_fetch<'__w>( unsafe fn init_fetch<'__w, '__s>(
_world: #path::world::unsafe_world_cell::UnsafeWorldCell<'__w>, _world: #path::world::unsafe_world_cell::UnsafeWorldCell<'__w>,
state: &Self::State, state: &'__s Self::State,
_last_run: #path::component::Tick, _last_run: #path::component::Tick,
_this_run: #path::component::Tick, _this_run: #path::component::Tick,
) -> <Self as #path::query::WorldQuery>::Fetch<'__w> { ) -> <Self as #path::query::WorldQuery>::Fetch<'__w, '__s> {
#fetch_struct_name { #fetch_struct_name {
#(#named_field_idents: #(#named_field_idents:
<#field_types>::init_fetch( <#field_types>::init_fetch(
@ -125,7 +125,7 @@ pub(crate) fn world_query_impl(
_this_run, _this_run,
), ),
)* )*
#marker_name: &(), #marker_name: (&(), &()),
} }
} }
@ -133,9 +133,9 @@ pub(crate) fn world_query_impl(
/// SAFETY: we call `set_archetype` for each member that implements `Fetch` /// SAFETY: we call `set_archetype` for each member that implements `Fetch`
#[inline] #[inline]
unsafe fn set_archetype<'__w>( unsafe fn set_archetype<'__w, '__s>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>, _fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
_state: &Self::State, _state: &'__s Self::State,
_archetype: &'__w #path::archetype::Archetype, _archetype: &'__w #path::archetype::Archetype,
_table: &'__w #path::storage::Table _table: &'__w #path::storage::Table
) { ) {
@ -144,9 +144,9 @@ pub(crate) fn world_query_impl(
/// SAFETY: we call `set_table` for each member that implements `Fetch` /// SAFETY: we call `set_table` for each member that implements `Fetch`
#[inline] #[inline]
unsafe fn set_table<'__w>( unsafe fn set_table<'__w, '__s>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>, _fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
_state: &Self::State, _state: &'__s Self::State,
_table: &'__w #path::storage::Table _table: &'__w #path::storage::Table
) { ) {
#(<#field_types>::set_table(&mut _fetch.#named_field_idents, &_state.#named_field_idents, _table);)* #(<#field_types>::set_table(&mut _fetch.#named_field_idents, &_state.#named_field_idents, _table);)*

View File

@ -141,7 +141,7 @@ pub struct NameOrEntity {
pub entity: Entity, pub entity: Entity,
} }
impl<'a> core::fmt::Display for NameOrEntityItem<'a> { impl<'w, 's> core::fmt::Display for NameOrEntityItem<'w, 's> {
#[inline(always)] #[inline(always)]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self.name { match self.name {
@ -274,9 +274,9 @@ mod tests {
let e2 = world.spawn(name.clone()).id(); let e2 = world.spawn(name.clone()).id();
let mut query = world.query::<NameOrEntity>(); let mut query = world.query::<NameOrEntity>();
let d1 = query.get(&world, e1).unwrap(); let d1 = query.get(&world, e1).unwrap();
let d2 = query.get(&world, e2).unwrap();
// NameOrEntity Display for entities without a Name should be {index}v{generation} // NameOrEntity Display for entities without a Name should be {index}v{generation}
assert_eq!(d1.to_string(), "0v0"); assert_eq!(d1.to_string(), "0v0");
let d2 = query.get(&world, e2).unwrap();
// NameOrEntity Display for entities with a Name should be the Name // NameOrEntity Display for entities with a Name should be the Name
assert_eq!(d2.to_string(), "MyName"); assert_eq!(d2.to_string(), "MyName");
} }

View File

@ -1078,7 +1078,7 @@ mod tests {
struct ChildOf(Entity); struct ChildOf(Entity);
impl<D> Traversal<D> for &'_ ChildOf { impl<D> Traversal<D> for &'_ ChildOf {
fn traverse(item: Self::Item<'_>, _: &D) -> Option<Entity> { fn traverse(item: Self::Item<'_, '_>, _: &D) -> Option<Entity> {
Some(item.0) Some(item.0)
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -103,7 +103,7 @@ pub unsafe trait QueryFilter: WorldQuery {
/// Must always be called _after_ [`WorldQuery::set_table`] or [`WorldQuery::set_archetype`]. `entity` and /// Must always be called _after_ [`WorldQuery::set_table`] or [`WorldQuery::set_archetype`]. `entity` and
/// `table_row` must be in the range of the current table and archetype. /// `table_row` must be in the range of the current table and archetype.
unsafe fn filter_fetch( unsafe fn filter_fetch(
fetch: &mut Self::Fetch<'_>, fetch: &mut Self::Fetch<'_, '_>,
entity: Entity, entity: Entity,
table_row: TableRow, table_row: TableRow,
) -> bool; ) -> bool;
@ -144,10 +144,13 @@ pub struct With<T>(PhantomData<T>);
/// `update_component_access` adds a `With` filter for `T`. /// `update_component_access` adds a `With` filter for `T`.
/// This is sound because `matches_component_set` returns whether the set contains the component. /// This is sound because `matches_component_set` returns whether the set contains the component.
unsafe impl<T: Component> WorldQuery for With<T> { unsafe impl<T: Component> WorldQuery for With<T> {
type Fetch<'w> = (); type Fetch<'w, 's> = ();
type State = ComponentId; type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
_: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort, 's> {
}
#[inline] #[inline]
unsafe fn init_fetch( unsafe fn init_fetch(
@ -204,7 +207,7 @@ unsafe impl<T: Component> QueryFilter for With<T> {
#[inline(always)] #[inline(always)]
unsafe fn filter_fetch( unsafe fn filter_fetch(
_fetch: &mut Self::Fetch<'_>, _fetch: &mut Self::Fetch<'_, '_>,
_entity: Entity, _entity: Entity,
_table_row: TableRow, _table_row: TableRow,
) -> bool { ) -> bool {
@ -244,10 +247,13 @@ pub struct Without<T>(PhantomData<T>);
/// `update_component_access` adds a `Without` filter for `T`. /// `update_component_access` adds a `Without` filter for `T`.
/// This is sound because `matches_component_set` returns whether the set does not contain the component. /// This is sound because `matches_component_set` returns whether the set does not contain the component.
unsafe impl<T: Component> WorldQuery for Without<T> { unsafe impl<T: Component> WorldQuery for Without<T> {
type Fetch<'w> = (); type Fetch<'w, 's> = ();
type State = ComponentId; type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
_: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort, 's> {
}
#[inline] #[inline]
unsafe fn init_fetch( unsafe fn init_fetch(
@ -304,7 +310,7 @@ unsafe impl<T: Component> QueryFilter for Without<T> {
#[inline(always)] #[inline(always)]
unsafe fn filter_fetch( unsafe fn filter_fetch(
_fetch: &mut Self::Fetch<'_>, _fetch: &mut Self::Fetch<'_, '_>,
_entity: Entity, _entity: Entity,
_table_row: TableRow, _table_row: TableRow,
) -> bool { ) -> bool {
@ -345,12 +351,12 @@ unsafe impl<T: Component> QueryFilter for Without<T> {
pub struct Or<T>(PhantomData<T>); pub struct Or<T>(PhantomData<T>);
#[doc(hidden)] #[doc(hidden)]
pub struct OrFetch<'w, T: WorldQuery> { pub struct OrFetch<'w, 's, T: WorldQuery> {
fetch: T::Fetch<'w>, fetch: T::Fetch<'w, 's>,
matches: bool, matches: bool,
} }
impl<T: WorldQuery> Clone for OrFetch<'_, T> { impl<T: WorldQuery> Clone for OrFetch<'_, '_, T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
fetch: self.fetch.clone(), fetch: self.fetch.clone(),
@ -384,10 +390,10 @@ macro_rules! impl_or_query_filter {
/// `update_component_access` replace the filters with a disjunction where every element is a conjunction of the previous filters and the filters of one of the subqueries. /// `update_component_access` replace the filters with a disjunction where every element is a conjunction of the previous filters and the filters of one of the subqueries.
/// This is sound because `matches_component_set` returns a disjunction of the results of the subqueries' implementations. /// This is sound because `matches_component_set` returns a disjunction of the results of the subqueries' implementations.
unsafe impl<$($filter: QueryFilter),*> WorldQuery for Or<($($filter,)*)> { unsafe impl<$($filter: QueryFilter),*> WorldQuery for Or<($($filter,)*)> {
type Fetch<'w> = ($(OrFetch<'w, $filter>,)*); type Fetch<'w, 's> = ($(OrFetch<'w, 's, $filter>,)*);
type State = ($($filter::State,)*); type State = ($($filter::State,)*);
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(fetch: Self::Fetch<'wlong, 's>) -> Self::Fetch<'wshort, 's> {
let ($($filter,)*) = fetch; let ($($filter,)*) = fetch;
($( ($(
OrFetch { OrFetch {
@ -400,7 +406,7 @@ macro_rules! impl_or_query_filter {
const IS_DENSE: bool = true $(&& $filter::IS_DENSE)*; const IS_DENSE: bool = true $(&& $filter::IS_DENSE)*;
#[inline] #[inline]
unsafe fn init_fetch<'w>(world: UnsafeWorldCell<'w>, state: &Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w> { unsafe fn init_fetch<'w, 's>(world: UnsafeWorldCell<'w>, state: &'s Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w, 's> {
let ($($filter,)*) = state; let ($($filter,)*) = state;
($(OrFetch { ($(OrFetch {
// SAFETY: The invariants are upheld by the caller. // SAFETY: The invariants are upheld by the caller.
@ -410,7 +416,7 @@ macro_rules! impl_or_query_filter {
} }
#[inline] #[inline]
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) { unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w, 's>, state: &'s Self::State, table: &'w Table) {
let ($($filter,)*) = fetch; let ($($filter,)*) = fetch;
let ($($state,)*) = state; let ($($state,)*) = state;
$( $(
@ -423,9 +429,9 @@ macro_rules! impl_or_query_filter {
} }
#[inline] #[inline]
unsafe fn set_archetype<'w>( unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
state: & Self::State, state: &'s Self::State,
archetype: &'w Archetype, archetype: &'w Archetype,
table: &'w Table table: &'w Table
) { ) {
@ -495,7 +501,7 @@ macro_rules! impl_or_query_filter {
#[inline(always)] #[inline(always)]
unsafe fn filter_fetch( unsafe fn filter_fetch(
fetch: &mut Self::Fetch<'_>, fetch: &mut Self::Fetch<'_, '_>,
entity: Entity, entity: Entity,
table_row: TableRow table_row: TableRow
) -> bool { ) -> bool {
@ -528,7 +534,7 @@ macro_rules! impl_tuple_query_filter {
#[inline(always)] #[inline(always)]
unsafe fn filter_fetch( unsafe fn filter_fetch(
fetch: &mut Self::Fetch<'_>, fetch: &mut Self::Fetch<'_, '_>,
entity: Entity, entity: Entity,
table_row: TableRow table_row: TableRow
) -> bool { ) -> bool {
@ -568,10 +574,13 @@ pub struct Allows<T>(PhantomData<T>);
/// `update_component_access` adds an archetypal filter for `T`. /// `update_component_access` adds an archetypal filter for `T`.
/// This is sound because it doesn't affect the query /// This is sound because it doesn't affect the query
unsafe impl<T: Component> WorldQuery for Allows<T> { unsafe impl<T: Component> WorldQuery for Allows<T> {
type Fetch<'w> = (); type Fetch<'w, 's> = ();
type State = ComponentId; type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
_: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort, 's> {
}
#[inline] #[inline]
unsafe fn init_fetch(_: UnsafeWorldCell, _: &ComponentId, _: Tick, _: Tick) {} unsafe fn init_fetch(_: UnsafeWorldCell, _: &ComponentId, _: Tick, _: Tick) {}
@ -609,7 +618,7 @@ unsafe impl<T: Component> QueryFilter for Allows<T> {
const IS_ARCHETYPAL: bool = true; const IS_ARCHETYPAL: bool = true;
#[inline(always)] #[inline(always)]
unsafe fn filter_fetch(_: &mut Self::Fetch<'_>, _: Entity, _: TableRow) -> bool { unsafe fn filter_fetch(_: &mut Self::Fetch<'_, '_>, _: Entity, _: TableRow) -> bool {
true true
} }
} }
@ -710,21 +719,23 @@ impl<T: Component> Clone for AddedFetch<'_, T> {
/// `update_component_access` adds a `With` filter for a component. /// `update_component_access` adds a `With` filter for a component.
/// This is sound because `matches_component_set` returns whether the set contains that component. /// This is sound because `matches_component_set` returns whether the set contains that component.
unsafe impl<T: Component> WorldQuery for Added<T> { unsafe impl<T: Component> WorldQuery for Added<T> {
type Fetch<'w> = AddedFetch<'w, T>; type Fetch<'w, 's> = AddedFetch<'w, T>;
type State = ComponentId; type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
fetch: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort, 's> {
fetch fetch
} }
#[inline] #[inline]
unsafe fn init_fetch<'w>( unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
&id: &ComponentId, &id: &'s ComponentId,
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) -> Self::Fetch<'w> { ) -> Self::Fetch<'w, 's> {
Self::Fetch::<'w> { Self::Fetch::<'w, 's> {
ticks: StorageSwitch::new( ticks: StorageSwitch::new(
|| None, || None,
|| { || {
@ -748,9 +759,9 @@ unsafe impl<T: Component> WorldQuery for Added<T> {
}; };
#[inline] #[inline]
unsafe fn set_archetype<'w>( unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
component_id: &ComponentId, component_id: &'s ComponentId,
_archetype: &'w Archetype, _archetype: &'w Archetype,
table: &'w Table, table: &'w Table,
) { ) {
@ -763,9 +774,9 @@ unsafe impl<T: Component> WorldQuery for Added<T> {
} }
#[inline] #[inline]
unsafe fn set_table<'w>( unsafe fn set_table<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
&component_id: &ComponentId, &component_id: &'s ComponentId,
table: &'w Table, table: &'w Table,
) { ) {
let table_ticks = Some( let table_ticks = Some(
@ -807,7 +818,7 @@ unsafe impl<T: Component> QueryFilter for Added<T> {
const IS_ARCHETYPAL: bool = false; const IS_ARCHETYPAL: bool = false;
#[inline(always)] #[inline(always)]
unsafe fn filter_fetch( unsafe fn filter_fetch(
fetch: &mut Self::Fetch<'_>, fetch: &mut Self::Fetch<'_, '_>,
entity: Entity, entity: Entity,
table_row: TableRow, table_row: TableRow,
) -> bool { ) -> bool {
@ -936,21 +947,23 @@ impl<T: Component> Clone for ChangedFetch<'_, T> {
/// `update_component_access` adds a `With` filter for a component. /// `update_component_access` adds a `With` filter for a component.
/// This is sound because `matches_component_set` returns whether the set contains that component. /// This is sound because `matches_component_set` returns whether the set contains that component.
unsafe impl<T: Component> WorldQuery for Changed<T> { unsafe impl<T: Component> WorldQuery for Changed<T> {
type Fetch<'w> = ChangedFetch<'w, T>; type Fetch<'w, 's> = ChangedFetch<'w, T>;
type State = ComponentId; type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
fetch: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort, 's> {
fetch fetch
} }
#[inline] #[inline]
unsafe fn init_fetch<'w>( unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
&id: &ComponentId, &id: &'s ComponentId,
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) -> Self::Fetch<'w> { ) -> Self::Fetch<'w, 's> {
Self::Fetch::<'w> { Self::Fetch::<'w, 's> {
ticks: StorageSwitch::new( ticks: StorageSwitch::new(
|| None, || None,
|| { || {
@ -974,9 +987,9 @@ unsafe impl<T: Component> WorldQuery for Changed<T> {
}; };
#[inline] #[inline]
unsafe fn set_archetype<'w>( unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
component_id: &ComponentId, component_id: &'s ComponentId,
_archetype: &'w Archetype, _archetype: &'w Archetype,
table: &'w Table, table: &'w Table,
) { ) {
@ -989,9 +1002,9 @@ unsafe impl<T: Component> WorldQuery for Changed<T> {
} }
#[inline] #[inline]
unsafe fn set_table<'w>( unsafe fn set_table<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
&component_id: &ComponentId, &component_id: &'s ComponentId,
table: &'w Table, table: &'w Table,
) { ) {
let table_ticks = Some( let table_ticks = Some(
@ -1034,7 +1047,7 @@ unsafe impl<T: Component> QueryFilter for Changed<T> {
#[inline(always)] #[inline(always)]
unsafe fn filter_fetch( unsafe fn filter_fetch(
fetch: &mut Self::Fetch<'_>, fetch: &mut Self::Fetch<'_, '_>,
entity: Entity, entity: Entity,
table_row: TableRow, table_row: TableRow,
) -> bool { ) -> bool {
@ -1133,20 +1146,22 @@ pub struct SpawnedFetch<'w> {
// SAFETY: WorldQuery impl accesses no components or component ticks // SAFETY: WorldQuery impl accesses no components or component ticks
unsafe impl WorldQuery for Spawned { unsafe impl WorldQuery for Spawned {
type Fetch<'w> = SpawnedFetch<'w>; type Fetch<'w, 's> = SpawnedFetch<'w>;
type State = (); type State = ();
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
fetch: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort, 's> {
fetch fetch
} }
#[inline] #[inline]
unsafe fn init_fetch<'w>( unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
_state: &(), _state: &'s (),
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) -> Self::Fetch<'w> { ) -> Self::Fetch<'w, 's> {
SpawnedFetch { SpawnedFetch {
entities: world.entities(), entities: world.entities(),
last_run, last_run,
@ -1157,16 +1172,21 @@ unsafe impl WorldQuery for Spawned {
const IS_DENSE: bool = true; const IS_DENSE: bool = true;
#[inline] #[inline]
unsafe fn set_archetype<'w>( unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>, _fetch: &mut Self::Fetch<'w, 's>,
_state: &(), _state: &'s (),
_archetype: &'w Archetype, _archetype: &'w Archetype,
_table: &'w Table, _table: &'w Table,
) { ) {
} }
#[inline] #[inline]
unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &(), _table: &'w Table) {} unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w, 's>,
_state: &'s (),
_table: &'w Table,
) {
}
#[inline] #[inline]
fn update_component_access(_state: &(), _access: &mut FilteredAccess<ComponentId>) {} fn update_component_access(_state: &(), _access: &mut FilteredAccess<ComponentId>) {}
@ -1188,7 +1208,7 @@ unsafe impl QueryFilter for Spawned {
#[inline(always)] #[inline(always)]
unsafe fn filter_fetch( unsafe fn filter_fetch(
fetch: &mut Self::Fetch<'_>, fetch: &mut Self::Fetch<'_, '_>,
entity: Entity, entity: Entity,
_table_row: TableRow, _table_row: TableRow,
) -> bool { ) -> bool {

View File

@ -140,7 +140,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
range: Option<Range<u32>>, range: Option<Range<u32>>,
) -> B ) -> B
where where
Func: FnMut(B, D::Item<'w>) -> B, Func: FnMut(B, D::Item<'w, 's>) -> B,
{ {
if self.cursor.is_dense { if self.cursor.is_dense {
// SAFETY: `self.cursor.is_dense` is true, so storage ids are guaranteed to be table ids. // SAFETY: `self.cursor.is_dense` is true, so storage ids are guaranteed to be table ids.
@ -203,7 +203,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
rows: Range<u32>, rows: Range<u32>,
) -> B ) -> B
where where
Func: FnMut(B, D::Item<'w>) -> B, Func: FnMut(B, D::Item<'w, 's>) -> B,
{ {
if table.is_empty() { if table.is_empty() {
return accum; return accum;
@ -255,7 +255,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
indices: Range<u32>, indices: Range<u32>,
) -> B ) -> B
where where
Func: FnMut(B, D::Item<'w>) -> B, Func: FnMut(B, D::Item<'w, 's>) -> B,
{ {
if archetype.is_empty() { if archetype.is_empty() {
return accum; return accum;
@ -324,7 +324,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
rows: Range<u32>, rows: Range<u32>,
) -> B ) -> B
where where
Func: FnMut(B, D::Item<'w>) -> B, Func: FnMut(B, D::Item<'w, 's>) -> B,
{ {
if archetype.is_empty() { if archetype.is_empty() {
return accum; return accum;
@ -492,7 +492,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w, impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w,
> >
where where
for<'lw> L::Item<'lw>: Ord, for<'lw, 'ls> L::Item<'lw, 'ls>: Ord,
{ {
self.sort_impl::<L>(|keyed_query| keyed_query.sort()) self.sort_impl::<L>(|keyed_query| keyed_query.sort())
} }
@ -549,7 +549,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w, impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w,
> >
where where
for<'lw> L::Item<'lw>: Ord, for<'lw, 'ls> L::Item<'lw, 'ls>: Ord,
{ {
self.sort_impl::<L>(|keyed_query| keyed_query.sort_unstable()) self.sort_impl::<L>(|keyed_query| keyed_query.sort_unstable())
} }
@ -605,7 +605,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
/// ``` /// ```
pub fn sort_by<L: ReadOnlyQueryData + 'w>( pub fn sort_by<L: ReadOnlyQueryData + 'w>(
self, self,
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
) -> QuerySortedIter< ) -> QuerySortedIter<
'w, 'w,
's, 's,
@ -637,7 +637,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
/// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty.
pub fn sort_unstable_by<L: ReadOnlyQueryData + 'w>( pub fn sort_unstable_by<L: ReadOnlyQueryData + 'w>(
self, self,
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
) -> QuerySortedIter< ) -> QuerySortedIter<
'w, 'w,
's, 's,
@ -729,7 +729,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
/// ``` /// ```
pub fn sort_by_key<L: ReadOnlyQueryData + 'w, K>( pub fn sort_by_key<L: ReadOnlyQueryData + 'w, K>(
self, self,
mut f: impl FnMut(&L::Item<'_>) -> K, mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedIter< ) -> QuerySortedIter<
'w, 'w,
's, 's,
@ -762,7 +762,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
/// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty.
pub fn sort_unstable_by_key<L: ReadOnlyQueryData + 'w, K>( pub fn sort_unstable_by_key<L: ReadOnlyQueryData + 'w, K>(
self, self,
mut f: impl FnMut(&L::Item<'_>) -> K, mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedIter< ) -> QuerySortedIter<
'w, 'w,
's, 's,
@ -797,7 +797,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
/// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty.
pub fn sort_by_cached_key<L: ReadOnlyQueryData + 'w, K>( pub fn sort_by_cached_key<L: ReadOnlyQueryData + 'w, K>(
self, self,
mut f: impl FnMut(&L::Item<'_>) -> K, mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedIter< ) -> QuerySortedIter<
'w, 'w,
's, 's,
@ -827,7 +827,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
/// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty.
fn sort_impl<L: ReadOnlyQueryData + 'w>( fn sort_impl<L: ReadOnlyQueryData + 'w>(
self, self,
f: impl FnOnce(&mut Vec<(L::Item<'_>, NeutralOrd<Entity>)>), f: impl FnOnce(&mut Vec<(L::Item<'_, '_>, NeutralOrd<Entity>)>),
) -> QuerySortedIter< ) -> QuerySortedIter<
'w, 'w,
's, 's,
@ -856,7 +856,11 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
.map(|(key, entity)| (key, NeutralOrd(entity))) .map(|(key, entity)| (key, NeutralOrd(entity)))
.collect(); .collect();
f(&mut keyed_query); f(&mut keyed_query);
let entity_iter = keyed_query.into_iter().map(|(.., entity)| entity.0); let entity_iter = keyed_query
.into_iter()
.map(|(.., entity)| entity.0)
.collect::<Vec<_>>()
.into_iter();
// SAFETY: // SAFETY:
// `self.world` has permission to access the required components. // `self.world` has permission to access the required components.
// Each lens query item is dropped before the respective actual query item is accessed. // Each lens query item is dropped before the respective actual query item is accessed.
@ -873,7 +877,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
} }
impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for QueryIter<'w, 's, D, F> { impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for QueryIter<'w, 's, D, F> {
type Item = D::Item<'w>; type Item = D::Item<'w, 's>;
#[inline(always)] #[inline(always)]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -975,7 +979,7 @@ where
entities: &'w Entities, entities: &'w Entities,
tables: &'w Tables, tables: &'w Tables,
archetypes: &'w Archetypes, archetypes: &'w Archetypes,
fetch: D::Fetch<'w>, fetch: D::Fetch<'w, 's>,
query_state: &'s QueryState<D, F>, query_state: &'s QueryState<D, F>,
} }
@ -1010,7 +1014,7 @@ where
/// # Safety /// # Safety
/// `entity` must stem from `self.entity_iter`, and not have been passed before. /// `entity` must stem from `self.entity_iter`, and not have been passed before.
#[inline(always)] #[inline(always)]
unsafe fn fetch_next(&mut self, entity: Entity) -> D::Item<'w> { unsafe fn fetch_next(&mut self, entity: Entity) -> D::Item<'w, 's> {
let (location, archetype, table); let (location, archetype, table);
// SAFETY: // SAFETY:
// `tables` and `archetypes` belong to the same world that the [`QueryIter`] // `tables` and `archetypes` belong to the same world that the [`QueryIter`]
@ -1048,7 +1052,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Iterator
where where
I: Iterator<Item = Entity>, I: Iterator<Item = Entity>,
{ {
type Item = D::Item<'w>; type Item = D::Item<'w, 's>;
#[inline(always)] #[inline(always)]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -1119,8 +1123,8 @@ pub struct QueryManyIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item:
entities: &'w Entities, entities: &'w Entities,
tables: &'w Tables, tables: &'w Tables,
archetypes: &'w Archetypes, archetypes: &'w Archetypes,
fetch: D::Fetch<'w>, fetch: D::Fetch<'w, 's>,
filter: F::Fetch<'w>, filter: F::Fetch<'w, 's>,
query_state: &'s QueryState<D, F>, query_state: &'s QueryState<D, F>,
} }
@ -1167,10 +1171,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
entities: &'w Entities, entities: &'w Entities,
tables: &'w Tables, tables: &'w Tables,
archetypes: &'w Archetypes, archetypes: &'w Archetypes,
fetch: &mut D::Fetch<'w>, fetch: &mut D::Fetch<'w, 's>,
filter: &mut F::Fetch<'w>, filter: &mut F::Fetch<'w, 's>,
query_state: &'s QueryState<D, F>, query_state: &'s QueryState<D, F>,
) -> Option<D::Item<'w>> { ) -> Option<D::Item<'w, 's>> {
for entity_borrow in entity_iter { for entity_borrow in entity_iter {
let entity = entity_borrow.entity(); let entity = entity_borrow.entity();
let Some(location) = entities.get(entity) else { let Some(location) = entities.get(entity) else {
@ -1212,7 +1216,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// Get next result from the query /// Get next result from the query
#[inline(always)] #[inline(always)]
pub fn fetch_next(&mut self) -> Option<D::Item<'_>> { pub fn fetch_next(&mut self) -> Option<D::Item<'_, 's>> {
// SAFETY: // SAFETY:
// All arguments stem from self. // All arguments stem from self.
// We are limiting the returned reference to self, // We are limiting the returned reference to self,
@ -1336,7 +1340,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w, impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w,
> >
where where
for<'lw> L::Item<'lw>: Ord, for<'lw, 'ls> L::Item<'lw, 'ls>: Ord,
{ {
self.sort_impl::<L>(|keyed_query| keyed_query.sort()) self.sort_impl::<L>(|keyed_query| keyed_query.sort())
} }
@ -1394,7 +1398,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w, impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w,
> >
where where
for<'lw> L::Item<'lw>: Ord, for<'lw, 'ls> L::Item<'lw, 'ls>: Ord,
{ {
self.sort_impl::<L>(|keyed_query| keyed_query.sort_unstable()) self.sort_impl::<L>(|keyed_query| keyed_query.sort_unstable())
} }
@ -1451,7 +1455,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// ``` /// ```
pub fn sort_by<L: ReadOnlyQueryData + 'w>( pub fn sort_by<L: ReadOnlyQueryData + 'w>(
self, self,
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
) -> QuerySortedManyIter< ) -> QuerySortedManyIter<
'w, 'w,
's, 's,
@ -1482,7 +1486,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// called on [`QueryManyIter`] before. /// called on [`QueryManyIter`] before.
pub fn sort_unstable_by<L: ReadOnlyQueryData + 'w>( pub fn sort_unstable_by<L: ReadOnlyQueryData + 'w>(
self, self,
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
) -> QuerySortedManyIter< ) -> QuerySortedManyIter<
'w, 'w,
's, 's,
@ -1576,7 +1580,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// ``` /// ```
pub fn sort_by_key<L: ReadOnlyQueryData + 'w, K>( pub fn sort_by_key<L: ReadOnlyQueryData + 'w, K>(
self, self,
mut f: impl FnMut(&L::Item<'_>) -> K, mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedManyIter< ) -> QuerySortedManyIter<
'w, 'w,
's, 's,
@ -1608,7 +1612,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// called on [`QueryManyIter`] before. /// called on [`QueryManyIter`] before.
pub fn sort_unstable_by_key<L: ReadOnlyQueryData + 'w, K>( pub fn sort_unstable_by_key<L: ReadOnlyQueryData + 'w, K>(
self, self,
mut f: impl FnMut(&L::Item<'_>) -> K, mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedManyIter< ) -> QuerySortedManyIter<
'w, 'w,
's, 's,
@ -1642,7 +1646,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// called on [`QueryManyIter`] before. /// called on [`QueryManyIter`] before.
pub fn sort_by_cached_key<L: ReadOnlyQueryData + 'w, K>( pub fn sort_by_cached_key<L: ReadOnlyQueryData + 'w, K>(
self, self,
mut f: impl FnMut(&L::Item<'_>) -> K, mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedManyIter< ) -> QuerySortedManyIter<
'w, 'w,
's, 's,
@ -1671,7 +1675,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// called on [`QueryManyIter`] before. /// called on [`QueryManyIter`] before.
fn sort_impl<L: ReadOnlyQueryData + 'w>( fn sort_impl<L: ReadOnlyQueryData + 'w>(
self, self,
f: impl FnOnce(&mut Vec<(L::Item<'_>, NeutralOrd<Entity>)>), f: impl FnOnce(&mut Vec<(L::Item<'_, '_>, NeutralOrd<Entity>)>),
) -> QuerySortedManyIter< ) -> QuerySortedManyIter<
'w, 'w,
's, 's,
@ -1721,7 +1725,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator<Item: EntityEq
{ {
/// Get next result from the back of the query /// Get next result from the back of the query
#[inline(always)] #[inline(always)]
pub fn fetch_next_back(&mut self) -> Option<D::Item<'_>> { pub fn fetch_next_back(&mut self) -> Option<D::Item<'_, 's>> {
// SAFETY: // SAFETY:
// All arguments stem from self. // All arguments stem from self.
// We are limiting the returned reference to self, // We are limiting the returned reference to self,
@ -1745,7 +1749,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator<Item: EntityEq
impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>> Iterator impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>> Iterator
for QueryManyIter<'w, 's, D, F, I> for QueryManyIter<'w, 's, D, F, I>
{ {
type Item = D::Item<'w>; type Item = D::Item<'w, 's>;
#[inline(always)] #[inline(always)]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -1861,7 +1865,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator>
impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> Iterator impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> Iterator
for QueryManyUniqueIter<'w, 's, D, F, I> for QueryManyUniqueIter<'w, 's, D, F, I>
{ {
type Item = D::Item<'w>; type Item = D::Item<'w, 's>;
#[inline(always)] #[inline(always)]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -1915,7 +1919,7 @@ pub struct QuerySortedManyIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator
entities: &'w Entities, entities: &'w Entities,
tables: &'w Tables, tables: &'w Tables,
archetypes: &'w Archetypes, archetypes: &'w Archetypes,
fetch: D::Fetch<'w>, fetch: D::Fetch<'w, 's>,
query_state: &'s QueryState<D, F>, query_state: &'s QueryState<D, F>,
} }
@ -1954,7 +1958,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item = Entity>>
/// It is always safe for shared access. /// It is always safe for shared access.
/// `entity` must stem from `self.entity_iter`, and not have been passed before. /// `entity` must stem from `self.entity_iter`, and not have been passed before.
#[inline(always)] #[inline(always)]
unsafe fn fetch_next_aliased_unchecked(&mut self, entity: Entity) -> D::Item<'w> { unsafe fn fetch_next_aliased_unchecked(&mut self, entity: Entity) -> D::Item<'w, 's> {
let (location, archetype, table); let (location, archetype, table);
// SAFETY: // SAFETY:
// `tables` and `archetypes` belong to the same world that the [`QueryIter`] // `tables` and `archetypes` belong to the same world that the [`QueryIter`]
@ -1988,7 +1992,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item = Entity>>
/// Get next result from the query /// Get next result from the query
#[inline(always)] #[inline(always)]
pub fn fetch_next(&mut self) -> Option<D::Item<'_>> { pub fn fetch_next(&mut self) -> Option<D::Item<'_, 's>> {
let entity = self.entity_iter.next()?; let entity = self.entity_iter.next()?;
// SAFETY: // SAFETY:
@ -2007,7 +2011,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator<Item = Entity>
{ {
/// Get next result from the query /// Get next result from the query
#[inline(always)] #[inline(always)]
pub fn fetch_next_back(&mut self) -> Option<D::Item<'_>> { pub fn fetch_next_back(&mut self) -> Option<D::Item<'_, 's>> {
let entity = self.entity_iter.next_back()?; let entity = self.entity_iter.next_back()?;
// SAFETY: // SAFETY:
@ -2024,7 +2028,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator<Item = Entity>
impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator<Item = Entity>> Iterator impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator<Item = Entity>> Iterator
for QuerySortedManyIter<'w, 's, D, F, I> for QuerySortedManyIter<'w, 's, D, F, I>
{ {
type Item = D::Item<'w>; type Item = D::Item<'w, 's>;
#[inline(always)] #[inline(always)]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -2185,7 +2189,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter<
/// . /// .
/// It is always safe for shared access. /// It is always safe for shared access.
#[inline] #[inline]
unsafe fn fetch_next_aliased_unchecked(&mut self) -> Option<[D::Item<'w>; K]> { unsafe fn fetch_next_aliased_unchecked(&mut self) -> Option<[D::Item<'w, 's>; K]> {
// PERF: can speed up the following code using `cursor.remaining()` instead of `next_item.is_none()` // PERF: can speed up the following code using `cursor.remaining()` instead of `next_item.is_none()`
// when D::IS_ARCHETYPAL && F::IS_ARCHETYPAL // when D::IS_ARCHETYPAL && F::IS_ARCHETYPAL
// //
@ -2211,9 +2215,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter<
} }
} }
let mut values = MaybeUninit::<[D::Item<'w>; K]>::uninit(); let mut values = MaybeUninit::<[D::Item<'w, 's>; K]>::uninit();
let ptr = values.as_mut_ptr().cast::<D::Item<'w>>(); let ptr = values.as_mut_ptr().cast::<D::Item<'w, 's>>();
for (offset, cursor) in self.cursors.iter_mut().enumerate() { for (offset, cursor) in self.cursors.iter_mut().enumerate() {
ptr.add(offset).write(cursor.peek_last().unwrap()); ptr.add(offset).write(cursor.peek_last().unwrap());
} }
@ -2223,7 +2227,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter<
/// Get next combination of queried components /// Get next combination of queried components
#[inline] #[inline]
pub fn fetch_next(&mut self) -> Option<[D::Item<'_>; K]> { pub fn fetch_next(&mut self) -> Option<[D::Item<'_, 's>; K]> {
// SAFETY: we are limiting the returned reference to self, // SAFETY: we are limiting the returned reference to self,
// making sure this method cannot be called multiple times without getting rid // making sure this method cannot be called multiple times without getting rid
// of any previously returned unique references first, thus preventing aliasing. // of any previously returned unique references first, thus preventing aliasing.
@ -2240,7 +2244,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter<
impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, const K: usize> Iterator impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, const K: usize> Iterator
for QueryCombinationIter<'w, 's, D, F, K> for QueryCombinationIter<'w, 's, D, F, K>
{ {
type Item = [D::Item<'w>; K]; type Item = [D::Item<'w, 's>; K];
#[inline] #[inline]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -2309,8 +2313,8 @@ struct QueryIterationCursor<'w, 's, D: QueryData, F: QueryFilter> {
storage_id_iter: core::slice::Iter<'s, StorageId>, storage_id_iter: core::slice::Iter<'s, StorageId>,
table_entities: &'w [Entity], table_entities: &'w [Entity],
archetype_entities: &'w [ArchetypeEntity], archetype_entities: &'w [ArchetypeEntity],
fetch: D::Fetch<'w>, fetch: D::Fetch<'w, 's>,
filter: F::Fetch<'w>, filter: F::Fetch<'w, 's>,
// length of the table or length of the archetype, depending on whether both `D`'s and `F`'s fetches are dense // length of the table or length of the archetype, depending on whether both `D`'s and `F`'s fetches are dense
current_len: u32, current_len: u32,
// either table row or archetype index, depending on whether both `D`'s and `F`'s fetches are dense // either table row or archetype index, depending on whether both `D`'s and `F`'s fetches are dense
@ -2390,7 +2394,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> {
/// The result of `next` and any previous calls to `peek_last` with this row must have been /// The result of `next` and any previous calls to `peek_last` with this row must have been
/// dropped to prevent aliasing mutable references. /// dropped to prevent aliasing mutable references.
#[inline] #[inline]
unsafe fn peek_last(&mut self) -> Option<D::Item<'w>> { unsafe fn peek_last(&mut self) -> Option<D::Item<'w, 's>> {
if self.current_row > 0 { if self.current_row > 0 {
let index = self.current_row - 1; let index = self.current_row - 1;
if self.is_dense { if self.is_dense {
@ -2457,7 +2461,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> {
tables: &'w Tables, tables: &'w Tables,
archetypes: &'w Archetypes, archetypes: &'w Archetypes,
query_state: &'s QueryState<D, F>, query_state: &'s QueryState<D, F>,
) -> Option<D::Item<'w>> { ) -> Option<D::Item<'w, 's>> {
if self.is_dense { if self.is_dense {
loop { loop {
// we are on the beginning of the query, or finished processing a table, so skip to the next // we are on the beginning of the query, or finished processing a table, so skip to the next

View File

@ -819,34 +819,37 @@ mod tests {
/// SAFETY: /// SAFETY:
/// `update_component_access` adds resource read access for `R`. /// `update_component_access` adds resource read access for `R`.
unsafe impl WorldQuery for ReadsRData { unsafe impl WorldQuery for ReadsRData {
type Fetch<'w> = (); type Fetch<'w, 's> = ();
type State = ComponentId; type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
_: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort, 's> {
}
unsafe fn init_fetch<'w>( unsafe fn init_fetch<'w, 's>(
_world: UnsafeWorldCell<'w>, _world: UnsafeWorldCell<'w>,
_state: &Self::State, _state: &'s Self::State,
_last_run: Tick, _last_run: Tick,
_this_run: Tick, _this_run: Tick,
) -> Self::Fetch<'w> { ) -> Self::Fetch<'w, 's> {
} }
const IS_DENSE: bool = true; const IS_DENSE: bool = true;
#[inline] #[inline]
unsafe fn set_archetype<'w>( unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>, _fetch: &mut Self::Fetch<'w, 's>,
_state: &Self::State, _state: &'s Self::State,
_archetype: &'w Archetype, _archetype: &'w Archetype,
_table: &Table, _table: &Table,
) { ) {
} }
#[inline] #[inline]
unsafe fn set_table<'w>( unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>, _fetch: &mut Self::Fetch<'w, 's>,
_state: &Self::State, _state: &'s Self::State,
_table: &'w Table, _table: &'w Table,
) { ) {
} }
@ -882,16 +885,19 @@ mod tests {
unsafe impl QueryData for ReadsRData { unsafe impl QueryData for ReadsRData {
const IS_READ_ONLY: bool = true; const IS_READ_ONLY: bool = true;
type ReadOnly = Self; type ReadOnly = Self;
type Item<'w> = (); type Item<'w, 's> = ();
fn shrink<'wlong: 'wshort, 'wshort>(_item: Self::Item<'wlong>) -> Self::Item<'wshort> {} fn shrink<'wlong: 'wshort, 'wshort, 's>(
_item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
}
#[inline(always)] #[inline(always)]
unsafe fn fetch<'w>( unsafe fn fetch<'w, 's>(
_fetch: &mut Self::Fetch<'w>, _fetch: &mut Self::Fetch<'w, 's>,
_entity: Entity, _entity: Entity,
_table_row: TableRow, _table_row: TableRow,
) -> Self::Item<'w> { ) -> Self::Item<'w, 's> {
} }
} }

View File

@ -39,7 +39,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> {
/// ///
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
#[inline] #[inline]
pub fn for_each<FN: Fn(QueryItem<'w, D>) + Send + Sync + Clone>(self, func: FN) { pub fn for_each<FN: Fn(QueryItem<'w, 's, D>) + Send + Sync + Clone>(self, func: FN) {
self.for_each_init(|| {}, |_, item| func(item)); self.for_each_init(|| {}, |_, item| func(item));
} }
@ -76,7 +76,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> {
#[inline] #[inline]
pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN) pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN)
where where
FN: Fn(&mut T, QueryItem<'w, D>) + Send + Sync + Clone, FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone,
INIT: Fn() -> T + Sync + Send + Clone, INIT: Fn() -> T + Sync + Send + Clone,
{ {
let func = |mut init, item| { let func = |mut init, item| {
@ -190,7 +190,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityEquivalent + Sync>
/// ///
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
#[inline] #[inline]
pub fn for_each<FN: Fn(QueryItem<'w, D>) + Send + Sync + Clone>(self, func: FN) { pub fn for_each<FN: Fn(QueryItem<'w, 's, D>) + Send + Sync + Clone>(self, func: FN) {
self.for_each_init(|| {}, |_, item| func(item)); self.for_each_init(|| {}, |_, item| func(item));
} }
@ -247,7 +247,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityEquivalent + Sync>
#[inline] #[inline]
pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN) pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN)
where where
FN: Fn(&mut T, QueryItem<'w, D>) + Send + Sync + Clone, FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone,
INIT: Fn() -> T + Sync + Send + Clone, INIT: Fn() -> T + Sync + Send + Clone,
{ {
let func = |mut init, item| { let func = |mut init, item| {
@ -345,7 +345,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: EntityEquivalent + Sync>
/// ///
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
#[inline] #[inline]
pub fn for_each<FN: Fn(QueryItem<'w, D>) + Send + Sync + Clone>(self, func: FN) { pub fn for_each<FN: Fn(QueryItem<'w, 's, D>) + Send + Sync + Clone>(self, func: FN) {
self.for_each_init(|| {}, |_, item| func(item)); self.for_each_init(|| {}, |_, item| func(item));
} }
@ -402,7 +402,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: EntityEquivalent + Sync>
#[inline] #[inline]
pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN) pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN)
where where
FN: Fn(&mut T, QueryItem<'w, D>) + Send + Sync + Clone, FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone,
INIT: Fn() -> T + Sync + Send + Clone, INIT: Fn() -> T + Sync + Send + Clone,
{ {
let func = |mut init, item| { let func = |mut init, item| {

View File

@ -845,13 +845,17 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
/// ///
/// This can only be called for read-only queries, see [`Self::get_mut`] for write-queries. /// This can only be called for read-only queries, see [`Self::get_mut`] for write-queries.
/// ///
/// If you need to get multiple items at once but get borrowing errors,
/// consider using [`Self::update_archetypes`] followed by multiple [`Self::get_manual`] calls,
/// or making a single call with [`Self::get_many`] or [`Self::iter_many`].
///
/// This is always guaranteed to run in `O(1)` time. /// This is always guaranteed to run in `O(1)` time.
#[inline] #[inline]
pub fn get<'w>( pub fn get<'w>(
&mut self, &mut self,
world: &'w World, world: &'w World,
entity: Entity, entity: Entity,
) -> Result<ROQueryItem<'w, D>, QueryEntityError> { ) -> Result<ROQueryItem<'w, '_, D>, QueryEntityError> {
self.query(world).get_inner(entity) self.query(world).get_inner(entity)
} }
@ -892,7 +896,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self, &mut self,
world: &'w World, world: &'w World,
entities: [Entity; N], entities: [Entity; N],
) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> { ) -> Result<[ROQueryItem<'w, '_, D>; N], QueryEntityError> {
self.query(world).get_many_inner(entities) self.query(world).get_many_inner(entities)
} }
@ -930,7 +934,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self, &mut self,
world: &'w World, world: &'w World,
entities: UniqueEntityArray<N>, entities: UniqueEntityArray<N>,
) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> { ) -> Result<[ROQueryItem<'w, '_, D>; N], QueryEntityError> {
self.query(world).get_many_unique_inner(entities) self.query(world).get_many_unique_inner(entities)
} }
@ -942,7 +946,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self, &mut self,
world: &'w mut World, world: &'w mut World,
entity: Entity, entity: Entity,
) -> Result<D::Item<'w>, QueryEntityError> { ) -> Result<D::Item<'w, '_>, QueryEntityError> {
self.query_mut(world).get_inner(entity) self.query_mut(world).get_inner(entity)
} }
@ -989,7 +993,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self, &mut self,
world: &'w mut World, world: &'w mut World,
entities: [Entity; N], entities: [Entity; N],
) -> Result<[D::Item<'w>; N], QueryEntityError> { ) -> Result<[D::Item<'w, '_>; N], QueryEntityError> {
self.query_mut(world).get_many_mut_inner(entities) self.query_mut(world).get_many_mut_inner(entities)
} }
@ -1034,7 +1038,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self, &mut self,
world: &'w mut World, world: &'w mut World,
entities: UniqueEntityArray<N>, entities: UniqueEntityArray<N>,
) -> Result<[D::Item<'w>; N], QueryEntityError> { ) -> Result<[D::Item<'w, '_>; N], QueryEntityError> {
self.query_mut(world).get_many_unique_inner(entities) self.query_mut(world).get_many_unique_inner(entities)
} }
@ -1056,7 +1060,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&self, &self,
world: &'w World, world: &'w World,
entity: Entity, entity: Entity,
) -> Result<ROQueryItem<'w, D>, QueryEntityError> { ) -> Result<ROQueryItem<'w, '_, D>, QueryEntityError> {
self.query_manual(world).get_inner(entity) self.query_manual(world).get_inner(entity)
} }
@ -1073,13 +1077,16 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self, &mut self,
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
entity: Entity, entity: Entity,
) -> Result<D::Item<'w>, QueryEntityError> { ) -> Result<D::Item<'w, '_>, QueryEntityError> {
self.query_unchecked(world).get_inner(entity) self.query_unchecked(world).get_inner(entity)
} }
/// Returns an [`Iterator`] over the query results for the given [`World`]. /// Returns an [`Iterator`] over the query results for the given [`World`].
/// ///
/// This can only be called for read-only queries, see [`Self::iter_mut`] for write-queries. /// This can only be called for read-only queries, see [`Self::iter_mut`] for write-queries.
///
/// If you need to iterate multiple times at once but get borrowing errors,
/// consider using [`Self::update_archetypes`] followed by multiple [`Self::iter_manual`] calls.
#[inline] #[inline]
pub fn iter<'w, 's>(&'s mut self, world: &'w World) -> QueryIter<'w, 's, D::ReadOnly, F> { pub fn iter<'w, 's>(&'s mut self, world: &'w World) -> QueryIter<'w, 's, D::ReadOnly, F> {
self.query(world).into_iter() self.query(world).into_iter()
@ -1168,6 +1175,9 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
/// Items are returned in the order of the list of entities. /// Items are returned in the order of the list of entities.
/// Entities that don't match the query are skipped. /// Entities that don't match the query are skipped.
/// ///
/// If you need to iterate multiple times at once but get borrowing errors,
/// consider using [`Self::update_archetypes`] followed by multiple [`Self::iter_many_manual`] calls.
///
/// # See also /// # See also
/// ///
/// - [`iter_many_mut`](Self::iter_many_mut) to get mutable query items. /// - [`iter_many_mut`](Self::iter_many_mut) to get mutable query items.
@ -1387,8 +1397,8 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
/// ///
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
#[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))]
pub(crate) unsafe fn par_fold_init_unchecked_manual<'w, T, FN, INIT>( pub(crate) unsafe fn par_fold_init_unchecked_manual<'w, 's, T, FN, INIT>(
&self, &'s self,
init_accum: INIT, init_accum: INIT,
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
batch_size: u32, batch_size: u32,
@ -1396,7 +1406,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) where ) where
FN: Fn(T, D::Item<'w>) -> T + Send + Sync + Clone, FN: Fn(T, D::Item<'w, 's>) -> T + Send + Sync + Clone,
INIT: Fn() -> T + Sync + Send + Clone, INIT: Fn() -> T + Sync + Send + Clone,
{ {
// NOTE: If you are changing query iteration code, remember to update the following places, where relevant: // NOTE: If you are changing query iteration code, remember to update the following places, where relevant:
@ -1501,8 +1511,8 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
/// ///
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
#[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))]
pub(crate) unsafe fn par_many_unique_fold_init_unchecked_manual<'w, T, FN, INIT, E>( pub(crate) unsafe fn par_many_unique_fold_init_unchecked_manual<'w, 's, T, FN, INIT, E>(
&self, &'s self,
init_accum: INIT, init_accum: INIT,
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
entity_list: &UniqueEntityEquivalentSlice<E>, entity_list: &UniqueEntityEquivalentSlice<E>,
@ -1511,7 +1521,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) where ) where
FN: Fn(T, D::Item<'w>) -> T + Send + Sync + Clone, FN: Fn(T, D::Item<'w, 's>) -> T + Send + Sync + Clone,
INIT: Fn() -> T + Sync + Send + Clone, INIT: Fn() -> T + Sync + Send + Clone,
E: EntityEquivalent + Sync, E: EntityEquivalent + Sync,
{ {
@ -1564,8 +1574,8 @@ impl<D: ReadOnlyQueryData, F: QueryFilter> QueryState<D, F> {
/// ///
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
#[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))]
pub(crate) unsafe fn par_many_fold_init_unchecked_manual<'w, T, FN, INIT, E>( pub(crate) unsafe fn par_many_fold_init_unchecked_manual<'w, 's, T, FN, INIT, E>(
&self, &'s self,
init_accum: INIT, init_accum: INIT,
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
entity_list: &[E], entity_list: &[E],
@ -1574,7 +1584,7 @@ impl<D: ReadOnlyQueryData, F: QueryFilter> QueryState<D, F> {
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) where ) where
FN: Fn(T, D::Item<'w>) -> T + Send + Sync + Clone, FN: Fn(T, D::Item<'w, 's>) -> T + Send + Sync + Clone,
INIT: Fn() -> T + Sync + Send + Clone, INIT: Fn() -> T + Sync + Send + Clone,
E: EntityEquivalent + Sync, E: EntityEquivalent + Sync,
{ {
@ -1686,7 +1696,10 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
/// ///
/// Simply unwrapping the [`Result`] also works, but should generally be reserved for tests. /// Simply unwrapping the [`Result`] also works, but should generally be reserved for tests.
#[inline] #[inline]
pub fn single<'w>(&mut self, world: &'w World) -> Result<ROQueryItem<'w, D>, QuerySingleError> { pub fn single<'w>(
&mut self,
world: &'w World,
) -> Result<ROQueryItem<'w, '_, D>, QuerySingleError> {
self.query(world).single_inner() self.query(world).single_inner()
} }
@ -1703,7 +1716,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
pub fn single_mut<'w>( pub fn single_mut<'w>(
&mut self, &mut self,
world: &'w mut World, world: &'w mut World,
) -> Result<D::Item<'w>, QuerySingleError> { ) -> Result<D::Item<'w, '_>, QuerySingleError> {
self.query_mut(world).single_inner() self.query_mut(world).single_inner()
} }
@ -1720,7 +1733,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
pub unsafe fn single_unchecked<'w>( pub unsafe fn single_unchecked<'w>(
&mut self, &mut self,
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
) -> Result<D::Item<'w>, QuerySingleError> { ) -> Result<D::Item<'w, '_>, QuerySingleError> {
self.query_unchecked(world).single_inner() self.query_unchecked(world).single_inner()
} }
@ -1742,7 +1755,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) -> Result<D::Item<'w>, QuerySingleError> { ) -> Result<D::Item<'w, '_>, QuerySingleError> {
// SAFETY: // SAFETY:
// - The caller ensured we have the correct access to the world. // - The caller ensured we have the correct access to the world.
// - The caller ensured that the world matches. // - The caller ensured that the world matches.

View File

@ -42,7 +42,7 @@ use variadics_please::all_tuples;
/// [`QueryFilter`]: crate::query::QueryFilter /// [`QueryFilter`]: crate::query::QueryFilter
pub unsafe trait WorldQuery { pub unsafe trait WorldQuery {
/// Per archetype/table state retrieved by this [`WorldQuery`] to compute [`Self::Item`](crate::query::QueryData::Item) for each entity. /// Per archetype/table state retrieved by this [`WorldQuery`] to compute [`Self::Item`](crate::query::QueryData::Item) for each entity.
type Fetch<'a>: Clone; type Fetch<'w, 's>: Clone;
/// State used to construct a [`Self::Fetch`](WorldQuery::Fetch). This will be cached inside [`QueryState`](crate::query::QueryState), /// State used to construct a [`Self::Fetch`](WorldQuery::Fetch). This will be cached inside [`QueryState`](crate::query::QueryState),
/// so it is best to move as much data / computation here as possible to reduce the cost of /// so it is best to move as much data / computation here as possible to reduce the cost of
@ -50,7 +50,9 @@ pub unsafe trait WorldQuery {
type State: Send + Sync + Sized; type State: Send + Sync + Sized;
/// This function manually implements subtyping for the query fetches. /// This function manually implements subtyping for the query fetches.
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort>; fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
fetch: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort, 's>;
/// Creates a new instance of [`Self::Fetch`](WorldQuery::Fetch), /// Creates a new instance of [`Self::Fetch`](WorldQuery::Fetch),
/// by combining data from the [`World`] with the cached [`Self::State`](WorldQuery::State). /// by combining data from the [`World`] with the cached [`Self::State`](WorldQuery::State).
@ -62,12 +64,12 @@ pub unsafe trait WorldQuery {
/// in to this function. /// in to this function.
/// - `world` must have the **right** to access any access registered in `update_component_access`. /// - `world` must have the **right** to access any access registered in `update_component_access`.
/// - There must not be simultaneous resource access conflicting with readonly resource access registered in [`WorldQuery::update_component_access`]. /// - There must not be simultaneous resource access conflicting with readonly resource access registered in [`WorldQuery::update_component_access`].
unsafe fn init_fetch<'w>( unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
state: &Self::State, state: &'s Self::State,
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) -> Self::Fetch<'w>; ) -> Self::Fetch<'w, 's>;
/// Returns true if (and only if) every table of every archetype matched by this fetch contains /// Returns true if (and only if) every table of every archetype matched by this fetch contains
/// all of the matched components. /// all of the matched components.
@ -87,9 +89,9 @@ pub unsafe trait WorldQuery {
/// - `archetype` and `tables` must be from the same [`World`] that [`WorldQuery::init_state`] was called on. /// - `archetype` and `tables` must be from the same [`World`] that [`WorldQuery::init_state`] was called on.
/// - `table` must correspond to `archetype`. /// - `table` must correspond to `archetype`.
/// - `state` must be the [`State`](Self::State) that `fetch` was initialized with. /// - `state` must be the [`State`](Self::State) that `fetch` was initialized with.
unsafe fn set_archetype<'w>( unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
state: &Self::State, state: &'s Self::State,
archetype: &'w Archetype, archetype: &'w Archetype,
table: &'w Table, table: &'w Table,
); );
@ -101,7 +103,11 @@ pub unsafe trait WorldQuery {
/// ///
/// - `table` must be from the same [`World`] that [`WorldQuery::init_state`] was called on. /// - `table` must be from the same [`World`] that [`WorldQuery::init_state`] was called on.
/// - `state` must be the [`State`](Self::State) that `fetch` was initialized with. /// - `state` must be the [`State`](Self::State) that `fetch` was initialized with.
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table); unsafe fn set_table<'w, 's>(
fetch: &mut Self::Fetch<'w, 's>,
state: &'s Self::State,
table: &'w Table,
);
/// Adds any component accesses used by this [`WorldQuery`] to `access`. /// Adds any component accesses used by this [`WorldQuery`] to `access`.
/// ///
@ -154,11 +160,11 @@ macro_rules! impl_tuple_world_query {
/// `update_component_access` adds all `With` and `Without` filters from the subqueries. /// `update_component_access` adds all `With` and `Without` filters from the subqueries.
/// This is sound because `matches_component_set` always returns `false` if any the subqueries' implementations return `false`. /// This is sound because `matches_component_set` always returns `false` if any the subqueries' implementations return `false`.
unsafe impl<$($name: WorldQuery),*> WorldQuery for ($($name,)*) { unsafe impl<$($name: WorldQuery),*> WorldQuery for ($($name,)*) {
type Fetch<'w> = ($($name::Fetch<'w>,)*); type Fetch<'w, 's> = ($($name::Fetch<'w, 's>,)*);
type State = ($($name::State,)*); type State = ($($name::State,)*);
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(fetch: Self::Fetch<'wlong, 's>) -> Self::Fetch<'wshort, 's> {
let ($($name,)*) = fetch; let ($($name,)*) = fetch;
($( ($(
$name::shrink_fetch($name), $name::shrink_fetch($name),
@ -166,7 +172,7 @@ macro_rules! impl_tuple_world_query {
} }
#[inline] #[inline]
unsafe fn init_fetch<'w>(world: UnsafeWorldCell<'w>, state: &Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w> { unsafe fn init_fetch<'w, 's>(world: UnsafeWorldCell<'w>, state: &'s Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w, 's> {
let ($($name,)*) = state; let ($($name,)*) = state;
// SAFETY: The invariants are upheld by the caller. // SAFETY: The invariants are upheld by the caller.
($(unsafe { $name::init_fetch(world, $name, last_run, this_run) },)*) ($(unsafe { $name::init_fetch(world, $name, last_run, this_run) },)*)
@ -175,9 +181,9 @@ macro_rules! impl_tuple_world_query {
const IS_DENSE: bool = true $(&& $name::IS_DENSE)*; const IS_DENSE: bool = true $(&& $name::IS_DENSE)*;
#[inline] #[inline]
unsafe fn set_archetype<'w>( unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
state: &Self::State, state: &'s Self::State,
archetype: &'w Archetype, archetype: &'w Archetype,
table: &'w Table table: &'w Table
) { ) {
@ -188,7 +194,7 @@ macro_rules! impl_tuple_world_query {
} }
#[inline] #[inline]
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) { unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w, 's>, state: &'s Self::State, table: &'w Table) {
let ($($name,)*) = fetch; let ($($name,)*) = fetch;
let ($($state,)*) = state; let ($($state,)*) = state;
// SAFETY: The invariants are upheld by the caller. // SAFETY: The invariants are upheld by the caller.

View File

@ -14,7 +14,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// target entity of that relationship. /// target entity of that relationship.
pub fn related<R: Relationship>(&'w self, entity: Entity) -> Option<Entity> pub fn related<R: Relationship>(&'w self, entity: Entity) -> Option<Entity>
where where
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w R>, <D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
{ {
self.get(entity).map(R::get).ok() self.get(entity).map(R::get).ok()
} }
@ -26,7 +26,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
entity: Entity, entity: Entity,
) -> impl Iterator<Item = Entity> + 'w ) -> impl Iterator<Item = Entity> + 'w
where where
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>, <D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{ {
self.get(entity) self.get(entity)
.into_iter() .into_iter()
@ -42,7 +42,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.
pub fn root_ancestor<R: Relationship>(&'w self, entity: Entity) -> Entity pub fn root_ancestor<R: Relationship>(&'w self, entity: Entity) -> Entity
where where
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w R>, <D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
{ {
// Recursively search up the tree until we're out of parents // Recursively search up the tree until we're out of parents
match self.get(entity) { match self.get(entity) {
@ -60,9 +60,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn iter_leaves<S: RelationshipTarget>( pub fn iter_leaves<S: RelationshipTarget>(
&'w self, &'w self,
entity: Entity, entity: Entity,
) -> impl Iterator<Item = Entity> + 'w ) -> impl Iterator<Item = Entity> + use<'w, 's, S, D, F>
where where
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>, <D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator, SourceIter<'w, S>: DoubleEndedIterator,
{ {
self.iter_descendants_depth_first(entity).filter(|entity| { self.iter_descendants_depth_first(entity).filter(|entity| {
@ -80,7 +80,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
entity: Entity, entity: Entity,
) -> impl Iterator<Item = Entity> + 'w ) -> impl Iterator<Item = Entity> + 'w
where where
D::ReadOnly: QueryData<Item<'w> = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>, D::ReadOnly: QueryData<Item<'w, 's> = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>,
{ {
self.get(entity) self.get(entity)
.ok() .ok()
@ -103,7 +103,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
entity: Entity, entity: Entity,
) -> DescendantIter<'w, 's, D, F, S> ) -> DescendantIter<'w, 's, D, F, S>
where where
D::ReadOnly: QueryData<Item<'w> = &'w S>, D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{ {
DescendantIter::new(self, entity) DescendantIter::new(self, entity)
} }
@ -120,7 +120,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
entity: Entity, entity: Entity,
) -> DescendantDepthFirstIter<'w, 's, D, F, S> ) -> DescendantDepthFirstIter<'w, 's, D, F, S>
where where
D::ReadOnly: QueryData<Item<'w> = &'w S>, D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator, SourceIter<'w, S>: DoubleEndedIterator,
{ {
DescendantDepthFirstIter::new(self, entity) DescendantDepthFirstIter::new(self, entity)
@ -137,7 +137,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
entity: Entity, entity: Entity,
) -> AncestorIter<'w, 's, D, F, R> ) -> AncestorIter<'w, 's, D, F, R>
where where
D::ReadOnly: QueryData<Item<'w> = &'w R>, D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
{ {
AncestorIter::new(self, entity) AncestorIter::new(self, entity)
} }
@ -148,7 +148,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// Traverses the hierarchy breadth-first. /// Traverses the hierarchy breadth-first.
pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
where where
D::ReadOnly: QueryData<Item<'w> = &'w S>, D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{ {
children_query: &'w Query<'w, 's, D, F>, children_query: &'w Query<'w, 's, D, F>,
vecdeque: VecDeque<Entity>, vecdeque: VecDeque<Entity>,
@ -156,7 +156,7 @@ where
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantIter<'w, 's, D, F, S> impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantIter<'w, 's, D, F, S>
where where
D::ReadOnly: QueryData<Item<'w> = &'w S>, D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{ {
/// Returns a new [`DescendantIter`]. /// Returns a new [`DescendantIter`].
pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
@ -174,7 +174,7 @@ where
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator
for DescendantIter<'w, 's, D, F, S> for DescendantIter<'w, 's, D, F, S>
where where
D::ReadOnly: QueryData<Item<'w> = &'w S>, D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{ {
type Item = Entity; type Item = Entity;
@ -194,7 +194,7 @@ where
/// Traverses the hierarchy depth-first. /// Traverses the hierarchy depth-first.
pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
where where
D::ReadOnly: QueryData<Item<'w> = &'w S>, D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{ {
children_query: &'w Query<'w, 's, D, F>, children_query: &'w Query<'w, 's, D, F>,
stack: SmallVec<[Entity; 8]>, stack: SmallVec<[Entity; 8]>,
@ -203,7 +203,7 @@ where
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
DescendantDepthFirstIter<'w, 's, D, F, S> DescendantDepthFirstIter<'w, 's, D, F, S>
where where
D::ReadOnly: QueryData<Item<'w> = &'w S>, D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator, SourceIter<'w, S>: DoubleEndedIterator,
{ {
/// Returns a new [`DescendantDepthFirstIter`]. /// Returns a new [`DescendantDepthFirstIter`].
@ -220,7 +220,7 @@ where
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator
for DescendantDepthFirstIter<'w, 's, D, F, S> for DescendantDepthFirstIter<'w, 's, D, F, S>
where where
D::ReadOnly: QueryData<Item<'w> = &'w S>, D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator, SourceIter<'w, S>: DoubleEndedIterator,
{ {
type Item = Entity; type Item = Entity;
@ -239,7 +239,7 @@ where
/// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`]. /// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`].
pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter, R: Relationship>
where where
D::ReadOnly: QueryData<Item<'w> = &'w R>, D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
{ {
parent_query: &'w Query<'w, 's, D, F>, parent_query: &'w Query<'w, 's, D, F>,
next: Option<Entity>, next: Option<Entity>,
@ -247,7 +247,7 @@ where
impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> AncestorIter<'w, 's, D, F, R> impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> AncestorIter<'w, 's, D, F, R>
where where
D::ReadOnly: QueryData<Item<'w> = &'w R>, D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
{ {
/// Returns a new [`AncestorIter`]. /// Returns a new [`AncestorIter`].
pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
@ -261,7 +261,7 @@ where
impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> Iterator impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> Iterator
for AncestorIter<'w, 's, D, F, R> for AncestorIter<'w, 's, D, F, R>
where where
D::ReadOnly: QueryData<Item<'w> = &'w R>, D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
{ {
type Item = Entity; type Item = Entity;

View File

@ -1185,7 +1185,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// [`par_iter_mut`]: Self::par_iter_mut /// [`par_iter_mut`]: Self::par_iter_mut
/// [`World`]: crate::world::World /// [`World`]: crate::world::World
#[inline] #[inline]
pub fn par_iter(&self) -> QueryParIter<'_, '_, D::ReadOnly, F> { pub fn par_iter(&self) -> QueryParIter<'_, 's, D::ReadOnly, F> {
self.as_readonly().par_iter_inner() self.as_readonly().par_iter_inner()
} }
@ -1220,7 +1220,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// [`par_iter`]: Self::par_iter /// [`par_iter`]: Self::par_iter
/// [`World`]: crate::world::World /// [`World`]: crate::world::World
#[inline] #[inline]
pub fn par_iter_mut(&mut self) -> QueryParIter<'_, '_, D, F> { pub fn par_iter_mut(&mut self) -> QueryParIter<'_, 's, D, F> {
self.reborrow().par_iter_inner() self.reborrow().par_iter_inner()
} }
@ -1280,7 +1280,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn par_iter_many<EntityList: IntoIterator<Item: EntityEquivalent>>( pub fn par_iter_many<EntityList: IntoIterator<Item: EntityEquivalent>>(
&self, &self,
entities: EntityList, entities: EntityList,
) -> QueryParManyIter<'_, '_, D::ReadOnly, F, EntityList::Item> { ) -> QueryParManyIter<'_, 's, D::ReadOnly, F, EntityList::Item> {
QueryParManyIter { QueryParManyIter {
world: self.world, world: self.world,
state: self.state.as_readonly(), state: self.state.as_readonly(),
@ -1309,7 +1309,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn par_iter_many_unique<EntityList: EntitySet<Item: Sync>>( pub fn par_iter_many_unique<EntityList: EntitySet<Item: Sync>>(
&self, &self,
entities: EntityList, entities: EntityList,
) -> QueryParManyUniqueIter<'_, '_, D::ReadOnly, F, EntityList::Item> { ) -> QueryParManyUniqueIter<'_, 's, D::ReadOnly, F, EntityList::Item> {
QueryParManyUniqueIter { QueryParManyUniqueIter {
world: self.world, world: self.world,
state: self.state.as_readonly(), state: self.state.as_readonly(),
@ -1338,7 +1338,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn par_iter_many_unique_mut<EntityList: EntitySet<Item: Sync>>( pub fn par_iter_many_unique_mut<EntityList: EntitySet<Item: Sync>>(
&mut self, &mut self,
entities: EntityList, entities: EntityList,
) -> QueryParManyUniqueIter<'_, '_, D, F, EntityList::Item> { ) -> QueryParManyUniqueIter<'_, 's, D, F, EntityList::Item> {
QueryParManyUniqueIter { QueryParManyUniqueIter {
world: self.world, world: self.world,
state: self.state, state: self.state,
@ -1383,7 +1383,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// ///
/// - [`get_mut`](Self::get_mut) to get a mutable query item. /// - [`get_mut`](Self::get_mut) to get a mutable query item.
#[inline] #[inline]
pub fn get(&self, entity: Entity) -> Result<ROQueryItem<'_, D>, QueryEntityError> { pub fn get(&self, entity: Entity) -> Result<ROQueryItem<'_, 's, D>, QueryEntityError> {
self.as_readonly().get_inner(entity) self.as_readonly().get_inner(entity)
} }
@ -1434,7 +1434,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn get_many<const N: usize>( pub fn get_many<const N: usize>(
&self, &self,
entities: [Entity; N], entities: [Entity; N],
) -> Result<[ROQueryItem<'_, D>; N], QueryEntityError> { ) -> Result<[ROQueryItem<'_, 's, D>; N], QueryEntityError> {
// Note that we call a separate `*_inner` method from `get_many_mut` // Note that we call a separate `*_inner` method from `get_many_mut`
// because we don't need to check for duplicates. // because we don't need to check for duplicates.
self.as_readonly().get_many_inner(entities) self.as_readonly().get_many_inner(entities)
@ -1485,7 +1485,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn get_many_unique<const N: usize>( pub fn get_many_unique<const N: usize>(
&self, &self,
entities: UniqueEntityArray<N>, entities: UniqueEntityArray<N>,
) -> Result<[ROQueryItem<'_, D>; N], QueryEntityError> { ) -> Result<[ROQueryItem<'_, 's, D>; N], QueryEntityError> {
self.as_readonly().get_many_unique_inner(entities) self.as_readonly().get_many_unique_inner(entities)
} }
@ -1519,7 +1519,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// ///
/// - [`get`](Self::get) to get a read-only query item. /// - [`get`](Self::get) to get a read-only query item.
#[inline] #[inline]
pub fn get_mut(&mut self, entity: Entity) -> Result<D::Item<'_>, QueryEntityError> { pub fn get_mut(&mut self, entity: Entity) -> Result<D::Item<'_, 's>, QueryEntityError> {
self.reborrow().get_inner(entity) self.reborrow().get_inner(entity)
} }
@ -1534,7 +1534,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// ///
/// - [`get_mut`](Self::get_mut) to get the item using a mutable borrow of the [`Query`]. /// - [`get_mut`](Self::get_mut) to get the item using a mutable borrow of the [`Query`].
#[inline] #[inline]
pub fn get_inner(self, entity: Entity) -> Result<D::Item<'w>, QueryEntityError> { pub fn get_inner(self, entity: Entity) -> Result<D::Item<'w, 's>, QueryEntityError> {
// SAFETY: system runs without conflicts with other systems. // SAFETY: system runs without conflicts with other systems.
// same-system queries have runtime borrow checks when they conflict // same-system queries have runtime borrow checks when they conflict
unsafe { unsafe {
@ -1662,7 +1662,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn get_many_mut<const N: usize>( pub fn get_many_mut<const N: usize>(
&mut self, &mut self,
entities: [Entity; N], entities: [Entity; N],
) -> Result<[D::Item<'_>; N], QueryEntityError> { ) -> Result<[D::Item<'_, 's>; N], QueryEntityError> {
self.reborrow().get_many_mut_inner(entities) self.reborrow().get_many_mut_inner(entities)
} }
@ -1730,7 +1730,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn get_many_unique_mut<const N: usize>( pub fn get_many_unique_mut<const N: usize>(
&mut self, &mut self,
entities: UniqueEntityArray<N>, entities: UniqueEntityArray<N>,
) -> Result<[D::Item<'_>; N], QueryEntityError> { ) -> Result<[D::Item<'_, 's>; N], QueryEntityError> {
self.reborrow().get_many_unique_inner(entities) self.reborrow().get_many_unique_inner(entities)
} }
@ -1749,7 +1749,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn get_many_mut_inner<const N: usize>( pub fn get_many_mut_inner<const N: usize>(
self, self,
entities: [Entity; N], entities: [Entity; N],
) -> Result<[D::Item<'w>; N], QueryEntityError> { ) -> Result<[D::Item<'w, 's>; N], QueryEntityError> {
// Verify that all entities are unique // Verify that all entities are unique
for i in 0..N { for i in 0..N {
for j in 0..i { for j in 0..i {
@ -1777,7 +1777,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn get_many_inner<const N: usize>( pub fn get_many_inner<const N: usize>(
self, self,
entities: [Entity; N], entities: [Entity; N],
) -> Result<[D::Item<'w>; N], QueryEntityError> ) -> Result<[D::Item<'w, 's>; N], QueryEntityError>
where where
D: ReadOnlyQueryData, D: ReadOnlyQueryData,
{ {
@ -1799,7 +1799,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn get_many_unique_inner<const N: usize>( pub fn get_many_unique_inner<const N: usize>(
self, self,
entities: UniqueEntityArray<N>, entities: UniqueEntityArray<N>,
) -> Result<[D::Item<'w>; N], QueryEntityError> { ) -> Result<[D::Item<'w, 's>; N], QueryEntityError> {
// SAFETY: All entities are unique, so the results don't alias. // SAFETY: All entities are unique, so the results don't alias.
unsafe { self.get_many_impl(entities.into_inner()) } unsafe { self.get_many_impl(entities.into_inner()) }
} }
@ -1814,7 +1814,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
unsafe fn get_many_impl<const N: usize>( unsafe fn get_many_impl<const N: usize>(
self, self,
entities: [Entity; N], entities: [Entity; N],
) -> Result<[D::Item<'w>; N], QueryEntityError> { ) -> Result<[D::Item<'w, 's>; N], QueryEntityError> {
let mut values = [(); N].map(|_| MaybeUninit::uninit()); let mut values = [(); N].map(|_| MaybeUninit::uninit());
for (value, entity) in core::iter::zip(&mut values, entities) { for (value, entity) in core::iter::zip(&mut values, entities) {
@ -1842,7 +1842,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// ///
/// - [`get_mut`](Self::get_mut) for the safe version. /// - [`get_mut`](Self::get_mut) for the safe version.
#[inline] #[inline]
pub unsafe fn get_unchecked(&self, entity: Entity) -> Result<D::Item<'_>, QueryEntityError> { pub unsafe fn get_unchecked(
&self,
entity: Entity,
) -> Result<D::Item<'_, 's>, QueryEntityError> {
// SAFETY: The caller promises that this will not result in multiple mutable references. // SAFETY: The caller promises that this will not result in multiple mutable references.
unsafe { self.reborrow_unsafe() }.get_inner(entity) unsafe { self.reborrow_unsafe() }.get_inner(entity)
} }
@ -1878,7 +1881,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// ///
/// - [`single_mut`](Self::single_mut) to get the mutable query item. /// - [`single_mut`](Self::single_mut) to get the mutable query item.
#[inline] #[inline]
pub fn single(&self) -> Result<ROQueryItem<'_, D>, QuerySingleError> { pub fn single(&self) -> Result<ROQueryItem<'_, 's, D>, QuerySingleError> {
self.as_readonly().single_inner() self.as_readonly().single_inner()
} }
@ -1907,7 +1910,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// ///
/// - [`single`](Self::single) to get the read-only query item. /// - [`single`](Self::single) to get the read-only query item.
#[inline] #[inline]
pub fn single_mut(&mut self) -> Result<D::Item<'_>, QuerySingleError> { pub fn single_mut(&mut self) -> Result<D::Item<'_, 's>, QuerySingleError> {
self.reborrow().single_inner() self.reborrow().single_inner()
} }
@ -1939,7 +1942,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// - [`single_mut`](Self::single_mut) to get the mutable query item. /// - [`single_mut`](Self::single_mut) to get the mutable query item.
/// - [`single_inner`](Self::single_inner) for the panicking version. /// - [`single_inner`](Self::single_inner) for the panicking version.
#[inline] #[inline]
pub fn single_inner(self) -> Result<D::Item<'w>, QuerySingleError> { pub fn single_inner(self) -> Result<D::Item<'w, 's>, QuerySingleError> {
let mut query = self.into_iter(); let mut query = self.into_iter();
let first = query.next(); let first = query.next();
let extra = query.next().is_some(); let extra = query.next().is_some();
@ -2451,7 +2454,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
} }
impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for Query<'w, 's, D, F> { impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for Query<'w, 's, D, F> {
type Item = D::Item<'w>; type Item = D::Item<'w, 's>;
type IntoIter = QueryIter<'w, 's, D, F>; type IntoIter = QueryIter<'w, 's, D, F>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
@ -2464,7 +2467,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for Query<'w, 's, D, F>
} }
impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w Query<'_, 's, D, F> { impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w Query<'_, 's, D, F> {
type Item = ROQueryItem<'w, D>; type Item = ROQueryItem<'w, 's, D>;
type IntoIter = QueryIter<'w, 's, D::ReadOnly, F>; type IntoIter = QueryIter<'w, 's, D::ReadOnly, F>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
@ -2473,7 +2476,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w Query<'_, 's, D,
} }
impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w mut Query<'_, 's, D, F> { impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w mut Query<'_, 's, D, F> {
type Item = D::Item<'w>; type Item = D::Item<'w, 's>;
type IntoIter = QueryIter<'w, 's, D, F>; type IntoIter = QueryIter<'w, 's, D, F>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
@ -2588,28 +2591,28 @@ impl<'w, 'q, Q: QueryData, F: QueryFilter> From<&'q mut Query<'w, '_, Q, F>>
/// ``` /// ```
/// Note that because [`Single`] implements [`Deref`] and [`DerefMut`], methods and fields like `health` can be accessed directly. /// Note that because [`Single`] implements [`Deref`] and [`DerefMut`], methods and fields like `health` can be accessed directly.
/// You can also access the underlying data manually, by calling `.deref`/`.deref_mut`, or by using the `*` operator. /// You can also access the underlying data manually, by calling `.deref`/`.deref_mut`, or by using the `*` operator.
pub struct Single<'w, D: QueryData, F: QueryFilter = ()> { pub struct Single<'w, 's, D: QueryData, F: QueryFilter = ()> {
pub(crate) item: D::Item<'w>, pub(crate) item: D::Item<'w, 's>,
pub(crate) _filter: PhantomData<F>, pub(crate) _filter: PhantomData<F>,
} }
impl<'w, D: QueryData, F: QueryFilter> Deref for Single<'w, D, F> { impl<'w, 's, D: QueryData, F: QueryFilter> Deref for Single<'w, 's, D, F> {
type Target = D::Item<'w>; type Target = D::Item<'w, 's>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.item &self.item
} }
} }
impl<'w, D: QueryData, F: QueryFilter> DerefMut for Single<'w, D, F> { impl<'w, 's, D: QueryData, F: QueryFilter> DerefMut for Single<'w, 's, D, F> {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.item &mut self.item
} }
} }
impl<'w, D: QueryData, F: QueryFilter> Single<'w, D, F> { impl<'w, 's, D: QueryData, F: QueryFilter> Single<'w, 's, D, F> {
/// Returns the inner item with ownership. /// Returns the inner item with ownership.
pub fn into_inner(self) -> D::Item<'w> { pub fn into_inner(self) -> D::Item<'w, 's> {
self.item self.item
} }
} }

View File

@ -389,9 +389,11 @@ fn assert_component_access_compatibility(
// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If // SAFETY: Relevant query ComponentId access is applied to SystemMeta. If
// this Query conflicts with any prior access, a panic will occur. // this Query conflicts with any prior access, a panic will occur.
unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Single<'a, D, F> { unsafe impl<'a, 'b, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam
for Single<'a, 'b, D, F>
{
type State = QueryState<D, F>; type State = QueryState<D, F>;
type Item<'w, 's> = Single<'w, D, F>; type Item<'w, 's> = Single<'w, 's, D, F>;
fn init_state(world: &mut World) -> Self::State { fn init_state(world: &mut World) -> Self::State {
Query::init_state(world) Query::init_state(world)
@ -451,8 +453,8 @@ unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam fo
} }
// SAFETY: QueryState is constrained to read-only fetches, so it only reads World. // SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
unsafe impl<'a, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam unsafe impl<'a, 'b, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
for Single<'a, D, F> for Single<'a, 'b, D, F>
{ {
} }

View File

@ -1,6 +1,10 @@
//! A trait for components that let you traverse the ECS. //! A trait for components that let you traverse the ECS.
use crate::{entity::Entity, query::ReadOnlyQueryData, relationship::Relationship}; use crate::{
entity::Entity,
query::{ReadOnlyQueryData, ReleaseStateQueryData},
relationship::Relationship,
};
/// A component that can point to another entity, and which can be used to define a path through the ECS. /// A component that can point to another entity, and which can be used to define a path through the ECS.
/// ///
@ -20,13 +24,13 @@ use crate::{entity::Entity, query::ReadOnlyQueryData, relationship::Relationship
/// [specify the direction]: crate::event::EntityEvent::Traversal /// [specify the direction]: crate::event::EntityEvent::Traversal
/// [event propagation]: crate::observer::On::propagate /// [event propagation]: crate::observer::On::propagate
/// [observers]: crate::observer::Observer /// [observers]: crate::observer::Observer
pub trait Traversal<D: ?Sized>: ReadOnlyQueryData { pub trait Traversal<D: ?Sized>: ReadOnlyQueryData + ReleaseStateQueryData {
/// Returns the next entity to visit. /// Returns the next entity to visit.
fn traverse(item: Self::Item<'_>, data: &D) -> Option<Entity>; fn traverse(item: Self::Item<'_, '_>, data: &D) -> Option<Entity>;
} }
impl<D> Traversal<D> for () { impl<D> Traversal<D> for () {
fn traverse(_: Self::Item<'_>, _data: &D) -> Option<Entity> { fn traverse(_: Self::Item<'_, '_>, _data: &D) -> Option<Entity> {
None None
} }
} }
@ -39,7 +43,7 @@ impl<D> Traversal<D> for () {
/// ///
/// [event propagation]: crate::observer::On::propagate /// [event propagation]: crate::observer::On::propagate
impl<R: Relationship, D> Traversal<D> for &R { impl<R: Relationship, D> Traversal<D> for &R {
fn traverse(item: Self::Item<'_>, _data: &D) -> Option<Entity> { fn traverse(item: Self::Item<'_, '_>, _data: &D) -> Option<Entity> {
Some(item.get()) Some(item.get())
} }
} }

View File

@ -16,7 +16,7 @@ use crate::{
event::EntityEvent, event::EntityEvent,
lifecycle::{DESPAWN, REMOVE, REPLACE}, lifecycle::{DESPAWN, REMOVE, REPLACE},
observer::Observer, observer::Observer,
query::{Access, DebugCheckedUnwrap, ReadOnlyQueryData}, query::{Access, DebugCheckedUnwrap, ReadOnlyQueryData, ReleaseStateQueryData},
relationship::RelationshipHookMode, relationship::RelationshipHookMode,
resource::Resource, resource::Resource,
system::IntoObserverSystem, system::IntoObserverSystem,
@ -279,14 +279,16 @@ impl<'w> EntityRef<'w> {
/// # Panics /// # Panics
/// ///
/// If the entity does not have the components required by the query `Q`. /// If the entity does not have the components required by the query `Q`.
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'w> { pub fn components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(&self) -> Q::Item<'w, 'static> {
self.get_components::<Q>() self.get_components::<Q>()
.expect("Query does not match the current entity") .expect("Query does not match the current entity")
} }
/// Returns read-only components for the current entity that match the query `Q`, /// Returns read-only components for the current entity that match the query `Q`,
/// or `None` if the entity does not have the components required by the query `Q`. /// or `None` if the entity does not have the components required by the query `Q`.
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'w>> { pub fn get_components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(
&self,
) -> Option<Q::Item<'w, 'static>> {
// SAFETY: We have read-only access to all components of this entity. // SAFETY: We have read-only access to all components of this entity.
unsafe { self.cell.get_components::<Q>() } unsafe { self.cell.get_components::<Q>() }
} }
@ -546,13 +548,15 @@ impl<'w> EntityMut<'w> {
/// # Panics /// # Panics
/// ///
/// If the entity does not have the components required by the query `Q`. /// If the entity does not have the components required by the query `Q`.
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_> { pub fn components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(&self) -> Q::Item<'_, 'static> {
self.as_readonly().components::<Q>() self.as_readonly().components::<Q>()
} }
/// Returns read-only components for the current entity that match the query `Q`, /// Returns read-only components for the current entity that match the query `Q`,
/// or `None` if the entity does not have the components required by the query `Q`. /// or `None` if the entity does not have the components required by the query `Q`.
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'_>> { pub fn get_components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(
&self,
) -> Option<Q::Item<'_, 'static>> {
self.as_readonly().get_components::<Q>() self.as_readonly().get_components::<Q>()
} }
@ -1310,7 +1314,7 @@ impl<'w> EntityWorldMut<'w> {
/// If the entity does not have the components required by the query `Q` or if the entity /// If the entity does not have the components required by the query `Q` or if the entity
/// has been despawned while this `EntityWorldMut` is still alive. /// has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_> { pub fn components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(&self) -> Q::Item<'_, 'static> {
self.as_readonly().components::<Q>() self.as_readonly().components::<Q>()
} }
@ -1321,7 +1325,9 @@ impl<'w> EntityWorldMut<'w> {
/// ///
/// If the entity has been despawned while this `EntityWorldMut` is still alive. /// If the entity has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'_>> { pub fn get_components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(
&self,
) -> Option<Q::Item<'_, 'static>> {
self.as_readonly().get_components::<Q>() self.as_readonly().get_components::<Q>()
} }

View File

@ -11,7 +11,7 @@ use crate::{
lifecycle::RemovedComponentEvents, lifecycle::RemovedComponentEvents,
observer::Observers, observer::Observers,
prelude::Component, prelude::Component,
query::{DebugCheckedUnwrap, ReadOnlyQueryData}, query::{DebugCheckedUnwrap, ReadOnlyQueryData, ReleaseStateQueryData},
resource::Resource, resource::Resource,
storage::{ComponentSparseSet, Storages, Table}, storage::{ComponentSparseSet, Storages, Table},
world::RawCommandQueue, world::RawCommandQueue,
@ -998,7 +998,9 @@ impl<'w> UnsafeEntityCell<'w> {
/// It is the caller's responsibility to ensure that /// It is the caller's responsibility to ensure that
/// - the [`UnsafeEntityCell`] has permission to access the queried data immutably /// - the [`UnsafeEntityCell`] has permission to access the queried data immutably
/// - no mutable references to the queried data exist at the same time /// - no mutable references to the queried data exist at the same time
pub(crate) unsafe fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'w>> { pub(crate) unsafe fn get_components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(
&self,
) -> Option<Q::Item<'w, 'static>> {
// SAFETY: World is only used to access query data and initialize query state // SAFETY: World is only used to access query data and initialize query state
let state = unsafe { let state = unsafe {
let world = self.world().world(); let world = self.world().world();
@ -1028,7 +1030,8 @@ impl<'w> UnsafeEntityCell<'w> {
// Table corresponds to archetype. State is the same state used to init fetch above. // Table corresponds to archetype. State is the same state used to init fetch above.
unsafe { Q::set_archetype(&mut fetch, &state, archetype, table) } unsafe { Q::set_archetype(&mut fetch, &state, archetype, table) }
// SAFETY: Called after set_archetype above. Entity and location are guaranteed to exist. // SAFETY: Called after set_archetype above. Entity and location are guaranteed to exist.
unsafe { Some(Q::fetch(&mut fetch, self.id(), location.table_row)) } let item = unsafe { Q::fetch(&mut fetch, self.id(), location.table_row) };
Some(Q::release_state(item))
} else { } else {
None None
} }

View File

@ -631,8 +631,8 @@ impl<const I: usize, P: PhaseItem> RenderCommand<P> for SetLineGizmoBindGroup<I>
#[inline] #[inline]
fn render<'w>( fn render<'w>(
_item: &P, _item: &P,
_view: ROQueryItem<'w, Self::ViewQuery>, _view: ROQueryItem<'w, '_, Self::ViewQuery>,
uniform_index: Option<ROQueryItem<'w, Self::ItemQuery>>, uniform_index: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
bind_group: SystemParamItem<'w, '_, Self::Param>, bind_group: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult { ) -> RenderCommandResult {
@ -662,8 +662,8 @@ impl<P: PhaseItem, const STRIP: bool> RenderCommand<P> for DrawLineGizmo<STRIP>
#[inline] #[inline]
fn render<'w>( fn render<'w>(
_item: &P, _item: &P,
_view: ROQueryItem<'w, Self::ViewQuery>, _view: ROQueryItem<'w, '_, Self::ViewQuery>,
config: Option<ROQueryItem<'w, Self::ItemQuery>>, config: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
line_gizmos: SystemParamItem<'w, '_, Self::Param>, line_gizmos: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult { ) -> RenderCommandResult {
@ -725,8 +725,8 @@ impl<P: PhaseItem> RenderCommand<P> for DrawLineJointGizmo {
#[inline] #[inline]
fn render<'w>( fn render<'w>(
_item: &P, _item: &P,
_view: ROQueryItem<'w, Self::ViewQuery>, _view: ROQueryItem<'w, '_, Self::ViewQuery>,
config: Option<ROQueryItem<'w, Self::ItemQuery>>, config: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
line_gizmos: SystemParamItem<'w, '_, Self::Param>, line_gizmos: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult { ) -> RenderCommandResult {

View File

@ -155,7 +155,7 @@ pub struct WindowTraversal {
} }
impl<E: BufferedEvent + Clone> Traversal<FocusedInput<E>> for WindowTraversal { impl<E: BufferedEvent + Clone> Traversal<FocusedInput<E>> for WindowTraversal {
fn traverse(item: Self::Item<'_>, event: &FocusedInput<E>) -> Option<Entity> { fn traverse(item: Self::Item<'_, '_>, event: &FocusedInput<E>) -> Option<Entity> {
let WindowTraversalItem { child_of, window } = item; let WindowTraversalItem { child_of, window } = item;
// Send event to parent, if it has one. // Send event to parent, if it has one.

View File

@ -309,7 +309,7 @@ impl ExtractComponent for Atmosphere {
type Out = Atmosphere; type Out = Atmosphere;
fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option<Self::Out> { fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
Some(item.clone()) Some(item.clone())
} }
} }
@ -405,7 +405,7 @@ impl ExtractComponent for AtmosphereSettings {
type Out = AtmosphereSettings; type Out = AtmosphereSettings;
fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option<Self::Out> { fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
Some(item.clone()) Some(item.clone())
} }
} }

View File

@ -181,7 +181,7 @@ impl ViewNode for RenderSkyNode {
view_uniforms_offset, view_uniforms_offset,
lights_uniforms_offset, lights_uniforms_offset,
render_sky_pipeline_id, render_sky_pipeline_id,
): QueryItem<'w, Self::ViewQuery>, ): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let pipeline_cache = world.resource::<PipelineCache>(); let pipeline_cache = world.resource::<PipelineCache>();

View File

@ -192,7 +192,7 @@ impl ExtractInstance for EnvironmentMapIds {
type QueryFilter = (); type QueryFilter = ();
fn extract(item: QueryItem<'_, Self::QueryData>) -> Option<Self> { fn extract(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self> {
Some(EnvironmentMapIds { Some(EnvironmentMapIds {
diffuse: item.diffuse_map.id(), diffuse: item.diffuse_map.id(),
specular: item.specular_map.id(), specular: item.specular_map.id(),

View File

@ -1540,7 +1540,7 @@ fn extract_mesh_for_gpu_building(
not_shadow_caster, not_shadow_caster,
no_automatic_batching, no_automatic_batching,
visibility_range, visibility_range,
): <GpuMeshExtractionQuery as QueryData>::Item<'_>, ): <GpuMeshExtractionQuery as QueryData>::Item<'_, '_>,
render_visibility_ranges: &RenderVisibilityRanges, render_visibility_ranges: &RenderVisibilityRanges,
render_mesh_instances: &RenderMeshInstancesGpu, render_mesh_instances: &RenderMeshInstancesGpu,
queue: &mut RenderMeshInstanceGpuQueue, queue: &mut RenderMeshInstanceGpuQueue,
@ -2874,7 +2874,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewBindGroup<I>
view_environment_map, view_environment_map,
mesh_view_bind_group, mesh_view_bind_group,
maybe_oit_layers_count_offset, maybe_oit_layers_count_offset,
): ROQueryItem<'w, Self::ViewQuery>, ): ROQueryItem<'w, '_, Self::ViewQuery>,
_entity: Option<()>, _entity: Option<()>,
_: SystemParamItem<'w, '_, Self::Param>, _: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,

View File

@ -280,7 +280,7 @@ impl ViewNode for ScreenSpaceReflectionsNode {
view_environment_map_offset, view_environment_map_offset,
view_bind_group, view_bind_group,
ssr_pipeline_id, ssr_pipeline_id,
): QueryItem<'w, Self::ViewQuery>, ): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
// Grab the render pipeline. // Grab the render pipeline.
@ -498,7 +498,7 @@ impl ExtractComponent for ScreenSpaceReflections {
type Out = ScreenSpaceReflectionsUniform; type Out = ScreenSpaceReflectionsUniform;
fn extract_component(settings: QueryItem<'_, Self::QueryData>) -> Option<Self::Out> { fn extract_component(settings: QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
if !DEPTH_TEXTURE_SAMPLING_SUPPORTED { if !DEPTH_TEXTURE_SAMPLING_SUPPORTED {
once!(info!( once!(info!(
"Disabling screen-space reflections on this platform because depth textures \ "Disabling screen-space reflections on this platform because depth textures \

View File

@ -347,7 +347,7 @@ impl ViewNode for VolumetricFogNode {
view_ssr_offset, view_ssr_offset,
msaa, msaa,
view_environment_map_offset, view_environment_map_offset,
): QueryItem<'w, Self::ViewQuery>, ): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let pipeline_cache = world.resource::<PipelineCache>(); let pipeline_cache = world.resource::<PipelineCache>();

View File

@ -374,7 +374,7 @@ impl ViewNode for Wireframe3dNode {
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
(camera, view, target, depth): QueryItem<'w, Self::ViewQuery>, (camera, view, target, depth): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let Some(wireframe_phase) = world.get_resource::<ViewBinnedRenderPhases<Wireframe3d>>() let Some(wireframe_phase) = world.get_resource::<ViewBinnedRenderPhases<Wireframe3d>>()

View File

@ -86,7 +86,7 @@ impl<E> Traversal<Pointer<E>> for PointerTraversal
where where
E: Debug + Clone + Reflect, E: Debug + Clone + Reflect,
{ {
fn traverse(item: Self::Item<'_>, pointer: &Pointer<E>) -> Option<Entity> { fn traverse(item: Self::Item<'_, '_>, pointer: &Pointer<E>) -> Option<Entity> {
let PointerTraversalItem { child_of, window } = item; let PointerTraversalItem { child_of, window } = item;
// Send event to parent, if it has one. // Send event to parent, if it has one.

View File

@ -43,7 +43,7 @@ pub fn derive_extract_component(input: TokenStream) -> TokenStream {
type QueryFilter = #filter; type QueryFilter = #filter;
type Out = Self; type Out = Self;
fn extract_component(item: #bevy_ecs_path::query::QueryItem<'_, Self::QueryData>) -> Option<Self::Out> { fn extract_component(item: #bevy_ecs_path::query::QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
Some(item.clone()) Some(item.clone())
} }
} }

View File

@ -60,7 +60,7 @@ pub trait ExtractComponent: Component {
// type Out: Component = Self; // type Out: Component = Self;
/// Defines how the component is transferred into the "render world". /// Defines how the component is transferred into the "render world".
fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option<Self::Out>; fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out>;
} }
/// This plugin prepares the components of the corresponding type for the GPU /// This plugin prepares the components of the corresponding type for the GPU

View File

@ -34,7 +34,7 @@ pub trait ExtractInstance: Send + Sync + Sized + 'static {
type QueryFilter: QueryFilter; type QueryFilter: QueryFilter;
/// Defines how the component is transferred into the "render world". /// Defines how the component is transferred into the "render world".
fn extract(item: QueryItem<'_, Self::QueryData>) -> Option<Self>; fn extract(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self>;
} }
/// This plugin extracts one or more components into the "render world" as /// This plugin extracts one or more components into the "render world" as

View File

@ -366,7 +366,7 @@ pub trait ViewNode {
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
view_query: QueryItem<'w, Self::ViewQuery>, view_query: QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError>; ) -> Result<(), NodeRunError>;
} }

View File

@ -213,8 +213,8 @@ pub trait RenderCommand<P: PhaseItem> {
/// issuing draw calls, etc.) via the [`TrackedRenderPass`]. /// issuing draw calls, etc.) via the [`TrackedRenderPass`].
fn render<'w>( fn render<'w>(
item: &P, item: &P,
view: ROQueryItem<'w, Self::ViewQuery>, view: ROQueryItem<'w, '_, Self::ViewQuery>,
entity: Option<ROQueryItem<'w, Self::ItemQuery>>, entity: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
param: SystemParamItem<'w, '_, Self::Param>, param: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult; ) -> RenderCommandResult;
@ -246,8 +246,8 @@ macro_rules! render_command_tuple_impl {
)] )]
fn render<'w>( fn render<'w>(
_item: &P, _item: &P,
($($view,)*): ROQueryItem<'w, Self::ViewQuery>, ($($view,)*): ROQueryItem<'w, '_, Self::ViewQuery>,
maybe_entities: Option<ROQueryItem<'w, Self::ItemQuery>>, maybe_entities: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
($($name,)*): SystemParamItem<'w, '_, Self::Param>, ($($name,)*): SystemParamItem<'w, '_, Self::Param>,
_pass: &mut TrackedRenderPass<'w>, _pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult { ) -> RenderCommandResult {

View File

@ -281,7 +281,7 @@ mod render_entities_world_query_impls {
archetype::Archetype, archetype::Archetype,
component::{ComponentId, Components, Tick}, component::{ComponentId, Components, Tick},
entity::Entity, entity::Entity,
query::{FilteredAccess, QueryData, ReadOnlyQueryData, WorldQuery}, query::{FilteredAccess, QueryData, ReadOnlyQueryData, ReleaseStateQueryData, WorldQuery},
storage::{Table, TableRow}, storage::{Table, TableRow},
world::{unsafe_world_cell::UnsafeWorldCell, World}, world::{unsafe_world_cell::UnsafeWorldCell, World},
}; };
@ -289,22 +289,22 @@ mod render_entities_world_query_impls {
/// SAFETY: defers completely to `&RenderEntity` implementation, /// SAFETY: defers completely to `&RenderEntity` implementation,
/// and then only modifies the output safely. /// and then only modifies the output safely.
unsafe impl WorldQuery for RenderEntity { unsafe impl WorldQuery for RenderEntity {
type Fetch<'w> = <&'static RenderEntity as WorldQuery>::Fetch<'w>; type Fetch<'w, 's> = <&'static RenderEntity as WorldQuery>::Fetch<'w, 's>;
type State = <&'static RenderEntity as WorldQuery>::State; type State = <&'static RenderEntity as WorldQuery>::State;
fn shrink_fetch<'wlong: 'wshort, 'wshort>( fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
fetch: Self::Fetch<'wlong>, fetch: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort> { ) -> Self::Fetch<'wshort, 's> {
fetch fetch
} }
#[inline] #[inline]
unsafe fn init_fetch<'w>( unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
component_id: &ComponentId, component_id: &'s ComponentId,
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) -> Self::Fetch<'w> { ) -> Self::Fetch<'w, 's> {
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`. // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
unsafe { unsafe {
<&RenderEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run) <&RenderEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run)
@ -314,9 +314,9 @@ mod render_entities_world_query_impls {
const IS_DENSE: bool = <&'static RenderEntity as WorldQuery>::IS_DENSE; const IS_DENSE: bool = <&'static RenderEntity as WorldQuery>::IS_DENSE;
#[inline] #[inline]
unsafe fn set_archetype<'w>( unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
component_id: &ComponentId, component_id: &'s ComponentId,
archetype: &'w Archetype, archetype: &'w Archetype,
table: &'w Table, table: &'w Table,
) { ) {
@ -327,9 +327,9 @@ mod render_entities_world_query_impls {
} }
#[inline] #[inline]
unsafe fn set_table<'w>( unsafe fn set_table<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
&component_id: &ComponentId, &component_id: &'s ComponentId,
table: &'w Table, table: &'w Table,
) { ) {
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`. // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
@ -364,18 +364,20 @@ mod render_entities_world_query_impls {
unsafe impl QueryData for RenderEntity { unsafe impl QueryData for RenderEntity {
const IS_READ_ONLY: bool = true; const IS_READ_ONLY: bool = true;
type ReadOnly = RenderEntity; type ReadOnly = RenderEntity;
type Item<'w> = Entity; type Item<'w, 's> = Entity;
fn shrink<'wlong: 'wshort, 'wshort>(item: Entity) -> Entity { fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item item
} }
#[inline(always)] #[inline(always)]
unsafe fn fetch<'w>( unsafe fn fetch<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
entity: Entity, entity: Entity,
table_row: TableRow, table_row: TableRow,
) -> Self::Item<'w> { ) -> Self::Item<'w, 's> {
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`. // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
let component = let component =
unsafe { <&RenderEntity as QueryData>::fetch(fetch, entity, table_row) }; unsafe { <&RenderEntity as QueryData>::fetch(fetch, entity, table_row) };
@ -386,25 +388,31 @@ mod render_entities_world_query_impls {
// SAFETY: the underlying `Entity` is copied, and no mutable access is provided. // SAFETY: the underlying `Entity` is copied, and no mutable access is provided.
unsafe impl ReadOnlyQueryData for RenderEntity {} unsafe impl ReadOnlyQueryData for RenderEntity {}
impl ReleaseStateQueryData for RenderEntity {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
/// SAFETY: defers completely to `&RenderEntity` implementation, /// SAFETY: defers completely to `&RenderEntity` implementation,
/// and then only modifies the output safely. /// and then only modifies the output safely.
unsafe impl WorldQuery for MainEntity { unsafe impl WorldQuery for MainEntity {
type Fetch<'w> = <&'static MainEntity as WorldQuery>::Fetch<'w>; type Fetch<'w, 's> = <&'static MainEntity as WorldQuery>::Fetch<'w, 's>;
type State = <&'static MainEntity as WorldQuery>::State; type State = <&'static MainEntity as WorldQuery>::State;
fn shrink_fetch<'wlong: 'wshort, 'wshort>( fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
fetch: Self::Fetch<'wlong>, fetch: Self::Fetch<'wlong, 's>,
) -> Self::Fetch<'wshort> { ) -> Self::Fetch<'wshort, 's> {
fetch fetch
} }
#[inline] #[inline]
unsafe fn init_fetch<'w>( unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
component_id: &ComponentId, component_id: &'s ComponentId,
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
) -> Self::Fetch<'w> { ) -> Self::Fetch<'w, 's> {
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`. // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
unsafe { unsafe {
<&MainEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run) <&MainEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run)
@ -414,8 +422,8 @@ mod render_entities_world_query_impls {
const IS_DENSE: bool = <&'static MainEntity as WorldQuery>::IS_DENSE; const IS_DENSE: bool = <&'static MainEntity as WorldQuery>::IS_DENSE;
#[inline] #[inline]
unsafe fn set_archetype<'w>( unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
component_id: &ComponentId, component_id: &ComponentId,
archetype: &'w Archetype, archetype: &'w Archetype,
table: &'w Table, table: &'w Table,
@ -427,9 +435,9 @@ mod render_entities_world_query_impls {
} }
#[inline] #[inline]
unsafe fn set_table<'w>( unsafe fn set_table<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
&component_id: &ComponentId, &component_id: &'s ComponentId,
table: &'w Table, table: &'w Table,
) { ) {
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`. // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
@ -464,18 +472,20 @@ mod render_entities_world_query_impls {
unsafe impl QueryData for MainEntity { unsafe impl QueryData for MainEntity {
const IS_READ_ONLY: bool = true; const IS_READ_ONLY: bool = true;
type ReadOnly = MainEntity; type ReadOnly = MainEntity;
type Item<'w> = Entity; type Item<'w, 's> = Entity;
fn shrink<'wlong: 'wshort, 'wshort>(item: Entity) -> Entity { fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item item
} }
#[inline(always)] #[inline(always)]
unsafe fn fetch<'w>( unsafe fn fetch<'w, 's>(
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w, 's>,
entity: Entity, entity: Entity,
table_row: TableRow, table_row: TableRow,
) -> Self::Item<'w> { ) -> Self::Item<'w, 's> {
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`. // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
let component = unsafe { <&MainEntity as QueryData>::fetch(fetch, entity, table_row) }; let component = unsafe { <&MainEntity as QueryData>::fetch(fetch, entity, table_row) };
component.id() component.id()
@ -484,6 +494,12 @@ mod render_entities_world_query_impls {
// SAFETY: the underlying `Entity` is copied, and no mutable access is provided. // SAFETY: the underlying `Entity` is copied, and no mutable access is provided.
unsafe impl ReadOnlyQueryData for MainEntity {} unsafe impl ReadOnlyQueryData for MainEntity {}
impl ReleaseStateQueryData for MainEntity {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -778,7 +778,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMesh2dViewBindGroup<I
#[inline] #[inline]
fn render<'w>( fn render<'w>(
_item: &P, _item: &P,
(view_uniform, mesh2d_view_bind_group): ROQueryItem<'w, Self::ViewQuery>, (view_uniform, mesh2d_view_bind_group): ROQueryItem<'w, '_, Self::ViewQuery>,
_view: Option<()>, _view: Option<()>,
_param: SystemParamItem<'w, '_, Self::Param>, _param: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,

View File

@ -372,7 +372,7 @@ impl ViewNode for Wireframe2dNode {
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
(camera, view, target, depth): QueryItem<'w, Self::ViewQuery>, (camera, view, target, depth): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let Some(wireframe_phase) = let Some(wireframe_phase) =

View File

@ -908,7 +908,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetSpriteViewBindGroup<I
fn render<'w>( fn render<'w>(
_item: &P, _item: &P,
(view_uniform, sprite_view_bind_group): ROQueryItem<'w, Self::ViewQuery>, (view_uniform, sprite_view_bind_group): ROQueryItem<'w, '_, Self::ViewQuery>,
_entity: Option<()>, _entity: Option<()>,
_param: SystemParamItem<'w, '_, Self::Param>, _param: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,
@ -925,7 +925,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetSpriteTextureBindGrou
fn render<'w>( fn render<'w>(
item: &P, item: &P,
view: ROQueryItem<'w, Self::ViewQuery>, view: ROQueryItem<'w, '_, Self::ViewQuery>,
_entity: Option<()>, _entity: Option<()>,
(image_bind_groups, batches): SystemParamItem<'w, '_, Self::Param>, (image_bind_groups, batches): SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,
@ -955,7 +955,7 @@ impl<P: PhaseItem> RenderCommand<P> for DrawSpriteBatch {
fn render<'w>( fn render<'w>(
item: &P, item: &P,
view: ROQueryItem<'w, Self::ViewQuery>, view: ROQueryItem<'w, '_, Self::ViewQuery>,
_entity: Option<()>, _entity: Option<()>,
(sprite_meta, batches): SystemParamItem<'w, '_, Self::Param>, (sprite_meta, batches): SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,

View File

@ -276,7 +276,7 @@ impl<P: PhaseItem, M: UiMaterial, const I: usize> RenderCommand<P>
fn render<'w>( fn render<'w>(
_item: &P, _item: &P,
_view: (), _view: (),
material_handle: Option<ROQueryItem<'_, Self::ItemQuery>>, material_handle: Option<ROQueryItem<'_, '_, Self::ItemQuery>>,
materials: SystemParamItem<'w, '_, Self::Param>, materials: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult { ) -> RenderCommandResult {

View File

@ -137,7 +137,7 @@ fn print_components_iter_mut(
println!("Print components (iter_mut):"); println!("Print components (iter_mut):");
for e in &mut query { for e in &mut query {
// Re-declaring the variable to illustrate the type of the actual iterator item. // Re-declaring the variable to illustrate the type of the actual iterator item.
let e: CustomQueryItem<'_, _, _> = e; let e: CustomQueryItem<'_, '_, _, _> = e;
println!("Entity: {}", e.entity); println!("Entity: {}", e.entity);
println!("A: {:?}", e.a); println!("A: {:?}", e.a);
println!("B: {:?}", e.b); println!("B: {:?}", e.b);
@ -155,7 +155,7 @@ fn print_components_iter(
println!("Print components (iter):"); println!("Print components (iter):");
for e in &query { for e in &query {
// Re-declaring the variable to illustrate the type of the actual iterator item. // Re-declaring the variable to illustrate the type of the actual iterator item.
let e: CustomQueryReadOnlyItem<'_, _, _> = e; let e: CustomQueryReadOnlyItem<'_, '_, _, _> = e;
println!("Entity: {}", e.entity); println!("Entity: {}", e.entity);
println!("A: {:?}", e.a); println!("A: {:?}", e.a);
println!("B: {:?}", e.b); println!("B: {:?}", e.b);

View File

@ -73,8 +73,8 @@ where
fn render<'w>( fn render<'w>(
_: &P, _: &P,
_: ROQueryItem<'w, Self::ViewQuery>, _: ROQueryItem<'w, '_, Self::ViewQuery>,
_: Option<ROQueryItem<'w, Self::ItemQuery>>, _: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
custom_phase_item_buffers: SystemParamItem<'w, '_, Self::Param>, custom_phase_item_buffers: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult { ) -> RenderCommandResult {

View File

@ -588,7 +588,7 @@ impl ViewNode for CustomDrawNode {
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
render_context: &mut RenderContext<'w>, render_context: &mut RenderContext<'w>,
(camera, view, target): QueryItem<'w, Self::ViewQuery>, (camera, view, target): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World, world: &'w World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
// First, we need to get our phases resource // First, we need to get our phases resource

View File

@ -88,7 +88,7 @@ impl ExtractComponent for InstanceMaterialData {
type QueryFilter = (); type QueryFilter = ();
type Out = Self; type Out = Self;
fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option<Self> { fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self> {
Some(InstanceMaterialData(item.0.clone())) Some(InstanceMaterialData(item.0.clone()))
} }
} }

View File

@ -0,0 +1,65 @@
---
title: Query items can borrow from query state
pull_requests: [15396]
---
The `QueryData::Item` and `WorldQuery::Fetch` associated types and the `QueryItem` and `ROQueryItem` type aliases now have an additional lifetime parameter corresponding to the `'s` lifetime in `Query`.
Manual implementations of `WorldQuery` and `QueryData` will need to update the method signatures to include the new lifetimes.
Other uses of the types will need to be updated to include a lifetime parameter, although it can usually be passed as `'_`.
In particular, `ROQueryItem` is used when implementing `RenderCommand`.
Before:
```rust
// 0.16
fn render<'w>(
item: &P,
view: ROQueryItem<'w, Self::ViewQuery>,
entity: Option<ROQueryItem<'w, Self::ItemQuery>>,
param: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult;
// 0.17
fn render<'w>(
item: &P,
view: ROQueryItem<'w, '_, Self::ViewQuery>,
entity: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
param: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult;
```
---
Methods on `QueryState` that take `&mut self` may now result in conflicting borrows if the query items capture the lifetime of the mutable reference.
This affects `get()`, `iter()`, and others.
To fix the errors, first call `QueryState::update_archetypes()`, and then replace a call `state.foo(world, param)` with `state.query_manual(world).foo_inner(param)`.
Alternately, you may be able to restructure the code to call `state.query(world)` once and then make multiple calls using the `Query`.
```rust
let mut state: QueryState<_, _> = ...;
// 0.16
let d1 = state.get(world, e1);
let d2 = state.get(world, e2); // Error: cannot borrow `state` as mutable more than once at a time
println!("{d1:?}");
println!("{d2:?}");
// 0.17
state.update_archetypes(world);
let d1 = state.get_manual(world, e1);
let d2 = state.get_manual(world, e2);
// OR
state.update_archetypes(world);
let d1 = state.query_manual(world).get_inner(e1);
let d2 = state.query_manual(world).get_inner(e2);
// OR
let query = state.query(world);
let d1 = query.get_inner(e1);
let d1 = query.get_inner(e2);
println!("{d1:?}");
println!("{d2:?}");
```