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,
smaa_textures,
view_smaa_bind_groups,
): QueryItem<'w, Self::ViewQuery>,
): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World,
) -> Result<(), NodeRunError> {
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.")]
/// SAFETY: `ROQueryFetch<Self>` is the same as `QueryFetch<Self>`
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>;
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
}
unsafe fn init_fetch<'w>(
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
state: &Self::State,
state: &'s Self::State,
last_run: Tick,
this_run: Tick,
) -> Self::Fetch<'w> {
) -> Self::Fetch<'w, 's> {
// SAFETY:
// - `AssetChanges` is private and only accessed mutably in the `AssetEventSystems` system set.
// - `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;
unsafe fn set_archetype<'w>(
fetch: &mut Self::Fetch<'w>,
state: &Self::State,
unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w, 's>,
state: &'s Self::State,
archetype: &'w Archetype,
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 {
// SAFETY: We delegate to the inner `set_table` for `A`
unsafe {
@ -265,7 +271,7 @@ unsafe impl<A: AsAssetId> QueryFilter for AssetChanged<A> {
#[inline]
unsafe fn filter_fetch(
fetch: &mut Self::Fetch<'_>,
fetch: &mut Self::Fetch<'_, '_>,
entity: Entity,
table_row: TableRow,
) -> bool {

View File

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

View File

@ -227,7 +227,7 @@ impl ExtractComponent for Bloom {
type QueryFilter = With<Hdr>;
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 (
camera.physical_viewport_rect(),
camera.physical_viewport_size(),

View File

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

View File

@ -28,7 +28,7 @@ impl ViewNode for MainTransparentPass2dNode {
&self,
graph: &mut RenderGraphContext,
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,
) -> Result<(), NodeRunError> {
let Some(transparent_phases) =

View File

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

View File

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

View File

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

View File

@ -61,7 +61,7 @@ impl ViewNode for MsaaWritebackNode {
&self,
_graph: &mut RenderGraphContext,
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,
) -> Result<(), NodeRunError> {
if *msaa == Msaa::Off {

View File

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

View File

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

View File

@ -113,7 +113,9 @@ impl ExtractComponent for Skybox {
type QueryFilter = ();
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
.map(Exposure::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 mut generics = ast.generics;
generics.params.insert(0, parse_quote!('__w));
generics.params.insert(0, parse_quote!('__s));
generics
};
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 {
const IS_READ_ONLY: bool = true;
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>(
item: Self::Item<'__wlong>
) -> Self::Item<'__wshort> {
fn shrink<'__wlong: '__wshort, '__wshort, '__s>(
item: Self::Item<'__wlong, '__s>
) -> Self::Item<'__wshort, '__s> {
#read_only_item_struct_name {
#(
#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`.
#[inline(always)]
unsafe fn fetch<'__w>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
unsafe fn fetch<'__w, '__s>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
_entity: #path::entity::Entity,
_table_row: #path::storage::TableRow,
) -> Self::Item<'__w> {
) -> Self::Item<'__w, '__s> {
Self::Item {
#(#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 {
quote! {}
@ -301,11 +314,11 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
for #struct_name #user_ty_generics #user_where_clauses {
const IS_READ_ONLY: bool = #is_read_only;
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>(
item: Self::Item<'__wlong>
) -> Self::Item<'__wshort> {
fn shrink<'__wlong: '__wshort, '__wshort, '__s>(
item: Self::Item<'__wlong, '__s>
) -> Self::Item<'__wshort, '__s> {
#item_struct_name {
#(
#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`.
#[inline(always)]
unsafe fn fetch<'__w>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
unsafe fn fetch<'__w, '__s>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
_entity: #path::entity::Entity,
_table_row: #path::storage::TableRow,
) -> Self::Item<'__w> {
) -> Self::Item<'__w, '__s> {
Self::Item {
#(#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
}
};

View File

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

View File

@ -34,14 +34,14 @@ pub(crate) fn item_struct(
#derive_macro_call
#item_attrs
#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! {
#derive_macro_call
#item_attrs
#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! {
@ -78,8 +78,8 @@ pub(crate) fn world_query_impl(
)]
#[automatically_derived]
#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>,)*
#marker_name: &'__w (),
#(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w, '__s>,)*
#marker_name: (&'__w(), &'__s()),
}
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 {
Self {
#(#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
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;
fn shrink_fetch<'__wlong: '__wshort, '__wshort>(
fetch: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wlong>
) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wshort> {
fn shrink_fetch<'__wlong: '__wshort, '__wshort, '__s>(
fetch: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wlong, '__s>
) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wshort, '__s> {
#fetch_struct_name {
#(
#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>,
state: &Self::State,
state: &'__s Self::State,
_last_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 {
#(#named_field_idents:
<#field_types>::init_fetch(
@ -125,7 +125,7 @@ pub(crate) fn world_query_impl(
_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`
#[inline]
unsafe fn set_archetype<'__w>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
_state: &Self::State,
unsafe fn set_archetype<'__w, '__s>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
_state: &'__s Self::State,
_archetype: &'__w #path::archetype::Archetype,
_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`
#[inline]
unsafe fn set_table<'__w>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
_state: &Self::State,
unsafe fn set_table<'__w, '__s>(
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
_state: &'__s Self::State,
_table: &'__w #path::storage::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,
}
impl<'a> core::fmt::Display for NameOrEntityItem<'a> {
impl<'w, 's> core::fmt::Display for NameOrEntityItem<'w, 's> {
#[inline(always)]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self.name {
@ -274,9 +274,9 @@ mod tests {
let e2 = world.spawn(name.clone()).id();
let mut query = world.query::<NameOrEntity>();
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}
assert_eq!(d1.to_string(), "0v0");
let d2 = query.get(&world, e2).unwrap();
// NameOrEntity Display for entities with a Name should be the Name
assert_eq!(d2.to_string(), "MyName");
}

View File

@ -1078,7 +1078,7 @@ mod tests {
struct ChildOf(Entity);
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)
}
}

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

View File

@ -140,7 +140,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
range: Option<Range<u32>>,
) -> B
where
Func: FnMut(B, D::Item<'w>) -> B,
Func: FnMut(B, D::Item<'w, 's>) -> B,
{
if self.cursor.is_dense {
// 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>,
) -> B
where
Func: FnMut(B, D::Item<'w>) -> B,
Func: FnMut(B, D::Item<'w, 's>) -> B,
{
if table.is_empty() {
return accum;
@ -255,7 +255,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
indices: Range<u32>,
) -> B
where
Func: FnMut(B, D::Item<'w>) -> B,
Func: FnMut(B, D::Item<'w, 's>) -> B,
{
if archetype.is_empty() {
return accum;
@ -324,7 +324,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
rows: Range<u32>,
) -> B
where
Func: FnMut(B, D::Item<'w>) -> B,
Func: FnMut(B, D::Item<'w, 's>) -> B,
{
if archetype.is_empty() {
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,
>
where
for<'lw> L::Item<'lw>: Ord,
for<'lw, 'ls> L::Item<'lw, 'ls>: Ord,
{
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,
>
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())
}
@ -605,7 +605,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
/// ```
pub fn sort_by<L: ReadOnlyQueryData + 'w>(
self,
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering,
mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
) -> QuerySortedIter<
'w,
'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.
pub fn sort_unstable_by<L: ReadOnlyQueryData + 'w>(
self,
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering,
mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
) -> QuerySortedIter<
'w,
'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>(
self,
mut f: impl FnMut(&L::Item<'_>) -> K,
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedIter<
'w,
'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.
pub fn sort_unstable_by_key<L: ReadOnlyQueryData + 'w, K>(
self,
mut f: impl FnMut(&L::Item<'_>) -> K,
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedIter<
'w,
'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.
pub fn sort_by_cached_key<L: ReadOnlyQueryData + 'w, K>(
self,
mut f: impl FnMut(&L::Item<'_>) -> K,
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedIter<
'w,
'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.
fn sort_impl<L: ReadOnlyQueryData + 'w>(
self,
f: impl FnOnce(&mut Vec<(L::Item<'_>, NeutralOrd<Entity>)>),
f: impl FnOnce(&mut Vec<(L::Item<'_, '_>, NeutralOrd<Entity>)>),
) -> QuerySortedIter<
'w,
's,
@ -856,7 +856,11 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
.map(|(key, entity)| (key, NeutralOrd(entity)))
.collect();
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:
// `self.world` has permission to access the required components.
// 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> {
type Item = D::Item<'w>;
type Item = D::Item<'w, 's>;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
@ -975,7 +979,7 @@ where
entities: &'w Entities,
tables: &'w Tables,
archetypes: &'w Archetypes,
fetch: D::Fetch<'w>,
fetch: D::Fetch<'w, 's>,
query_state: &'s QueryState<D, F>,
}
@ -1010,7 +1014,7 @@ where
/// # Safety
/// `entity` must stem from `self.entity_iter`, and not have been passed before.
#[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);
// SAFETY:
// `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
I: Iterator<Item = Entity>,
{
type Item = D::Item<'w>;
type Item = D::Item<'w, 's>;
#[inline(always)]
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,
tables: &'w Tables,
archetypes: &'w Archetypes,
fetch: D::Fetch<'w>,
filter: F::Fetch<'w>,
fetch: D::Fetch<'w, 's>,
filter: F::Fetch<'w, 's>,
query_state: &'s QueryState<D, F>,
}
@ -1167,10 +1171,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
entities: &'w Entities,
tables: &'w Tables,
archetypes: &'w Archetypes,
fetch: &mut D::Fetch<'w>,
filter: &mut F::Fetch<'w>,
fetch: &mut D::Fetch<'w, 's>,
filter: &mut F::Fetch<'w, 's>,
query_state: &'s QueryState<D, F>,
) -> Option<D::Item<'w>> {
) -> Option<D::Item<'w, 's>> {
for entity_borrow in entity_iter {
let entity = entity_borrow.entity();
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
#[inline(always)]
pub fn fetch_next(&mut self) -> Option<D::Item<'_>> {
pub fn fetch_next(&mut self) -> Option<D::Item<'_, 's>> {
// SAFETY:
// All arguments stem from 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,
>
where
for<'lw> L::Item<'lw>: Ord,
for<'lw, 'ls> L::Item<'lw, 'ls>: Ord,
{
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,
>
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())
}
@ -1451,7 +1455,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// ```
pub fn sort_by<L: ReadOnlyQueryData + 'w>(
self,
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering,
mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
) -> QuerySortedManyIter<
'w,
's,
@ -1482,7 +1486,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// called on [`QueryManyIter`] before.
pub fn sort_unstable_by<L: ReadOnlyQueryData + 'w>(
self,
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering,
mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
) -> QuerySortedManyIter<
'w,
'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>(
self,
mut f: impl FnMut(&L::Item<'_>) -> K,
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedManyIter<
'w,
's,
@ -1608,7 +1612,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// called on [`QueryManyIter`] before.
pub fn sort_unstable_by_key<L: ReadOnlyQueryData + 'w, K>(
self,
mut f: impl FnMut(&L::Item<'_>) -> K,
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedManyIter<
'w,
's,
@ -1642,7 +1646,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// called on [`QueryManyIter`] before.
pub fn sort_by_cached_key<L: ReadOnlyQueryData + 'w, K>(
self,
mut f: impl FnMut(&L::Item<'_>) -> K,
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
) -> QuerySortedManyIter<
'w,
's,
@ -1671,7 +1675,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
/// called on [`QueryManyIter`] before.
fn sort_impl<L: ReadOnlyQueryData + 'w>(
self,
f: impl FnOnce(&mut Vec<(L::Item<'_>, NeutralOrd<Entity>)>),
f: impl FnOnce(&mut Vec<(L::Item<'_, '_>, NeutralOrd<Entity>)>),
) -> QuerySortedManyIter<
'w,
'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
#[inline(always)]
pub fn fetch_next_back(&mut self) -> Option<D::Item<'_>> {
pub fn fetch_next_back(&mut self) -> Option<D::Item<'_, 's>> {
// SAFETY:
// All arguments stem from 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
for QueryManyIter<'w, 's, D, F, I>
{
type Item = D::Item<'w>;
type Item = D::Item<'w, 's>;
#[inline(always)]
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
for QueryManyUniqueIter<'w, 's, D, F, I>
{
type Item = D::Item<'w>;
type Item = D::Item<'w, 's>;
#[inline(always)]
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,
tables: &'w Tables,
archetypes: &'w Archetypes,
fetch: D::Fetch<'w>,
fetch: D::Fetch<'w, 's>,
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.
/// `entity` must stem from `self.entity_iter`, and not have been passed before.
#[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);
// SAFETY:
// `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
#[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()?;
// SAFETY:
@ -2007,7 +2011,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator<Item = Entity>
{
/// Get next result from the query
#[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()?;
// 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
for QuerySortedManyIter<'w, 's, D, F, I>
{
type Item = D::Item<'w>;
type Item = D::Item<'w, 's>;
#[inline(always)]
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.
#[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()`
// 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() {
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
#[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,
// making sure this method cannot be called multiple times without getting rid
// 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
for QueryCombinationIter<'w, 's, D, F, K>
{
type Item = [D::Item<'w>; K];
type Item = [D::Item<'w, 's>; K];
#[inline]
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>,
table_entities: &'w [Entity],
archetype_entities: &'w [ArchetypeEntity],
fetch: D::Fetch<'w>,
filter: F::Fetch<'w>,
fetch: D::Fetch<'w, 's>,
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
current_len: u32,
// 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
/// dropped to prevent aliasing mutable references.
#[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 {
let index = self.current_row - 1;
if self.is_dense {
@ -2457,7 +2461,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> {
tables: &'w Tables,
archetypes: &'w Archetypes,
query_state: &'s QueryState<D, F>,
) -> Option<D::Item<'w>> {
) -> Option<D::Item<'w, 's>> {
if self.is_dense {
loop {
// 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:
/// `update_component_access` adds resource read access for `R`.
unsafe impl WorldQuery for ReadsRData {
type Fetch<'w> = ();
type Fetch<'w, 's> = ();
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>,
_state: &Self::State,
_state: &'s Self::State,
_last_run: Tick,
_this_run: Tick,
) -> Self::Fetch<'w> {
) -> Self::Fetch<'w, 's> {
}
const IS_DENSE: bool = true;
#[inline]
unsafe fn set_archetype<'w>(
_fetch: &mut Self::Fetch<'w>,
_state: &Self::State,
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w, 's>,
_state: &'s Self::State,
_archetype: &'w Archetype,
_table: &Table,
) {
}
#[inline]
unsafe fn set_table<'w>(
_fetch: &mut Self::Fetch<'w>,
_state: &Self::State,
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w, 's>,
_state: &'s Self::State,
_table: &'w Table,
) {
}
@ -882,16 +885,19 @@ mod tests {
unsafe impl QueryData for ReadsRData {
const IS_READ_ONLY: bool = true;
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)]
unsafe fn fetch<'w>(
_fetch: &mut Self::Fetch<'w>,
unsafe fn fetch<'w, 's>(
_fetch: &mut Self::Fetch<'w, 's>,
_entity: Entity,
_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
#[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));
}
@ -76,7 +76,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> {
#[inline]
pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN)
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,
{
let func = |mut init, item| {
@ -190,7 +190,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityEquivalent + Sync>
///
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
#[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));
}
@ -247,7 +247,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityEquivalent + Sync>
#[inline]
pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN)
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,
{
let func = |mut init, item| {
@ -345,7 +345,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: EntityEquivalent + Sync>
///
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
#[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));
}
@ -402,7 +402,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: EntityEquivalent + Sync>
#[inline]
pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN)
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,
{
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.
///
/// 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.
#[inline]
pub fn get<'w>(
&mut self,
world: &'w World,
entity: Entity,
) -> Result<ROQueryItem<'w, D>, QueryEntityError> {
) -> Result<ROQueryItem<'w, '_, D>, QueryEntityError> {
self.query(world).get_inner(entity)
}
@ -892,7 +896,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self,
world: &'w World,
entities: [Entity; N],
) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> {
) -> Result<[ROQueryItem<'w, '_, D>; N], QueryEntityError> {
self.query(world).get_many_inner(entities)
}
@ -930,7 +934,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self,
world: &'w World,
entities: UniqueEntityArray<N>,
) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> {
) -> Result<[ROQueryItem<'w, '_, D>; N], QueryEntityError> {
self.query(world).get_many_unique_inner(entities)
}
@ -942,7 +946,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self,
world: &'w mut World,
entity: Entity,
) -> Result<D::Item<'w>, QueryEntityError> {
) -> Result<D::Item<'w, '_>, QueryEntityError> {
self.query_mut(world).get_inner(entity)
}
@ -989,7 +993,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self,
world: &'w mut World,
entities: [Entity; N],
) -> Result<[D::Item<'w>; N], QueryEntityError> {
) -> Result<[D::Item<'w, '_>; N], QueryEntityError> {
self.query_mut(world).get_many_mut_inner(entities)
}
@ -1034,7 +1038,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self,
world: &'w mut World,
entities: UniqueEntityArray<N>,
) -> Result<[D::Item<'w>; N], QueryEntityError> {
) -> Result<[D::Item<'w, '_>; N], QueryEntityError> {
self.query_mut(world).get_many_unique_inner(entities)
}
@ -1056,7 +1060,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&self,
world: &'w World,
entity: Entity,
) -> Result<ROQueryItem<'w, D>, QueryEntityError> {
) -> Result<ROQueryItem<'w, '_, D>, QueryEntityError> {
self.query_manual(world).get_inner(entity)
}
@ -1073,13 +1077,16 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&mut self,
world: UnsafeWorldCell<'w>,
entity: Entity,
) -> Result<D::Item<'w>, QueryEntityError> {
) -> Result<D::Item<'w, '_>, QueryEntityError> {
self.query_unchecked(world).get_inner(entity)
}
/// 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.
///
/// 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]
pub fn iter<'w, 's>(&'s mut self, world: &'w World) -> QueryIter<'w, 's, D::ReadOnly, F> {
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.
/// 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
///
/// - [`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
#[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))]
pub(crate) unsafe fn par_fold_init_unchecked_manual<'w, T, FN, INIT>(
&self,
pub(crate) unsafe fn par_fold_init_unchecked_manual<'w, 's, T, FN, INIT>(
&'s self,
init_accum: INIT,
world: UnsafeWorldCell<'w>,
batch_size: u32,
@ -1396,7 +1406,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
last_run: Tick,
this_run: Tick,
) 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,
{
// 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
#[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>(
&self,
pub(crate) unsafe fn par_many_unique_fold_init_unchecked_manual<'w, 's, T, FN, INIT, E>(
&'s self,
init_accum: INIT,
world: UnsafeWorldCell<'w>,
entity_list: &UniqueEntityEquivalentSlice<E>,
@ -1511,7 +1521,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
last_run: Tick,
this_run: Tick,
) 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,
E: EntityEquivalent + Sync,
{
@ -1564,8 +1574,8 @@ impl<D: ReadOnlyQueryData, F: QueryFilter> QueryState<D, F> {
///
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
#[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))]
pub(crate) unsafe fn par_many_fold_init_unchecked_manual<'w, T, FN, INIT, E>(
&self,
pub(crate) unsafe fn par_many_fold_init_unchecked_manual<'w, 's, T, FN, INIT, E>(
&'s self,
init_accum: INIT,
world: UnsafeWorldCell<'w>,
entity_list: &[E],
@ -1574,7 +1584,7 @@ impl<D: ReadOnlyQueryData, F: QueryFilter> QueryState<D, F> {
last_run: Tick,
this_run: Tick,
) 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,
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.
#[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()
}
@ -1703,7 +1716,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
pub fn single_mut<'w>(
&mut self,
world: &'w mut World,
) -> Result<D::Item<'w>, QuerySingleError> {
) -> Result<D::Item<'w, '_>, QuerySingleError> {
self.query_mut(world).single_inner()
}
@ -1720,7 +1733,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
pub unsafe fn single_unchecked<'w>(
&mut self,
world: UnsafeWorldCell<'w>,
) -> Result<D::Item<'w>, QuerySingleError> {
) -> Result<D::Item<'w, '_>, QuerySingleError> {
self.query_unchecked(world).single_inner()
}
@ -1742,7 +1755,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
world: UnsafeWorldCell<'w>,
last_run: Tick,
this_run: Tick,
) -> Result<D::Item<'w>, QuerySingleError> {
) -> Result<D::Item<'w, '_>, QuerySingleError> {
// SAFETY:
// - The caller ensured we have the correct access to the world.
// - The caller ensured that the world matches.

View File

@ -42,7 +42,7 @@ use variadics_please::all_tuples;
/// [`QueryFilter`]: crate::query::QueryFilter
pub unsafe trait WorldQuery {
/// 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),
/// 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;
/// 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),
/// 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.
/// - `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`].
unsafe fn init_fetch<'w>(
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
state: &Self::State,
state: &'s Self::State,
last_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
/// 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.
/// - `table` must correspond to `archetype`.
/// - `state` must be the [`State`](Self::State) that `fetch` was initialized with.
unsafe fn set_archetype<'w>(
fetch: &mut Self::Fetch<'w>,
state: &Self::State,
unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w, 's>,
state: &'s Self::State,
archetype: &'w Archetype,
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.
/// - `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`.
///
@ -154,11 +160,11 @@ macro_rules! impl_tuple_world_query {
/// `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`.
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,)*);
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;
($(
$name::shrink_fetch($name),
@ -166,7 +172,7 @@ macro_rules! impl_tuple_world_query {
}
#[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;
// SAFETY: The invariants are upheld by the caller.
($(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)*;
#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut Self::Fetch<'w>,
state: &Self::State,
unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w, 's>,
state: &'s Self::State,
archetype: &'w Archetype,
table: &'w Table
) {
@ -188,7 +194,7 @@ macro_rules! impl_tuple_world_query {
}
#[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 ($($state,)*) = state;
// 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.
pub fn related<R: Relationship>(&'w self, entity: Entity) -> Option<Entity>
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()
}
@ -26,7 +26,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
entity: Entity,
) -> impl Iterator<Item = Entity> + 'w
where
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>,
<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{
self.get(entity)
.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.
pub fn root_ancestor<R: Relationship>(&'w self, entity: Entity) -> Entity
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
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>(
&'w self,
entity: Entity,
) -> impl Iterator<Item = Entity> + 'w
) -> impl Iterator<Item = Entity> + use<'w, 's, S, D, F>
where
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>,
<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator,
{
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,
) -> impl Iterator<Item = Entity> + 'w
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)
.ok()
@ -103,7 +103,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
entity: Entity,
) -> DescendantIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{
DescendantIter::new(self, entity)
}
@ -120,7 +120,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
entity: Entity,
) -> DescendantDepthFirstIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator,
{
DescendantDepthFirstIter::new(self, entity)
@ -137,7 +137,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
entity: Entity,
) -> AncestorIter<'w, 's, D, F, R>
where
D::ReadOnly: QueryData<Item<'w> = &'w R>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
{
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.
pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{
children_query: &'w Query<'w, 's, D, F>,
vecdeque: VecDeque<Entity>,
@ -156,7 +156,7 @@ where
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{
/// Returns a new [`DescendantIter`].
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
for DescendantIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{
type Item = Entity;
@ -194,7 +194,7 @@ where
/// Traverses the hierarchy depth-first.
pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
{
children_query: &'w Query<'w, 's, D, F>,
stack: SmallVec<[Entity; 8]>,
@ -203,7 +203,7 @@ where
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
DescendantDepthFirstIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator,
{
/// Returns a new [`DescendantDepthFirstIter`].
@ -220,7 +220,7 @@ where
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator
for DescendantDepthFirstIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator,
{
type Item = Entity;
@ -239,7 +239,7 @@ where
/// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`].
pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter, R: Relationship>
where
D::ReadOnly: QueryData<Item<'w> = &'w R>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
{
parent_query: &'w Query<'w, 's, D, F>,
next: Option<Entity>,
@ -247,7 +247,7 @@ where
impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> AncestorIter<'w, 's, D, F, R>
where
D::ReadOnly: QueryData<Item<'w> = &'w R>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
{
/// Returns a new [`AncestorIter`].
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
for AncestorIter<'w, 's, D, F, R>
where
D::ReadOnly: QueryData<Item<'w> = &'w R>,
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
{
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
/// [`World`]: crate::world::World
#[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()
}
@ -1220,7 +1220,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// [`par_iter`]: Self::par_iter
/// [`World`]: crate::world::World
#[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()
}
@ -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>>(
&self,
entities: EntityList,
) -> QueryParManyIter<'_, '_, D::ReadOnly, F, EntityList::Item> {
) -> QueryParManyIter<'_, 's, D::ReadOnly, F, EntityList::Item> {
QueryParManyIter {
world: self.world,
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>>(
&self,
entities: EntityList,
) -> QueryParManyUniqueIter<'_, '_, D::ReadOnly, F, EntityList::Item> {
) -> QueryParManyUniqueIter<'_, 's, D::ReadOnly, F, EntityList::Item> {
QueryParManyUniqueIter {
world: self.world,
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>>(
&mut self,
entities: EntityList,
) -> QueryParManyUniqueIter<'_, '_, D, F, EntityList::Item> {
) -> QueryParManyUniqueIter<'_, 's, D, F, EntityList::Item> {
QueryParManyUniqueIter {
world: self.world,
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.
#[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)
}
@ -1434,7 +1434,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn get_many<const N: usize>(
&self,
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`
// because we don't need to check for duplicates.
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>(
&self,
entities: UniqueEntityArray<N>,
) -> Result<[ROQueryItem<'_, D>; N], QueryEntityError> {
) -> Result<[ROQueryItem<'_, 's, D>; N], QueryEntityError> {
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.
#[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)
}
@ -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`].
#[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.
// same-system queries have runtime borrow checks when they conflict
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>(
&mut self,
entities: [Entity; N],
) -> Result<[D::Item<'_>; N], QueryEntityError> {
) -> Result<[D::Item<'_, 's>; N], QueryEntityError> {
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>(
&mut self,
entities: UniqueEntityArray<N>,
) -> Result<[D::Item<'_>; N], QueryEntityError> {
) -> Result<[D::Item<'_, 's>; N], QueryEntityError> {
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>(
self,
entities: [Entity; N],
) -> Result<[D::Item<'w>; N], QueryEntityError> {
) -> Result<[D::Item<'w, 's>; N], QueryEntityError> {
// Verify that all entities are unique
for i in 0..N {
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>(
self,
entities: [Entity; N],
) -> Result<[D::Item<'w>; N], QueryEntityError>
) -> Result<[D::Item<'w, 's>; N], QueryEntityError>
where
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>(
self,
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.
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>(
self,
entities: [Entity; N],
) -> Result<[D::Item<'w>; N], QueryEntityError> {
) -> Result<[D::Item<'w, 's>; N], QueryEntityError> {
let mut values = [(); N].map(|_| MaybeUninit::uninit());
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.
#[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.
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.
#[inline]
pub fn single(&self) -> Result<ROQueryItem<'_, D>, QuerySingleError> {
pub fn single(&self) -> Result<ROQueryItem<'_, 's, D>, QuerySingleError> {
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.
#[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()
}
@ -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_inner`](Self::single_inner) for the panicking version.
#[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 first = query.next();
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> {
type Item = D::Item<'w>;
type Item = D::Item<'w, 's>;
type IntoIter = QueryIter<'w, 's, D, F>;
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> {
type Item = ROQueryItem<'w, D>;
type Item = ROQueryItem<'w, 's, D>;
type IntoIter = QueryIter<'w, 's, D::ReadOnly, F>;
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> {
type Item = D::Item<'w>;
type Item = D::Item<'w, 's>;
type IntoIter = QueryIter<'w, 's, D, F>;
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.
/// 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(crate) item: D::Item<'w>,
pub struct Single<'w, 's, D: QueryData, F: QueryFilter = ()> {
pub(crate) item: D::Item<'w, 's>,
pub(crate) _filter: PhantomData<F>,
}
impl<'w, D: QueryData, F: QueryFilter> Deref for Single<'w, D, F> {
type Target = D::Item<'w>;
impl<'w, 's, D: QueryData, F: QueryFilter> Deref for Single<'w, 's, D, F> {
type Target = D::Item<'w, 's>;
fn deref(&self) -> &Self::Target {
&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 {
&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.
pub fn into_inner(self) -> D::Item<'w> {
pub fn into_inner(self) -> D::Item<'w, 's> {
self.item
}
}

View File

@ -389,9 +389,11 @@ fn assert_component_access_compatibility(
// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If
// 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 Item<'w, 's> = Single<'w, D, F>;
type Item<'w, 's> = Single<'w, 's, D, F>;
fn init_state(world: &mut World) -> Self::State {
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.
unsafe impl<'a, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
for Single<'a, D, F>
unsafe impl<'a, 'b, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
for Single<'a, 'b, D, F>
{
}

View File

@ -1,6 +1,10 @@
//! 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.
///
@ -20,13 +24,13 @@ use crate::{entity::Entity, query::ReadOnlyQueryData, relationship::Relationship
/// [specify the direction]: crate::event::EntityEvent::Traversal
/// [event propagation]: crate::observer::On::propagate
/// [observers]: crate::observer::Observer
pub trait Traversal<D: ?Sized>: ReadOnlyQueryData {
pub trait Traversal<D: ?Sized>: ReadOnlyQueryData + ReleaseStateQueryData {
/// 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 () {
fn traverse(_: Self::Item<'_>, _data: &D) -> Option<Entity> {
fn traverse(_: Self::Item<'_, '_>, _data: &D) -> Option<Entity> {
None
}
}
@ -39,7 +43,7 @@ impl<D> Traversal<D> for () {
///
/// [event propagation]: crate::observer::On::propagate
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())
}
}

View File

@ -16,7 +16,7 @@ use crate::{
event::EntityEvent,
lifecycle::{DESPAWN, REMOVE, REPLACE},
observer::Observer,
query::{Access, DebugCheckedUnwrap, ReadOnlyQueryData},
query::{Access, DebugCheckedUnwrap, ReadOnlyQueryData, ReleaseStateQueryData},
relationship::RelationshipHookMode,
resource::Resource,
system::IntoObserverSystem,
@ -279,14 +279,16 @@ impl<'w> EntityRef<'w> {
/// # Panics
///
/// 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>()
.expect("Query does not match the current entity")
}
/// 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`.
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.
unsafe { self.cell.get_components::<Q>() }
}
@ -546,13 +548,15 @@ impl<'w> EntityMut<'w> {
/// # Panics
///
/// 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>()
}
/// 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`.
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>()
}
@ -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
/// has been despawned while this `EntityWorldMut` is still alive.
#[inline]
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_> {
pub fn components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(&self) -> Q::Item<'_, 'static> {
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.
#[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>()
}

View File

@ -11,7 +11,7 @@ use crate::{
lifecycle::RemovedComponentEvents,
observer::Observers,
prelude::Component,
query::{DebugCheckedUnwrap, ReadOnlyQueryData},
query::{DebugCheckedUnwrap, ReadOnlyQueryData, ReleaseStateQueryData},
resource::Resource,
storage::{ComponentSparseSet, Storages, Table},
world::RawCommandQueue,
@ -998,7 +998,9 @@ impl<'w> UnsafeEntityCell<'w> {
/// It is the caller's responsibility to ensure that
/// - the [`UnsafeEntityCell`] has permission to access the queried data immutably
/// - 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
let state = unsafe {
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.
unsafe { Q::set_archetype(&mut fetch, &state, archetype, table) }
// 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 {
None
}

View File

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

View File

@ -155,7 +155,7 @@ pub struct 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;
// Send event to parent, if it has one.

View File

@ -309,7 +309,7 @@ impl ExtractComponent for 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())
}
}
@ -405,7 +405,7 @@ impl ExtractComponent for 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())
}
}

View File

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

View File

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

View File

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

View File

@ -280,7 +280,7 @@ impl ViewNode for ScreenSpaceReflectionsNode {
view_environment_map_offset,
view_bind_group,
ssr_pipeline_id,
): QueryItem<'w, Self::ViewQuery>,
): QueryItem<'w, '_, Self::ViewQuery>,
world: &'w World,
) -> Result<(), NodeRunError> {
// Grab the render pipeline.
@ -498,7 +498,7 @@ impl ExtractComponent for ScreenSpaceReflections {
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 {
once!(info!(
"Disabling screen-space reflections on this platform because depth textures \

View File

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

View File

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

View File

@ -86,7 +86,7 @@ impl<E> Traversal<Pointer<E>> for PointerTraversal
where
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;
// 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 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())
}
}

View File

@ -60,7 +60,7 @@ pub trait ExtractComponent: Component {
// type Out: Component = Self;
/// 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

View File

@ -34,7 +34,7 @@ pub trait ExtractInstance: Send + Sync + Sized + 'static {
type QueryFilter: QueryFilter;
/// 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -137,7 +137,7 @@ fn print_components_iter_mut(
println!("Print components (iter_mut):");
for e in &mut query {
// 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!("A: {:?}", e.a);
println!("B: {:?}", e.b);
@ -155,7 +155,7 @@ fn print_components_iter(
println!("Print components (iter):");
for e in &query {
// 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!("A: {:?}", e.a);
println!("B: {:?}", e.b);

View File

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

View File

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

View File

@ -88,7 +88,7 @@ impl ExtractComponent for InstanceMaterialData {
type QueryFilter = ();
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()))
}
}

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:?}");
```