diff --git a/crates/bevy_asset/src/asset_changed.rs b/crates/bevy_asset/src/asset_changed.rs index 5fc959eada8bd..71186a4b4e7f6 100644 --- a/crates/bevy_asset/src/asset_changed.rs +++ b/crates/bevy_asset/src/asset_changed.rs @@ -151,20 +151,22 @@ pub struct AssetChangedState { #[expect(unsafe_code, reason = "WorldQuery is an unsafe trait.")] /// SAFETY: `ROQueryFetch` is the same as `QueryFetch` unsafe impl WorldQuery for AssetChanged { - type Fetch<'w> = AssetChangedFetch<'w, A>; + type Fetch<'w, 's> = AssetChangedFetch<'w, A>; type State = AssetChangedState; - 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 `AssetEvents` schedule // - `resource_id` was obtained from the type ID of `AssetChanges`. @@ -202,9 +204,9 @@ unsafe impl WorldQuery for AssetChanged { 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, ) { @@ -216,7 +218,11 @@ unsafe impl WorldQuery for AssetChanged { } } - 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 { @@ -266,7 +272,7 @@ unsafe impl QueryFilter for AssetChanged { #[inline] unsafe fn filter_fetch( - fetch: &mut Self::Fetch<'_>, + fetch: &mut Self::Fetch<'_, '_>, entity: Entity, table_row: TableRow, ) -> bool { diff --git a/crates/bevy_core_pipeline/src/bloom/settings.rs b/crates/bevy_core_pipeline/src/bloom/settings.rs index 2e22875a35f12..fdff1b9b16e8d 100644 --- a/crates/bevy_core_pipeline/src/bloom/settings.rs +++ b/crates/bevy_core_pipeline/src/bloom/settings.rs @@ -220,7 +220,7 @@ impl ExtractComponent for Bloom { type QueryFilter = (); type Out = (Self, BloomUniforms); - fn extract_component((bloom, camera): QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component((bloom, camera): QueryItem<'_, '_, Self::QueryData>) -> Option { match ( camera.physical_viewport_rect(), camera.physical_viewport_size(), diff --git a/crates/bevy_core_pipeline/src/core_2d/main_opaque_pass_2d_node.rs b/crates/bevy_core_pipeline/src/core_2d/main_opaque_pass_2d_node.rs index 60f355c1153db..e8cd0c65c6888 100644 --- a/crates/bevy_core_pipeline/src/core_2d/main_opaque_pass_2d_node.rs +++ b/crates/bevy_core_pipeline/src/core_2d/main_opaque_pass_2d_node.rs @@ -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)) = ( diff --git a/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs b/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs index dae9217d3a867..3ef48202156f1 100644 --- a/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs +++ b/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs @@ -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) = diff --git a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs index 3b1bc96c9014d..b19268ac1f5cd 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs @@ -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)) = ( diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index ffac1eec6de82..e786d2a222cb8 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -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, + '_, ::ViewQuery, >, is_late: bool, diff --git a/crates/bevy_core_pipeline/src/dof/mod.rs b/crates/bevy_core_pipeline/src/dof/mod.rs index 028bc97350f56..d49152de443d8 100644 --- a/crates/bevy_core_pipeline/src/dof/mod.rs +++ b/crates/bevy_core_pipeline/src/dof/mod.rs @@ -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::(); diff --git a/crates/bevy_core_pipeline/src/msaa_writeback.rs b/crates/bevy_core_pipeline/src/msaa_writeback.rs index f9c543aeff03c..b006cf81d9a36 100644 --- a/crates/bevy_core_pipeline/src/msaa_writeback.rs +++ b/crates/bevy_core_pipeline/src/msaa_writeback.rs @@ -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 { diff --git a/crates/bevy_core_pipeline/src/post_process/mod.rs b/crates/bevy_core_pipeline/src/post_process/mod.rs index c8b1da4497363..3761344c28819 100644 --- a/crates/bevy_core_pipeline/src/post_process/mod.rs +++ b/crates/bevy_core_pipeline/src/post_process/mod.rs @@ -364,7 +364,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::(); @@ -497,7 +497,7 @@ impl ExtractComponent for ChromaticAberration { type Out = ChromaticAberration; fn extract_component( - chromatic_aberration: QueryItem<'_, Self::QueryData>, + chromatic_aberration: QueryItem<'_, '_, Self::QueryData>, ) -> Option { // Skip the postprocessing phase entirely if the intensity is zero. if chromatic_aberration.intensity > 0.0 { diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index 04cc1890b0235..500cc0a42b374 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -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, ::ViewQuery>, + ): QueryItem<'w, '_, ::ViewQuery>, world: &'w World, label: &'static str, ) -> Result<(), NodeRunError> { diff --git a/crates/bevy_core_pipeline/src/skybox/mod.rs b/crates/bevy_core_pipeline/src/skybox/mod.rs index 6e1a8422768a8..57ecd6fe5ddb0 100644 --- a/crates/bevy_core_pipeline/src/skybox/mod.rs +++ b/crates/bevy_core_pipeline/src/skybox/mod.rs @@ -119,7 +119,9 @@ impl ExtractComponent for Skybox { type QueryFilter = (); type Out = (Self, SkyboxUniforms); - fn extract_component((skybox, exposure): QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component( + (skybox, exposure): QueryItem<'_, '_, Self::QueryData>, + ) -> Option { let exposure = exposure .map(Exposure::exposure) .unwrap_or_else(|| Exposure::default().exposure()); diff --git a/crates/bevy_core_pipeline/src/smaa/mod.rs b/crates/bevy_core_pipeline/src/smaa/mod.rs index fb066a3ce538c..8424086d8fb2b 100644 --- a/crates/bevy_core_pipeline/src/smaa/mod.rs +++ b/crates/bevy_core_pipeline/src/smaa/mod.rs @@ -842,7 +842,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::(); diff --git a/crates/bevy_ecs/macros/src/query_data.rs b/crates/bevy_ecs/macros/src/query_data.rs index d919d0b05e125..6f4275de243cf 100644 --- a/crates/bevy_ecs/macros/src/query_data.rs +++ b/crates/bevy_ecs/macros/src/query_data.rs @@ -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), @@ -270,16 +271,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 ::Fetch<'__w>, + unsafe fn fetch<'__w, '__s>( + _fetch: &mut ::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,)* { + 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! {} @@ -293,11 +306,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), @@ -307,17 +320,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 ::Fetch<'__w>, + unsafe fn fetch<'__w, '__s>( + _fetch: &mut ::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 } }; diff --git a/crates/bevy_ecs/macros/src/query_filter.rs b/crates/bevy_ecs/macros/src/query_filter.rs index c7ddb9cc83521..acc5c3d41b1ba 100644 --- a/crates/bevy_ecs/macros/src/query_filter.rs +++ b/crates/bevy_ecs/macros/src/query_filter.rs @@ -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 ::Fetch<'__w>, + unsafe fn filter_fetch<'__w, '__s>( + _fetch: &mut ::Fetch<'__w, '__s>, _entity: #path::entity::Entity, _table_row: #path::storage::TableRow, ) -> bool { diff --git a/crates/bevy_ecs/macros/src/world_query.rs b/crates/bevy_ecs/macros/src/world_query.rs index 77ee532a505f7..e96db40e6c32c 100644 --- a/crates/bevy_ecs/macros/src/world_query.rs +++ b/crates/bevy_ecs/macros/src/world_query.rs @@ -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, - ) -> ::Fetch<'__w> { + ) -> ::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 ::Fetch<'__w>, - _state: &Self::State, + unsafe fn set_archetype<'__w, '__s>( + _fetch: &mut ::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 ::Fetch<'__w>, - _state: &Self::State, + unsafe fn set_table<'__w, '__s>( + _fetch: &mut ::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);)* diff --git a/crates/bevy_ecs/src/name.rs b/crates/bevy_ecs/src/name.rs index 9c38b28481e7f..1cae293b401ef 100644 --- a/crates/bevy_ecs/src/name.rs +++ b/crates/bevy_ecs/src/name.rs @@ -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::(); 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(), "0v1"); + let d2 = query.get(&world, e2).unwrap(); // NameOrEntity Display for entities with a Name should be the Name assert_eq!(d2.to_string(), "MyName"); } diff --git a/crates/bevy_ecs/src/observer/mod.rs b/crates/bevy_ecs/src/observer/mod.rs index 4bbd82c85b824..c63c63e3a1cbd 100644 --- a/crates/bevy_ecs/src/observer/mod.rs +++ b/crates/bevy_ecs/src/observer/mod.rs @@ -889,7 +889,7 @@ mod tests { struct ChildOf(Entity); impl Traversal for &'_ ChildOf { - fn traverse(item: Self::Item<'_>, _: &D) -> Option { + fn traverse(item: Self::Item<'_, '_>, _: &D) -> Option { Some(item.0) } } diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index cd632f7b14f22..1c53594b80ac1 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -159,7 +159,7 @@ use variadics_please::all_tuples; /// } /// /// // `HealthQueryItem` is only available when accessing the query with mutable methods. -/// impl<'w> HealthQueryItem<'w> { +/// impl<'w, 's> HealthQueryItem<'w, 's> { /// fn damage(&mut self, value: f32) { /// self.health.0 -= value; /// } @@ -170,7 +170,7 @@ use variadics_please::all_tuples; /// } /// /// // `HealthQueryReadOnlyItem` is only available when accessing the query with immutable methods. -/// impl<'w> HealthQueryReadOnlyItem<'w> { +/// impl<'w, 's> HealthQueryReadOnlyItem<'w, 's> { /// fn total(&self) -> f32 { /// self.health.0 + self.buff.map_or(0.0, |Buff(buff)| *buff) /// } @@ -286,10 +286,12 @@ pub unsafe trait QueryData: WorldQuery { /// The item returned by this [`WorldQuery`] /// This will be the data retrieved by the query, /// and is visible to the end user when calling e.g. `Query::get`. - type Item<'a>; + type Item<'w, 's>; /// This function manually implements subtyping for the query items. - 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>; /// Fetch [`Self::Item`](`QueryData::Item`) for either the given `entity` in the current [`Table`], /// or for the given `entity` in the current [`Archetype`]. This must always be called after @@ -302,11 +304,11 @@ pub unsafe trait QueryData: 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. /// - There must not be simultaneous conflicting component access registered in `update_component_access`. - 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>; } /// A [`QueryData`] that is read only. @@ -317,40 +319,58 @@ pub unsafe trait QueryData: WorldQuery { pub unsafe trait ReadOnlyQueryData: QueryData {} /// The item type returned when a [`WorldQuery`] is iterated over -pub type QueryItem<'w, Q> = ::Item<'w>; +pub type QueryItem<'w, 's, Q> = ::Item<'w, 's>; /// The read-only variant of the item type returned when a [`QueryData`] is iterated over immutably -pub type ROQueryItem<'w, D> = QueryItem<'w, ::ReadOnly>; +pub type ROQueryItem<'w, 's, D> = QueryItem<'w, 's, ::ReadOnly>; + +/// A [`QueryData`] that does not borrow from its [`QueryState`](crate::query::QueryState). +/// +/// This is implemented by most `QueryData` types. +/// The main exceptions are [`FilteredEntityRef`], [`FilteredEntityMut`], [`EntityRefExcept`], and [`EntityMutExcept`], +/// which borrow an access list from their query state. +/// Consider using a full [`EntityRef`] or [`EntityMut`] if you would need those. +pub trait ReleaseStateQueryData: QueryData { + /// Releases the borrow from the query state by converting an item to have a `'static` state lifetime. + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static>; +} /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for Entity { - type Fetch<'w> = (); + type Fetch<'w, 's> = (); type State = (); - 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, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} @@ -374,18 +394,20 @@ unsafe impl QueryData for Entity { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'w> = Entity; + type Item<'w, 's> = Entity; - 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 } #[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> { entity } } @@ -393,23 +415,31 @@ unsafe impl QueryData for Entity { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for Entity {} +impl ReleaseStateQueryData for Entity { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } +} + /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for EntityLocation { - type Fetch<'w> = &'w Entities; + type Fetch<'w, 's> = &'w Entities; 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 } - 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> { world.entities() } @@ -418,16 +448,20 @@ unsafe impl WorldQuery for EntityLocation { 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, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} @@ -450,18 +484,20 @@ unsafe impl WorldQuery for EntityLocation { unsafe impl QueryData for EntityLocation { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'w> = EntityLocation; + type Item<'w, 's> = EntityLocation; - 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 } #[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: `fetch` must be called with an entity that exists in the world unsafe { fetch.get(entity).debug_checked_unwrap() } } @@ -470,40 +506,52 @@ unsafe impl QueryData for EntityLocation { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for EntityLocation {} +impl ReleaseStateQueryData for EntityLocation { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } +} + /// SAFETY: /// `fetch` accesses all components in a readonly way. /// This is sound because `update_component_access` and `update_archetype_component_access` set read access for all components and panic when appropriate. /// Filters are unchanged. unsafe impl<'a> WorldQuery for EntityRef<'a> { - type Fetch<'w> = UnsafeWorldCell<'w>; + type Fetch<'w, 's> = UnsafeWorldCell<'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 } - 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> { world } 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, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } fn update_component_access(_state: &Self::State, access: &mut FilteredAccess) { @@ -532,18 +580,20 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> { unsafe impl<'a> QueryData for EntityRef<'a> { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'w> = EntityRef<'w>; + type Item<'w, 's> = EntityRef<'w>; - 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 } #[inline(always)] - unsafe fn fetch<'w>( - world: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + world: &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: `fetch` must be called with an entity that exists in the world let cell = unsafe { world.get_entity(entity).debug_checked_unwrap() }; // SAFETY: Read-only access to every component has been registered. @@ -554,37 +604,49 @@ unsafe impl<'a> QueryData for EntityRef<'a> { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for EntityRef<'_> {} +impl ReleaseStateQueryData for EntityRef<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } +} + /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for EntityMut<'a> { - type Fetch<'w> = UnsafeWorldCell<'w>; + type Fetch<'w, 's> = UnsafeWorldCell<'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 } - 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> { world } 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, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } fn update_component_access(_state: &Self::State, access: &mut FilteredAccess) { @@ -613,18 +675,20 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> { unsafe impl<'a> QueryData for EntityMut<'a> { const IS_READ_ONLY: bool = false; type ReadOnly = EntityRef<'a>; - type Item<'w> = EntityMut<'w>; + type Item<'w, 's> = EntityMut<'w>; - 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 } #[inline(always)] - unsafe fn fetch<'w>( - world: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + world: &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: `fetch` must be called with an entity that exists in the world let cell = unsafe { world.get_entity(entity).debug_checked_unwrap() }; // SAFETY: mutable access to every component has been registered. @@ -632,32 +696,40 @@ unsafe impl<'a> QueryData for EntityMut<'a> { } } +impl ReleaseStateQueryData for EntityMut<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } +} + /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { - type Fetch<'w> = (UnsafeWorldCell<'w>, Access); + type Fetch<'w, 's> = (UnsafeWorldCell<'w>, Access); type State = FilteredAccess; - 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 } const IS_DENSE: bool = false; - 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> { let mut access = Access::default(); access.read_all_components(); (world, access) } #[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, _: &'w Archetype, _table: &Table, ) { @@ -665,7 +737,11 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { } #[inline] - unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, _: &'w Table) { + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, + _: &'w Table, + ) { fetch.1.clone_from(&state.access); } @@ -706,18 +782,20 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { unsafe impl<'a> QueryData for FilteredEntityRef<'a> { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'w> = FilteredEntityRef<'w>; + type Item<'w, 's> = FilteredEntityRef<'w>; - 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 } #[inline(always)] - unsafe fn fetch<'w>( - (world, access): &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + (world, access): &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: `fetch` must be called with an entity that exists in the world let cell = unsafe { world.get_entity(entity).debug_checked_unwrap() }; // SAFETY: mutable access to every component has been registered. @@ -730,30 +808,32 @@ unsafe impl ReadOnlyQueryData for FilteredEntityRef<'_> {} /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { - type Fetch<'w> = (UnsafeWorldCell<'w>, Access); + type Fetch<'w, 's> = (UnsafeWorldCell<'w>, Access); type State = FilteredAccess; - 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 } const IS_DENSE: bool = false; - 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> { let mut access = Access::default(); access.write_all_components(); (world, access) } #[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, _: &'w Archetype, _table: &Table, ) { @@ -761,7 +841,11 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { } #[inline] - unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, _: &'w Table) { + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, + _: &'w Table, + ) { fetch.1.clone_from(&state.access); } @@ -801,18 +885,20 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { unsafe impl<'a> QueryData for FilteredEntityMut<'a> { const IS_READ_ONLY: bool = false; type ReadOnly = FilteredEntityRef<'a>; - type Item<'w> = FilteredEntityMut<'w>; + type Item<'w, 's> = FilteredEntityMut<'w>; - 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 } #[inline(always)] - unsafe fn fetch<'w>( - (world, access): &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + (world, access): &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: `fetch` must be called with an entity that exists in the world let cell = unsafe { world.get_entity(entity).debug_checked_unwrap() }; // SAFETY: mutable access to every component has been registered. @@ -827,33 +913,35 @@ unsafe impl<'a, B> WorldQuery for EntityRefExcept<'a, B> where B: Bundle, { - type Fetch<'w> = UnsafeWorldCell<'w>; + type Fetch<'w, 's> = UnsafeWorldCell<'w>; type State = SmallVec<[ComponentId; 4]>; - 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>, - _: &Self::State, + _: &'s Self::State, _: Tick, _: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { world } const IS_DENSE: bool = true; - unsafe fn set_archetype<'w>( - _: &mut Self::Fetch<'w>, - _: &Self::State, + unsafe fn set_archetype<'w, 's>( + _: &mut Self::Fetch<'w, 's>, + _: &'s Self::State, _: &'w Archetype, _: &'w Table, ) { } - unsafe fn set_table<'w>(_: &mut Self::Fetch<'w>, _: &Self::State, _: &'w Table) {} + unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w, 's>, _: &'s Self::State, _: &'w Table) {} fn update_component_access( state: &Self::State, @@ -900,17 +988,19 @@ where { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'w> = EntityRefExcept<'w, B>; + type Item<'w, 's> = EntityRefExcept<'w, B>; - 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 } - unsafe fn fetch<'w>( - world: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + world: &mut Self::Fetch<'w, 's>, entity: Entity, _: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { let cell = world.get_entity(entity).unwrap(); EntityRefExcept::new(cell) } @@ -927,33 +1017,35 @@ unsafe impl<'a, B> WorldQuery for EntityMutExcept<'a, B> where B: Bundle, { - type Fetch<'w> = UnsafeWorldCell<'w>; + type Fetch<'w, 's> = UnsafeWorldCell<'w>; type State = SmallVec<[ComponentId; 4]>; - 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>, - _: &Self::State, + _: &'s Self::State, _: Tick, _: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { world } const IS_DENSE: bool = true; - unsafe fn set_archetype<'w>( - _: &mut Self::Fetch<'w>, - _: &Self::State, + unsafe fn set_archetype<'w, 's>( + _: &mut Self::Fetch<'w, 's>, + _: &'s Self::State, _: &'w Archetype, _: &'w Table, ) { } - unsafe fn set_table<'w>(_: &mut Self::Fetch<'w>, _: &Self::State, _: &'w Table) {} + unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w, 's>, _: &'s Self::State, _: &'w Table) {} fn update_component_access( state: &Self::State, @@ -1001,17 +1093,19 @@ where { const IS_READ_ONLY: bool = false; type ReadOnly = EntityRefExcept<'a, B>; - type Item<'w> = EntityMutExcept<'w, B>; + type Item<'w, 's> = EntityMutExcept<'w, B>; - 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 } - unsafe fn fetch<'w>( - world: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + world: &mut Self::Fetch<'w, 's>, entity: Entity, _: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { let cell = world.get_entity(entity).unwrap(); EntityMutExcept::new(cell) } @@ -1021,19 +1115,21 @@ where /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for &Archetype { - type Fetch<'w> = (&'w Entities, &'w Archetypes); + type Fetch<'w, 's> = (&'w Entities, &'w Archetypes); 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 } - 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> { (world.entities(), world.archetypes()) } @@ -1042,16 +1138,20 @@ unsafe impl WorldQuery for &Archetype { 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, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} @@ -1074,18 +1174,20 @@ unsafe impl WorldQuery for &Archetype { unsafe impl QueryData for &Archetype { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'w> = &'w Archetype; + type Item<'w, 's> = &'w Archetype; - 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 } #[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> { let (entities, archetypes) = *fetch; // SAFETY: `fetch` must be called with an entity that exists in the world let location = unsafe { entities.get(entity).debug_checked_unwrap() }; @@ -1097,6 +1199,12 @@ unsafe impl QueryData for &Archetype { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for &Archetype {} +impl ReleaseStateQueryData for &Archetype { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } +} + /// The [`WorldQuery::Fetch`] type for `& T`. pub struct ReadFetch<'w, T: Component> { components: StorageSwitch< @@ -1121,15 +1229,17 @@ impl Copy for ReadFetch<'_, 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 WorldQuery for &T { - type Fetch<'w> = ReadFetch<'w, T>; + type Fetch<'w, 's> = ReadFetch<'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>, &component_id: &ComponentId, _last_run: Tick, @@ -1219,18 +1329,20 @@ unsafe impl WorldQuery for &T { unsafe impl QueryData for &T { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'w> = &'w T; + type Item<'w, 's> = &'w T; - fn shrink<'wlong: 'wshort, 'wshort>(item: &'wlong T) -> &'wshort T { + 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> { fetch.components.extract( |table| { // SAFETY: set_table was previously called @@ -1256,6 +1368,12 @@ unsafe impl QueryData for &T { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for &T {} +impl ReleaseStateQueryData for &T { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } +} + #[doc(hidden)] pub struct RefFetch<'w, T: Component> { components: StorageSwitch< @@ -1288,15 +1406,17 @@ impl Copy for RefFetch<'_, 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<'__w, T: Component> WorldQuery for Ref<'__w, T> { - type Fetch<'w> = RefFetch<'w, T>; + type Fetch<'w, 's> = RefFetch<'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>, &component_id: &ComponentId, last_run: Tick, @@ -1391,18 +1511,20 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> { unsafe impl<'__w, T: Component> QueryData for Ref<'__w, T> { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'w> = Ref<'w, T>; + type Item<'w, 's> = Ref<'w, T>; - fn shrink<'wlong: 'wshort, 'wshort>(item: Ref<'wlong, T>) -> Ref<'wshort, T> { + 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> { fetch.components.extract( |table| { // SAFETY: set_table was previously called @@ -1451,6 +1573,12 @@ unsafe impl<'__w, T: Component> QueryData for Ref<'__w, T> { /// SAFETY: access is read only unsafe impl<'__w, T: Component> ReadOnlyQueryData for Ref<'__w, T> {} +impl ReleaseStateQueryData for Ref<'_, T> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } +} + /// The [`WorldQuery::Fetch`] type for `&mut T`. pub struct WriteFetch<'w, T: Component> { components: StorageSwitch< @@ -1483,15 +1611,17 @@ impl Copy for WriteFetch<'_, 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<'__w, T: Component> WorldQuery for &'__w mut T { - type Fetch<'w> = WriteFetch<'w, T>; + type Fetch<'w, 's> = WriteFetch<'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>, &component_id: &ComponentId, last_run: Tick, @@ -1586,18 +1716,20 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T { unsafe impl<'__w, T: Component> QueryData for &'__w mut T { const IS_READ_ONLY: bool = false; type ReadOnly = &'__w T; - type Item<'w> = Mut<'w, T>; + type Item<'w, 's> = Mut<'w, T>; - fn shrink<'wlong: 'wshort, 'wshort>(item: Mut<'wlong, T>) -> Mut<'wshort, T> { + 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> { fetch.components.extract( |table| { // SAFETY: set_table was previously called @@ -1643,6 +1775,12 @@ unsafe impl<'__w, T: Component> QueryData for &'__w mut T } } +impl> ReleaseStateQueryData for &mut T { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } +} + /// When `Mut` is used in a query, it will be converted to `Ref` when transformed into its read-only form, providing access to change detection methods. /// /// By contrast `&mut T` will result in a `Mut` item in mutable form to record mutations, but result in a bare `&T` in read-only form. @@ -1653,16 +1791,18 @@ unsafe impl<'__w, T: Component> QueryData for &'__w mut 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<'__w, T: Component> WorldQuery for Mut<'__w, T> { - type Fetch<'w> = WriteFetch<'w, T>; + type Fetch<'w, 's> = WriteFetch<'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] // Forwarded to `&mut T` - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, state: &ComponentId, last_run: Tick, @@ -1729,33 +1869,41 @@ unsafe impl<'__w, T: Component> WorldQuery for Mut<'__w, T> { unsafe impl<'__w, T: Component> QueryData for Mut<'__w, T> { const IS_READ_ONLY: bool = false; type ReadOnly = Ref<'__w, T>; - type Item<'w> = Mut<'w, T>; + type Item<'w, 's> = Mut<'w, T>; // Forwarded to `&mut T` - fn shrink<'wlong: 'wshort, 'wshort>(item: Mut<'wlong, T>) -> Mut<'wshort, T> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { <&mut T as QueryData>::shrink(item) } #[inline(always)] // Forwarded to `&mut T` - unsafe fn fetch<'w>( + unsafe fn fetch<'w, 's>( // Rust complains about lifetime bounds not matching the trait if I directly use `WriteFetch<'w, T>` right here. // But it complains nowhere else in the entire trait implementation. - fetch: &mut Self::Fetch<'w>, + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Mut<'w, T> { + ) -> Self::Item<'w, 's> { <&mut T as QueryData>::fetch(fetch, entity, table_row) } } +impl> ReleaseStateQueryData for Mut<'_, T> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } +} + #[doc(hidden)] -pub struct OptionFetch<'w, T: WorldQuery> { - fetch: T::Fetch<'w>, +pub struct OptionFetch<'w, 's, T: WorldQuery> { + fetch: T::Fetch<'w, 's>, matches: bool, } -impl Clone for OptionFetch<'_, T> { +impl Clone for OptionFetch<'_, '_, T> { fn clone(&self) -> Self { Self { fetch: self.fetch.clone(), @@ -1769,10 +1917,12 @@ impl Clone for OptionFetch<'_, T> { /// This is sound because `update_component_access` and `update_archetype_component_access` add the same accesses as `T`. /// Filters are unchanged. unsafe impl WorldQuery for Option { - type Fetch<'w> = OptionFetch<'w, T>; + type Fetch<'w, 's> = OptionFetch<'w, 's, T>; type State = T::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> { OptionFetch { fetch: T::shrink_fetch(fetch.fetch), matches: fetch.matches, @@ -1780,12 +1930,12 @@ unsafe impl WorldQuery for Option { } #[inline] - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - state: &T::State, + state: &'s T::State, last_run: Tick, this_run: Tick, - ) -> OptionFetch<'w, T> { + ) -> OptionFetch<'w, 's, T> { OptionFetch { // SAFETY: The invariants are upheld by the caller. fetch: unsafe { T::init_fetch(world, state, last_run, this_run) }, @@ -1796,9 +1946,9 @@ unsafe impl WorldQuery for Option { const IS_DENSE: bool = T::IS_DENSE; #[inline] - unsafe fn set_archetype<'w>( - fetch: &mut OptionFetch<'w, T>, - state: &T::State, + unsafe fn set_archetype<'w, 's>( + fetch: &mut OptionFetch<'w, 's, T>, + state: &'s T::State, archetype: &'w Archetype, table: &'w Table, ) { @@ -1812,7 +1962,11 @@ unsafe impl WorldQuery for Option { } #[inline] - unsafe fn set_table<'w>(fetch: &mut OptionFetch<'w, T>, state: &T::State, table: &'w Table) { + unsafe fn set_table<'w, 's>( + fetch: &mut OptionFetch<'w, 's, T>, + state: &'s T::State, + table: &'w Table, + ) { fetch.matches = T::matches_component_set(state, &|id| table.has_column(id)); if fetch.matches { // SAFETY: The invariants are upheld by the caller. @@ -1857,18 +2011,20 @@ unsafe impl WorldQuery for Option { unsafe impl QueryData for Option { const IS_READ_ONLY: bool = T::IS_READ_ONLY; type ReadOnly = Option; - type Item<'w> = Option>; + type Item<'w, 's> = Option>; - 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.map(T::shrink) } #[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> { fetch .matches // SAFETY: The invariants are upheld by the caller. @@ -1879,6 +2035,12 @@ unsafe impl QueryData for Option { /// SAFETY: [`OptionFetch`] is read only because `T` is read only unsafe impl ReadOnlyQueryData for Option {} +impl ReleaseStateQueryData for Option { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item.map(T::release_state) + } +} + /// Returns a bool that describes if an entity has the component `T`. /// /// This can be used in a [`Query`](crate::system::Query) if you want to know whether or not entities @@ -1954,20 +2116,22 @@ impl core::fmt::Debug for Has { /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for Has { - type Fetch<'w> = bool; + type Fetch<'w, 's> = bool; 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>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { false } @@ -1979,9 +2143,9 @@ unsafe impl WorldQuery for Has { }; #[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, ) { @@ -1989,7 +2153,11 @@ unsafe impl WorldQuery for Has { } #[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, + ) { *fetch = table.has_column(*state); } @@ -2021,18 +2189,20 @@ unsafe impl WorldQuery for Has { unsafe impl QueryData for Has { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'w> = bool; + type Item<'w, 's> = bool; - 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 } #[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> { *fetch } } @@ -2040,6 +2210,12 @@ unsafe impl QueryData for Has { /// SAFETY: [`Has`] is read only unsafe impl ReadOnlyQueryData for Has {} +impl ReleaseStateQueryData for Has { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } +} + /// The `AnyOf` query parameter fetches entities with any of the component types included in T. /// /// `Query>` is equivalent to `Query<(Option<&A>, Option<&B>, Option<&mut C>), Or<(With, With, With)>>`. @@ -2048,7 +2224,7 @@ unsafe impl ReadOnlyQueryData for Has {} pub struct AnyOf(PhantomData); macro_rules! impl_tuple_query_data { - ($(#[$meta:meta])* $(($name: ident, $state: ident)),*) => { + ($(#[$meta:meta])* $(($name: ident, $item: ident)),*) => { #[expect( clippy::allow_attributes, reason = "This is a tuple-related macro; as such the lints below may not always apply." @@ -2070,9 +2246,9 @@ macro_rules! impl_tuple_query_data { unsafe impl<$($name: QueryData),*> QueryData for ($($name,)*) { const IS_READ_ONLY: bool = true $(&& $name::IS_READ_ONLY)*; type ReadOnly = ($($name::ReadOnly,)*); - type Item<'w> = ($($name::Item<'w>,)*); + type Item<'w, 's> = ($($name::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> { let ($($name,)*) = item; ($( $name::shrink($name), @@ -2080,26 +2256,38 @@ macro_rules! impl_tuple_query_data { } #[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> { let ($($name,)*) = fetch; // SAFETY: The invariants are upheld by the caller. ($(unsafe { $name::fetch($name, entity, table_row) },)*) } } - $(#[$meta])* /// SAFETY: each item in the tuple is read only unsafe impl<$($name: ReadOnlyQueryData),*> ReadOnlyQueryData for ($($name,)*) {} + #[expect( + clippy::allow_attributes, + reason = "This is a tuple-related macro; as such the lints below may not always apply." + )] + #[allow( + clippy::unused_unit, + reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case." + )] + impl<$($name: ReleaseStateQueryData),*> ReleaseStateQueryData for ($($name,)*) { + fn release_state<'w>(($($item,)*): Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + ($($name::release_state($item),)*) + } + } }; } macro_rules! impl_anytuple_fetch { - ($(#[$meta:meta])* $(($name: ident, $state: ident)),*) => { + ($(#[$meta:meta])* $(($name: ident, $state: ident, $item: ident)),*) => { $(#[$meta])* #[expect( clippy::allow_attributes, @@ -2123,10 +2311,10 @@ macro_rules! impl_anytuple_fetch { /// `update_component_access` replaces 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<$($name: WorldQuery),*> WorldQuery for AnyOf<($($name,)*)> { - type Fetch<'w> = ($(($name::Fetch<'w>, bool),)*); + type Fetch<'w, 's> = ($(($name::Fetch<'w, 's>, bool),)*); 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.0), $name.1), @@ -2134,7 +2322,7 @@ macro_rules! impl_anytuple_fetch { } #[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) }, false),)*) @@ -2143,9 +2331,9 @@ macro_rules! impl_anytuple_fetch { 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 ) { @@ -2161,7 +2349,7 @@ macro_rules! impl_anytuple_fetch { } #[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; $( @@ -2233,9 +2421,9 @@ macro_rules! impl_anytuple_fetch { unsafe impl<$($name: QueryData),*> QueryData for AnyOf<($($name,)*)> { const IS_READ_ONLY: bool = true $(&& $name::IS_READ_ONLY)*; type ReadOnly = AnyOf<($($name::ReadOnly,)*)>; - type Item<'w> = ($(Option<$name::Item<'w>>,)*); + type Item<'w, 's> = ($(Option<$name::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> { let ($($name,)*) = item; ($( $name.map($name::shrink), @@ -2243,11 +2431,11 @@ macro_rules! impl_anytuple_fetch { } #[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> { let ($($name,)*) = _fetch; ($( // SAFETY: The invariants are required to be upheld by the caller. @@ -2259,6 +2447,20 @@ macro_rules! impl_anytuple_fetch { $(#[$meta])* /// SAFETY: each item in the tuple is read only unsafe impl<$($name: ReadOnlyQueryData),*> ReadOnlyQueryData for AnyOf<($($name,)*)> {} + + #[expect( + clippy::allow_attributes, + reason = "This is a tuple-related macro; as such the lints below may not always apply." + )] + #[allow( + clippy::unused_unit, + reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case." + )] + impl<$($name: ReleaseStateQueryData),*> ReleaseStateQueryData for AnyOf<($($name,)*)> { + fn release_state<'w>(($($item,)*): Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + ($($item.map(|$item| $name::release_state($item)),)*) + } + } }; } @@ -2268,7 +2470,7 @@ all_tuples!( 0, 15, F, - S + i ); all_tuples!( #[doc(fake_variadic)] @@ -2276,7 +2478,8 @@ all_tuples!( 0, 15, F, - S + S, + i ); /// [`WorldQuery`] used to nullify queries by turning `Query` into `Query>` @@ -2288,10 +2491,13 @@ pub(crate) struct NopWorldQuery(PhantomData); /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for NopWorldQuery { - type Fetch<'w> = (); + type Fetch<'w, 's> = (); type State = D::State; - fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: ()) {} + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + _fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { + } #[inline(always)] unsafe fn init_fetch( @@ -2338,54 +2544,67 @@ unsafe impl WorldQuery for NopWorldQuery { unsafe impl QueryData for NopWorldQuery { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'w> = (); + type Item<'w, 's> = (); - fn shrink<'wlong: 'wshort, '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> { } } /// SAFETY: `NopFetch` never accesses any data unsafe impl ReadOnlyQueryData for NopWorldQuery {} +impl ReleaseStateQueryData for NopWorldQuery { + fn release_state<'w>(_item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {} +} + /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for PhantomData { - type Fetch<'a> = (); + type Fetch<'w, 's> = (); 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> { } - 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> { } // `PhantomData` does not match any components, so all components it matches // are stored in a Table (vacuous truth). const IS_DENSE: bool = true; - 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, ) { } - 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, + ) { } fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} @@ -2408,21 +2627,28 @@ unsafe impl WorldQuery for PhantomData { unsafe impl QueryData for PhantomData { const IS_READ_ONLY: bool = true; type ReadOnly = Self; - type Item<'a> = (); + 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> { + } - 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: `PhantomData` never accesses any world data. unsafe impl ReadOnlyQueryData for PhantomData {} +impl ReleaseStateQueryData for PhantomData { + fn release_state<'w>(_item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {} +} + /// A compile-time checked union of two different types that differs based on the /// [`StorageType`] of a given component. pub(super) union StorageSwitch { @@ -2538,6 +2764,123 @@ mod tests { assert_is_system(ignored_system); } + #[test] + fn derive_release_state() { + struct NonReleaseQueryData; + + /// SAFETY: + /// `update_component_access` and `update_archetype_component_access` do nothing. + /// This is sound because `fetch` does not access components. + unsafe impl WorldQuery for NonReleaseQueryData { + type Fetch<'w, 's> = (); + type State = (); + + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + _: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { + } + + unsafe fn init_fetch<'w, 's>( + _world: UnsafeWorldCell<'w>, + _state: &'s Self::State, + _last_run: Tick, + _this_run: Tick, + ) -> Self::Fetch<'w, 's> { + } + + const IS_DENSE: bool = true; + + #[inline] + 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, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { + } + + fn update_component_access( + _state: &Self::State, + _access: &mut FilteredAccess, + ) { + } + + fn init_state(_world: &mut World) {} + + fn get_state(_components: &Components) -> Option<()> { + Some(()) + } + + fn matches_component_set( + _state: &Self::State, + _set_contains_id: &impl Fn(ComponentId) -> bool, + ) -> bool { + true + } + } + + /// SAFETY: `Self` is the same as `Self::ReadOnly` + unsafe impl QueryData for NonReleaseQueryData { + type ReadOnly = Self; + const IS_READ_ONLY: bool = true; + + type Item<'w, 's> = (); + + fn shrink<'wlong: 'wshort, 'wshort, 's>( + _item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { + } + + #[inline(always)] + unsafe fn fetch<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _entity: Entity, + _table_row: TableRow, + ) -> Self::Item<'w, 's> { + } + } + + /// SAFETY: access is read only + unsafe impl ReadOnlyQueryData for NonReleaseQueryData {} + + #[derive(QueryData)] + pub struct DerivedNonReleaseRead { + non_release: NonReleaseQueryData, + a: &'static A, + } + + #[derive(QueryData)] + #[query_data(mutable)] + pub struct DerivedNonReleaseMutable { + non_release: NonReleaseQueryData, + a: &'static mut A, + } + + #[derive(QueryData)] + pub struct DerivedReleaseRead { + a: &'static A, + } + + #[derive(QueryData)] + #[query_data(mutable)] + pub struct DerivedReleaseMutable { + a: &'static mut A, + } + + fn assert_is_release_state() {} + + assert_is_release_state::(); + assert_is_release_state::(); + } + // Ensures that each field of a `WorldQuery` struct's read-only variant // has the same visibility as its corresponding mutable field. #[test] diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index e4e1f0fd668d3..1652b2a3eff89 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -101,7 +101,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; @@ -142,10 +142,13 @@ pub struct With(PhantomData); /// `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 WorldQuery for With { - 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( @@ -202,7 +205,7 @@ unsafe impl QueryFilter for With { #[inline(always)] unsafe fn filter_fetch( - _fetch: &mut Self::Fetch<'_>, + _fetch: &mut Self::Fetch<'_, '_>, _entity: Entity, _table_row: TableRow, ) -> bool { @@ -242,10 +245,13 @@ pub struct Without(PhantomData); /// `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 WorldQuery for Without { - 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( @@ -302,7 +308,7 @@ unsafe impl QueryFilter for Without { #[inline(always)] unsafe fn filter_fetch( - _fetch: &mut Self::Fetch<'_>, + _fetch: &mut Self::Fetch<'_, '_>, _entity: Entity, _table_row: TableRow, ) -> bool { @@ -343,12 +349,12 @@ unsafe impl QueryFilter for Without { pub struct Or(PhantomData); #[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 Clone for OrFetch<'_, T> { +impl Clone for OrFetch<'_, '_, T> { fn clone(&self) -> Self { Self { fetch: self.fetch.clone(), @@ -382,10 +388,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 { @@ -398,7 +404,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. @@ -408,7 +414,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; $( @@ -421,9 +427,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 ) { @@ -493,7 +499,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 { @@ -526,7 +532,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 { @@ -651,21 +657,23 @@ impl 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 WorldQuery for Added { - 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, || { @@ -689,9 +697,9 @@ unsafe impl WorldQuery for Added { }; #[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, ) { @@ -704,9 +712,9 @@ unsafe impl WorldQuery for Added { } #[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( @@ -748,7 +756,7 @@ unsafe impl QueryFilter for Added { 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 { @@ -878,21 +886,23 @@ impl 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 WorldQuery for Changed { - 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, || { @@ -916,9 +926,9 @@ unsafe impl WorldQuery for Changed { }; #[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, ) { @@ -931,9 +941,9 @@ unsafe impl WorldQuery for Changed { } #[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( @@ -976,7 +986,7 @@ unsafe impl QueryFilter for Changed { #[inline(always)] unsafe fn filter_fetch( - fetch: &mut Self::Fetch<'_>, + fetch: &mut Self::Fetch<'_, '_>, entity: Entity, table_row: TableRow, ) -> bool { diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 58034618cb887..b76159e2f16e6 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -139,7 +139,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { range: Option>, ) -> 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. @@ -202,7 +202,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { rows: Range, ) -> B where - Func: FnMut(B, D::Item<'w>) -> B, + Func: FnMut(B, D::Item<'w, 's>) -> B, { if table.is_empty() { return accum; @@ -257,7 +257,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { indices: Range, ) -> B where - Func: FnMut(B, D::Item<'w>) -> B, + Func: FnMut(B, D::Item<'w, 's>) -> B, { if archetype.is_empty() { return accum; @@ -326,7 +326,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { rows: Range, ) -> B where - Func: FnMut(B, D::Item<'w>) -> B, + Func: FnMut(B, D::Item<'w, 's>) -> B, { if archetype.is_empty() { return accum; @@ -497,7 +497,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where - for<'lw> L::Item<'lw>: Ord, + for<'lw, 'ls> L::Item<'lw, 'ls>: Ord, { self.sort_impl::(|keyed_query| keyed_query.sort()) } @@ -554,7 +554,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where - for<'lw> L::Item<'lw>: Ord, + for<'lw, 'ls> L::Item<'lw, 'ls>: Ord, { self.sort_impl::(|keyed_query| keyed_query.sort_unstable()) } @@ -610,7 +610,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// ``` pub fn sort_by( self, - mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, + mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering, ) -> QuerySortedIter< 'w, 's, @@ -642,7 +642,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( self, - mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, + mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering, ) -> QuerySortedIter< 'w, 's, @@ -734,7 +734,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// ``` pub fn sort_by_key( self, - mut f: impl FnMut(&L::Item<'_>) -> K, + mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedIter< 'w, 's, @@ -767,7 +767,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( self, - mut f: impl FnMut(&L::Item<'_>) -> K, + mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedIter< 'w, 's, @@ -802,7 +802,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( self, - mut f: impl FnMut(&L::Item<'_>) -> K, + mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedIter< 'w, 's, @@ -832,7 +832,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( self, - f: impl FnOnce(&mut Vec<(L::Item<'_>, NeutralOrd)>), + f: impl FnOnce(&mut Vec<(L::Item<'_, '_>, NeutralOrd)>), ) -> QuerySortedIter< 'w, 's, @@ -861,7 +861,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::>() + .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. @@ -878,7 +882,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 { @@ -980,7 +984,7 @@ where entities: &'w Entities, tables: &'w Tables, archetypes: &'w Archetypes, - fetch: D::Fetch<'w>, + fetch: D::Fetch<'w, 's>, query_state: &'s QueryState, } @@ -1015,7 +1019,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`] @@ -1053,7 +1057,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Iterator where I: Iterator, { - type Item = D::Item<'w>; + type Item = D::Item<'w, 's>; #[inline(always)] fn next(&mut self) -> Option { @@ -1123,8 +1127,8 @@ pub struct QueryManyIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator, - filter: F::Fetch<'w>, + fetch: D::Fetch<'w, 's>, + filter: F::Fetch<'w, 's>, query_state: &'s QueryState, } @@ -1171,10 +1175,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> 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, - ) -> Option> { + ) -> Option> { for entity_borrow in entity_iter { let entity = entity_borrow.entity(); let Some(location) = entities.get(entity) else { @@ -1216,7 +1220,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// Get next result from the query #[inline(always)] - pub fn fetch_next(&mut self) -> Option> { + pub fn fetch_next(&mut self) -> Option> { // SAFETY: // All arguments stem from self. // We are limiting the returned reference to self, @@ -1340,7 +1344,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where - for<'lw> L::Item<'lw>: Ord, + for<'lw, 'ls> L::Item<'lw, 'ls>: Ord, { self.sort_impl::(|keyed_query| keyed_query.sort()) } @@ -1398,7 +1402,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where - for<'lw> L::Item<'lw>: Ord, + for<'lw, 'ls> L::Item<'lw, 'ls>: Ord, { self.sort_impl::(|keyed_query| keyed_query.sort_unstable()) } @@ -1455,7 +1459,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// ``` pub fn sort_by( self, - mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, + mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering, ) -> QuerySortedManyIter< 'w, 's, @@ -1486,7 +1490,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// called on [`QueryManyIter`] before. pub fn sort_unstable_by( self, - mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, + mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering, ) -> QuerySortedManyIter< 'w, 's, @@ -1580,7 +1584,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// ``` pub fn sort_by_key( self, - mut f: impl FnMut(&L::Item<'_>) -> K, + mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedManyIter< 'w, 's, @@ -1612,7 +1616,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// called on [`QueryManyIter`] before. pub fn sort_unstable_by_key( self, - mut f: impl FnMut(&L::Item<'_>) -> K, + mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedManyIter< 'w, 's, @@ -1646,7 +1650,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// called on [`QueryManyIter`] before. pub fn sort_by_cached_key( self, - mut f: impl FnMut(&L::Item<'_>) -> K, + mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedManyIter< 'w, 's, @@ -1675,7 +1679,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// called on [`QueryManyIter`] before. fn sort_impl( self, - f: impl FnOnce(&mut Vec<(L::Item<'_>, NeutralOrd)>), + f: impl FnOnce(&mut Vec<(L::Item<'_, '_>, NeutralOrd)>), ) -> QuerySortedManyIter< 'w, 's, @@ -1725,7 +1729,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator Option> { + pub fn fetch_next_back(&mut self) -> Option> { // SAFETY: // All arguments stem from self. // We are limiting the returned reference to self, @@ -1749,7 +1753,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator> 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 { @@ -1860,7 +1864,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 { @@ -1914,7 +1918,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, } @@ -1953,7 +1957,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// 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`] @@ -1987,7 +1991,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// Get next result from the query #[inline(always)] - pub fn fetch_next(&mut self) -> Option> { + pub fn fetch_next(&mut self) -> Option> { let entity = self.entity_iter.next()?; // SAFETY: @@ -2006,7 +2010,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator { /// Get next result from the query #[inline(always)] - pub fn fetch_next_back(&mut self) -> Option> { + pub fn fetch_next_back(&mut self) -> Option> { let entity = self.entity_iter.next_back()?; // SAFETY: @@ -2023,7 +2027,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator> 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 { @@ -2184,7 +2188,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 // @@ -2210,9 +2214,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::>(); + let ptr = values.as_mut_ptr().cast::>(); for (offset, cursor) in self.cursors.iter_mut().enumerate() { ptr.add(offset).write(cursor.peek_last().unwrap()); } @@ -2222,7 +2226,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. @@ -2239,7 +2243,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 { @@ -2308,8 +2312,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: usize, // either table row or archetype index, depending on whether both `D`'s and `F`'s fetches are dense @@ -2389,7 +2393,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> { + unsafe fn peek_last(&mut self) -> Option> { if self.current_row > 0 { let index = self.current_row - 1; if self.is_dense { @@ -2454,7 +2458,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { tables: &'w Tables, archetypes: &'w Archetypes, query_state: &'s QueryState, - ) -> Option> { + ) -> Option> { if self.is_dense { loop { // we are on the beginning of the query, or finished processing a table, so skip to the next diff --git a/crates/bevy_ecs/src/query/mod.rs b/crates/bevy_ecs/src/query/mod.rs index f9dbcc1df48f2..645bfdaf7a722 100644 --- a/crates/bevy_ecs/src/query/mod.rs +++ b/crates/bevy_ecs/src/query/mod.rs @@ -819,34 +819,37 @@ mod tests { /// `update_component_access` adds resource read access for `R`. /// `update_archetype_component_access` does nothing, as this accesses no components. 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> { } } diff --git a/crates/bevy_ecs/src/query/par_iter.rs b/crates/bevy_ecs/src/query/par_iter.rs index 0805774f8cdde..c16230dabbb90 100644 --- a/crates/bevy_ecs/src/query/par_iter.rs +++ b/crates/bevy_ecs/src/query/par_iter.rs @@ -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) + Send + Sync + Clone>(self, func: FN) { + pub fn for_each) + 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(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| { @@ -189,7 +189,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityBorrow + Sync> /// /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool #[inline] - pub fn for_each) + Send + Sync + Clone>(self, func: FN) { + pub fn for_each) + Send + Sync + Clone>(self, func: FN) { self.for_each_init(|| {}, |_, item| func(item)); } @@ -246,7 +246,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityBorrow + Sync> #[inline] pub fn for_each_init(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| { @@ -349,7 +349,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: TrustedEntityBorrow + Sync> /// /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool #[inline] - pub fn for_each) + Send + Sync + Clone>(self, func: FN) { + pub fn for_each) + Send + Sync + Clone>(self, func: FN) { self.for_each_init(|| {}, |_, item| func(item)); } @@ -406,7 +406,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: TrustedEntityBorrow + Sync> #[inline] pub fn for_each_init(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| { diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 9f6b55fa891b2..45b8537800d4f 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -946,13 +946,17 @@ impl QueryState { /// /// 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, QueryEntityError<'w>> { + ) -> Result, QueryEntityError<'w>> { self.query(world).get_inner(entity) } @@ -993,7 +997,7 @@ impl QueryState { &mut self, world: &'w World, entities: [Entity; N], - ) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError<'w>> { + ) -> Result<[ROQueryItem<'w, '_, D>; N], QueryEntityError<'w>> { self.query(world).get_many_inner(entities) } @@ -1005,7 +1009,7 @@ impl QueryState { &mut self, world: &'w mut World, entity: Entity, - ) -> Result, QueryEntityError<'w>> { + ) -> Result, QueryEntityError<'w>> { self.query_mut(world).get_inner(entity) } @@ -1052,7 +1056,7 @@ impl QueryState { &mut self, world: &'w mut World, entities: [Entity; N], - ) -> Result<[D::Item<'w>; N], QueryEntityError<'w>> { + ) -> Result<[D::Item<'w, '_>; N], QueryEntityError<'w>> { self.query_mut(world).get_many_inner(entities) } @@ -1074,7 +1078,7 @@ impl QueryState { &self, world: &'w World, entity: Entity, - ) -> Result, QueryEntityError<'w>> { + ) -> Result, QueryEntityError<'w>> { self.query_manual(world).get_inner(entity) } @@ -1091,13 +1095,16 @@ impl QueryState { &mut self, world: UnsafeWorldCell<'w>, entity: Entity, - ) -> Result, QueryEntityError<'w>> { + ) -> Result, QueryEntityError<'w>> { 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() @@ -1186,6 +1193,9 @@ impl QueryState { /// 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. @@ -1405,8 +1415,8 @@ impl QueryState { /// /// [`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: usize, @@ -1414,7 +1424,7 @@ impl QueryState { 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: @@ -1519,8 +1529,8 @@ impl QueryState { /// /// [`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: &UniqueEntitySlice, @@ -1529,7 +1539,7 @@ impl QueryState { 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: TrustedEntityBorrow + Sync, { @@ -1582,8 +1592,8 @@ impl QueryState { /// /// [`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], @@ -1592,7 +1602,7 @@ impl QueryState { 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: EntityBorrow + Sync, { @@ -1704,7 +1714,10 @@ impl QueryState { /// /// Simply unwrapping the [`Result`] also works, but should generally be reserved for tests. #[inline] - pub fn single<'w>(&mut self, world: &'w World) -> Result, QuerySingleError> { + pub fn single<'w>( + &mut self, + world: &'w World, + ) -> Result, QuerySingleError> { self.query(world).single_inner() } @@ -1714,7 +1727,7 @@ impl QueryState { pub fn get_single<'w>( &mut self, world: &'w World, - ) -> Result, QuerySingleError> { + ) -> Result, QuerySingleError> { self.single(world) } @@ -1731,7 +1744,7 @@ impl QueryState { pub fn single_mut<'w>( &mut self, world: &'w mut World, - ) -> Result, QuerySingleError> { + ) -> Result, QuerySingleError> { self.query_mut(world).single_inner() } @@ -1740,7 +1753,7 @@ impl QueryState { pub fn get_single_mut<'w>( &mut self, world: &'w mut World, - ) -> Result, QuerySingleError> { + ) -> Result, QuerySingleError> { self.single_mut(world) } @@ -1757,7 +1770,7 @@ impl QueryState { pub unsafe fn single_unchecked<'w>( &mut self, world: UnsafeWorldCell<'w>, - ) -> Result, QuerySingleError> { + ) -> Result, QuerySingleError> { self.query_unchecked(world).single_inner() } @@ -1779,7 +1792,7 @@ impl QueryState { world: UnsafeWorldCell<'w>, last_run: Tick, this_run: Tick, - ) -> Result, QuerySingleError> { + ) -> Result, QuerySingleError> { // SAFETY: // - The caller ensured we have the correct access to the world. // - The caller ensured that the world matches. diff --git a/crates/bevy_ecs/src/query/world_query.rs b/crates/bevy_ecs/src/query/world_query.rs index da147770e0fcf..3dfe6b958ad1f 100644 --- a/crates/bevy_ecs/src/query/world_query.rs +++ b/crates/bevy_ecs/src/query/world_query.rs @@ -40,7 +40,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 @@ -48,7 +48,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). @@ -60,12 +62,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. @@ -85,9 +87,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, ); @@ -99,7 +101,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, + ); /// Sets available accesses for implementors with dynamic access such as [`FilteredEntityRef`](crate::world::FilteredEntityRef) /// or [`FilteredEntityMut`](crate::world::FilteredEntityMut). @@ -158,11 +164,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), @@ -170,7 +176,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) },)*) @@ -179,9 +185,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 ) { @@ -192,7 +198,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. diff --git a/crates/bevy_ecs/src/relationship/relationship_query.rs b/crates/bevy_ecs/src/relationship/relationship_query.rs index a2ec937c29b9a..a7acea7de0732 100644 --- a/crates/bevy_ecs/src/relationship/relationship_query.rs +++ b/crates/bevy_ecs/src/relationship/relationship_query.rs @@ -14,7 +14,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// target entity of that relationship. pub fn related(&'w self, entity: Entity) -> Option where - ::ReadOnly: QueryData = &'w R>, + ::ReadOnly: QueryData = &'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 + 'w where - ::ReadOnly: QueryData = &'w S>, + ::ReadOnly: QueryData = &'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(&'w self, entity: Entity) -> Entity where - ::ReadOnly: QueryData = &'w R>, + ::ReadOnly: QueryData = &'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( &'w self, entity: Entity, - ) -> impl Iterator + 'w + ) -> impl Iterator + use<'w, 's, S, D, F> where - ::ReadOnly: QueryData = &'w S>, + ::ReadOnly: QueryData = &'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 + 'w where - D::ReadOnly: QueryData = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>, + D::ReadOnly: QueryData = (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 = &'w S>, + D::ReadOnly: QueryData = &'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 = &'w S>, + D::ReadOnly: QueryData = &'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 = &'w R>, + D::ReadOnly: QueryData = &'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 = &'w S>, + D::ReadOnly: QueryData = &'w S>, { children_query: &'w Query<'w, 's, D, F>, vecdeque: VecDeque, @@ -156,7 +156,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantIter<'w, 's, D, F, S> where - D::ReadOnly: QueryData = &'w S>, + D::ReadOnly: QueryData = &'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 = &'w S>, + D::ReadOnly: QueryData = &'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 = &'w S>, + D::ReadOnly: QueryData = &'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 = &'w S>, + D::ReadOnly: QueryData = &'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 = &'w S>, + D::ReadOnly: QueryData = &'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 = &'w R>, + D::ReadOnly: QueryData = &'w R>, { parent_query: &'w Query<'w, 's, D, F>, next: Option, @@ -247,7 +247,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> AncestorIter<'w, 's, D, F, R> where - D::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'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 = &'w R>, + D::ReadOnly: QueryData = &'w R>, { type Item = Entity; diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 22f0d1df20f45..ab4a4f965ac69 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -1079,7 +1079,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() } @@ -1114,7 +1114,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() } @@ -1174,7 +1174,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn par_iter_many>( &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(), @@ -1203,7 +1203,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn par_iter_many_unique>( &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(), @@ -1232,7 +1232,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn par_iter_many_unique_mut>( &mut self, entities: EntityList, - ) -> QueryParManyUniqueIter<'_, '_, D, F, EntityList::Item> { + ) -> QueryParManyUniqueIter<'_, 's, D, F, EntityList::Item> { QueryParManyUniqueIter { world: self.world, state: self.state, @@ -1277,7 +1277,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, QueryEntityError> { + pub fn get(&self, entity: Entity) -> Result, QueryEntityError> { self.as_readonly().get_inner(entity) } @@ -1328,7 +1328,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn get_many( &self, entities: [Entity; N], - ) -> Result<[ROQueryItem<'_, D>; N], QueryEntityError> { + ) -> Result<[ROQueryItem<'_, 's, D>; N], QueryEntityError> { // Note that this calls `get_many_readonly` instead of `get_many_inner` // since we don't need to check for duplicates. self.as_readonly().get_many_readonly(entities) @@ -1378,7 +1378,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { #[inline] #[track_caller] #[deprecated(note = "Use `get_many` instead and handle the Result.")] - pub fn many(&self, entities: [Entity; N]) -> [ROQueryItem<'_, D>; N] { + pub fn many(&self, entities: [Entity; N]) -> [ROQueryItem<'_, 's, D>; N] { match self.get_many(entities) { Ok(items) => items, Err(error) => panic!("Cannot get query results: {error}"), @@ -1415,7 +1415,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, QueryEntityError> { + pub fn get_mut(&mut self, entity: Entity) -> Result, QueryEntityError> { self.reborrow().get_inner(entity) } @@ -1430,7 +1430,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, QueryEntityError<'w>> { + pub fn get_inner(self, entity: Entity) -> Result, QueryEntityError<'w>> { // SAFETY: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe { @@ -1553,7 +1553,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn get_many_mut( &mut self, entities: [Entity; N], - ) -> Result<[D::Item<'_>; N], QueryEntityError> { + ) -> Result<[D::Item<'_, 's>; N], QueryEntityError> { self.reborrow().get_many_inner(entities) } @@ -1573,7 +1573,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn get_many_inner( self, entities: [Entity; N], - ) -> Result<[D::Item<'w>; N], QueryEntityError<'w>> { + ) -> Result<[D::Item<'w, 's>; N], QueryEntityError<'w>> { // Verify that all entities are unique for i in 0..N { for j in 0..i { @@ -1602,7 +1602,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn get_many_readonly( self, entities: [Entity; N], - ) -> Result<[D::Item<'w>; N], QueryEntityError<'w>> + ) -> Result<[D::Item<'w, 's>; N], QueryEntityError<'w>> where D: ReadOnlyQueryData, { @@ -1620,7 +1620,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { unsafe fn get_many_impl( self, entities: [Entity; N], - ) -> Result<[D::Item<'w>; N], QueryEntityError<'w>> { + ) -> Result<[D::Item<'w, 's>; N], QueryEntityError<'w>> { let mut values = [(); N].map(|_| MaybeUninit::uninit()); for (value, entity) in core::iter::zip(&mut values, entities) { @@ -1684,7 +1684,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { #[inline] #[track_caller] #[deprecated(note = "Use `get_many_mut` instead and handle the Result.")] - pub fn many_mut(&mut self, entities: [Entity; N]) -> [D::Item<'_>; N] { + pub fn many_mut(&mut self, entities: [Entity; N]) -> [D::Item<'_, 's>; N] { match self.get_many_mut(entities) { Ok(items) => items, Err(error) => panic!("Cannot get query result: {error}"), @@ -1706,7 +1706,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, QueryEntityError> { + pub unsafe fn get_unchecked( + &self, + entity: Entity, + ) -> Result, QueryEntityError> { // SAFETY: The caller promises that this will not result in multiple mutable references. unsafe { self.reborrow_unsafe() }.get_inner(entity) } @@ -1742,13 +1745,13 @@ 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, QuerySingleError> { + pub fn single(&self) -> Result, QuerySingleError> { self.as_readonly().single_inner() } /// A deprecated alias for [`single`](Self::single). #[deprecated(note = "Please use `single` instead")] - pub fn get_single(&self) -> Result, QuerySingleError> { + pub fn get_single(&self) -> Result, QuerySingleError> { self.single() } @@ -1777,13 +1780,13 @@ 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, QuerySingleError> { + pub fn single_mut(&mut self) -> Result, QuerySingleError> { self.reborrow().single_inner() } /// A deprecated alias for [`single_mut`](Self::single_mut). #[deprecated(note = "Please use `single_mut` instead")] - pub fn get_single_mut(&mut self) -> Result, QuerySingleError> { + pub fn get_single_mut(&mut self) -> Result, QuerySingleError> { self.single_mut() } @@ -1815,7 +1818,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, QuerySingleError> { + pub fn single_inner(self) -> Result, QuerySingleError> { let mut query = self.into_iter(); let first = query.next(); let extra = query.next().is_some(); @@ -2315,7 +2318,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 { @@ -2328,7 +2331,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 { @@ -2337,7 +2340,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 { @@ -2437,28 +2440,28 @@ impl<'w, 'q, Q: QueryData, F: QueryFilter> From<&'q mut Query<'w, '_, Q, F>> /// See [`Query`] for more details. /// /// [System parameter]: crate::system::SystemParam -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, } -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 } } diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index c30cc191dd4b0..736092ed6f5c3 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -378,9 +378,11 @@ fn assert_component_access_compatibility( // SAFETY: Relevant query ComponentId and ArchetypeComponentId 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; - type Item<'w, 's> = Single<'w, D, F>; + type Item<'w, 's> = Single<'w, 's, D, F>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { Query::init_state(world, system_meta) @@ -442,11 +444,11 @@ unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam fo // SAFETY: Relevant query ComponentId and ArchetypeComponentId 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 Option> +unsafe impl<'a, 'b, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam + for Option> { type State = QueryState; - type Item<'w, 's> = Option>; + type Item<'w, 's> = Option>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { Single::init_state(world, system_meta) @@ -510,14 +512,14 @@ unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam } // 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> { } // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. -unsafe impl<'a, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam - for Option> +unsafe impl<'a, 'b, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam + for Option> { } diff --git a/crates/bevy_ecs/src/traversal.rs b/crates/bevy_ecs/src/traversal.rs index 342ad47849e06..a4d05540ebfda 100644 --- a/crates/bevy_ecs/src/traversal.rs +++ b/crates/bevy_ecs/src/traversal.rs @@ -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::Event::Traversal /// [event propagation]: crate::observer::Trigger::propagate /// [observers]: crate::observer::Observer -pub trait Traversal: ReadOnlyQueryData { +pub trait Traversal: ReadOnlyQueryData + ReleaseStateQueryData { /// Returns the next entity to visit. - fn traverse(item: Self::Item<'_>, data: &D) -> Option; + fn traverse(item: Self::Item<'_, '_>, data: &D) -> Option; } impl Traversal for () { - fn traverse(_: Self::Item<'_>, _data: &D) -> Option { + fn traverse(_: Self::Item<'_, '_>, _data: &D) -> Option { None } } @@ -39,7 +43,7 @@ impl Traversal for () { /// /// [event propagation]: crate::observer::Trigger::propagate impl Traversal for &R { - fn traverse(item: Self::Item<'_>, _data: &D) -> Option { + fn traverse(item: Self::Item<'_, '_>, _data: &D) -> Option { Some(item.get()) } } diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index 7c6d8ac3603b5..aeaeabe3d9bc2 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -12,7 +12,7 @@ use crate::{ }, event::Event, observer::Observer, - query::{Access, ReadOnlyQueryData}, + query::{Access, ReadOnlyQueryData, ReleaseStateQueryData}, relationship::RelationshipInsertHookMode, removal_detection::RemovedComponentEvents, resource::Resource, @@ -280,14 +280,16 @@ impl<'w> EntityRef<'w> { /// # Panics /// /// If the entity does not have the components required by the query `Q`. - pub fn components(&self) -> Q::Item<'w> { + pub fn components(&self) -> Q::Item<'w, 'static> { self.get_components::() .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(&self) -> Option> { + pub fn get_components( + &self, + ) -> Option> { // SAFETY: We have read-only access to all components of this entity. unsafe { self.cell.get_components::() } } @@ -541,13 +543,15 @@ impl<'w> EntityMut<'w> { /// # Panics /// /// If the entity does not have the components required by the query `Q`. - pub fn components(&self) -> Q::Item<'_> { + pub fn components(&self) -> Q::Item<'_, 'static> { self.as_readonly().components::() } /// 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(&self) -> Option> { + pub fn get_components( + &self, + ) -> Option> { self.as_readonly().get_components::() } @@ -1181,7 +1185,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(&self) -> Q::Item<'_> { + pub fn components(&self) -> Q::Item<'_, 'static> { self.as_readonly().components::() } @@ -1192,7 +1196,9 @@ impl<'w> EntityWorldMut<'w> { /// /// If the entity has been despawned while this `EntityWorldMut` is still alive. #[inline] - pub fn get_components(&self) -> Option> { + pub fn get_components( + &self, + ) -> Option> { self.as_readonly().get_components::() } diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index f094906b1267b..f96423a83ef7c 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -9,7 +9,7 @@ use crate::{ entity::{Entities, Entity, EntityBorrow, EntityDoesNotExistError, EntityLocation}, observer::Observers, prelude::Component, - query::{DebugCheckedUnwrap, ReadOnlyQueryData}, + query::{DebugCheckedUnwrap, ReadOnlyQueryData, ReleaseStateQueryData}, removal_detection::RemovedComponentEvents, resource::Resource, storage::{ComponentSparseSet, Storages, Table}, @@ -960,7 +960,9 @@ impl<'w> UnsafeEntityCell<'w> { /// It is the callers 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(&self) -> Option> { + pub(crate) unsafe fn get_components( + &self, + ) -> Option> { // SAFETY: World is only used to access query data and initialize query state let state = unsafe { let world = self.world().world(); @@ -996,7 +998,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 } diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index fdc2243233916..bf43d87a9ef51 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -634,8 +634,8 @@ impl RenderCommand

for SetLineGizmoBindGroup #[inline] fn render<'w>( _item: &P, - _view: ROQueryItem<'w, Self::ViewQuery>, - uniform_index: Option>, + _view: ROQueryItem<'w, '_, Self::ViewQuery>, + uniform_index: Option>, bind_group: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -665,8 +665,8 @@ impl RenderCommand

for DrawLineGizmo #[inline] fn render<'w>( _item: &P, - _view: ROQueryItem<'w, Self::ViewQuery>, - config: Option>, + _view: ROQueryItem<'w, '_, Self::ViewQuery>, + config: Option>, line_gizmos: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -728,8 +728,8 @@ impl RenderCommand

for DrawLineJointGizmo { #[inline] fn render<'w>( _item: &P, - _view: ROQueryItem<'w, Self::ViewQuery>, - config: Option>, + _view: ROQueryItem<'w, '_, Self::ViewQuery>, + config: Option>, line_gizmos: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_input_focus/src/lib.rs b/crates/bevy_input_focus/src/lib.rs index 573ce56d8979f..a3c89563f1010 100644 --- a/crates/bevy_input_focus/src/lib.rs +++ b/crates/bevy_input_focus/src/lib.rs @@ -156,7 +156,7 @@ pub struct WindowTraversal { } impl Traversal> for WindowTraversal { - fn traverse(item: Self::Item<'_>, event: &FocusedInput) -> Option { + fn traverse(item: Self::Item<'_, '_>, event: &FocusedInput) -> Option { let WindowTraversalItem { child_of, window } = item; // Send event to parent, if it has one. diff --git a/crates/bevy_pbr/src/atmosphere/mod.rs b/crates/bevy_pbr/src/atmosphere/mod.rs index 82dc201c5de2d..0584f1ee55106 100644 --- a/crates/bevy_pbr/src/atmosphere/mod.rs +++ b/crates/bevy_pbr/src/atmosphere/mod.rs @@ -368,7 +368,7 @@ impl ExtractComponent for Atmosphere { type Out = Atmosphere; - fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(item.clone()) } } @@ -463,7 +463,7 @@ impl ExtractComponent for AtmosphereSettings { type Out = AtmosphereSettings; - fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(item.clone()) } } diff --git a/crates/bevy_pbr/src/atmosphere/node.rs b/crates/bevy_pbr/src/atmosphere/node.rs index 851447d760fc3..e09b27c590a04 100644 --- a/crates/bevy_pbr/src/atmosphere/node.rs +++ b/crates/bevy_pbr/src/atmosphere/node.rs @@ -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::(); diff --git a/crates/bevy_pbr/src/light_probe/environment_map.rs b/crates/bevy_pbr/src/light_probe/environment_map.rs index 8069f2acac752..5f6bd6502cff2 100644 --- a/crates/bevy_pbr/src/light_probe/environment_map.rs +++ b/crates/bevy_pbr/src/light_probe/environment_map.rs @@ -196,7 +196,7 @@ impl ExtractInstance for EnvironmentMapIds { type QueryFilter = (); - fn extract(item: QueryItem<'_, Self::QueryData>) -> Option { + fn extract(item: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(EnvironmentMapIds { diffuse: item.diffuse_map.id(), specular: item.specular_map.id(), diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 433df17c54e4e..233de4ae1236c 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -1567,7 +1567,7 @@ fn extract_mesh_for_gpu_building( not_shadow_caster, no_automatic_batching, visibility_range, - ): ::Item<'_>, + ): ::Item<'_, '_>, render_visibility_ranges: &RenderVisibilityRanges, render_mesh_instances: &RenderMeshInstancesGpu, queue: &mut RenderMeshInstanceGpuQueue, @@ -2897,7 +2897,7 @@ impl RenderCommand

for SetMeshViewBindGroup 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>, diff --git a/crates/bevy_pbr/src/ssr/mod.rs b/crates/bevy_pbr/src/ssr/mod.rs index fa7424145f51b..296a11bb41fb3 100644 --- a/crates/bevy_pbr/src/ssr/mod.rs +++ b/crates/bevy_pbr/src/ssr/mod.rs @@ -287,7 +287,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. @@ -502,7 +502,7 @@ impl ExtractComponent for ScreenSpaceReflections { type Out = ScreenSpaceReflectionsUniform; - fn extract_component(settings: QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(settings: QueryItem<'_, '_, Self::QueryData>) -> Option { if !DEPTH_TEXTURE_SAMPLING_SUPPORTED { once!(info!( "Disabling screen-space reflections on this platform because depth textures \ diff --git a/crates/bevy_pbr/src/volumetric_fog/render.rs b/crates/bevy_pbr/src/volumetric_fog/render.rs index 632a6f2c30a72..403d5afb93b42 100644 --- a/crates/bevy_pbr/src/volumetric_fog/render.rs +++ b/crates/bevy_pbr/src/volumetric_fog/render.rs @@ -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::(); diff --git a/crates/bevy_picking/src/events.rs b/crates/bevy_picking/src/events.rs index a5435d6f5983d..35296d3ba241d 100644 --- a/crates/bevy_picking/src/events.rs +++ b/crates/bevy_picking/src/events.rs @@ -87,7 +87,7 @@ impl Traversal> for PointerTraversal where E: Debug + Clone + Reflect, { - fn traverse(item: Self::Item<'_>, pointer: &Pointer) -> Option { + fn traverse(item: Self::Item<'_, '_>, pointer: &Pointer) -> Option { let PointerTraversalItem { child_of, window } = item; // Send event to parent, if it has one. diff --git a/crates/bevy_render/macros/src/extract_component.rs b/crates/bevy_render/macros/src/extract_component.rs index 2bfd0e0e11133..8526f7b889c11 100644 --- a/crates/bevy_render/macros/src/extract_component.rs +++ b/crates/bevy_render/macros/src/extract_component.rs @@ -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 { + fn extract_component(item: #bevy_ecs_path::query::QueryItem<'_, '_, Self::QueryData>) -> Option { Some(item.clone()) } } diff --git a/crates/bevy_render/src/extract_component.rs b/crates/bevy_render/src/extract_component.rs index 19d15a2b8607c..1c4ec79a777c7 100644 --- a/crates/bevy_render/src/extract_component.rs +++ b/crates/bevy_render/src/extract_component.rs @@ -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; + fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option; } /// This plugin prepares the components of the corresponding type for the GPU diff --git a/crates/bevy_render/src/extract_instances.rs b/crates/bevy_render/src/extract_instances.rs index a8e5a9ecbdf92..cd194b7c40274 100644 --- a/crates/bevy_render/src/extract_instances.rs +++ b/crates/bevy_render/src/extract_instances.rs @@ -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; + fn extract(item: QueryItem<'_, '_, Self::QueryData>) -> Option; } /// This plugin extracts one or more components into the "render world" as diff --git a/crates/bevy_render/src/render_graph/node.rs b/crates/bevy_render/src/render_graph/node.rs index 0a634c2598461..4355892487c00 100644 --- a/crates/bevy_render/src/render_graph/node.rs +++ b/crates/bevy_render/src/render_graph/node.rs @@ -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>; } diff --git a/crates/bevy_render/src/render_phase/draw.rs b/crates/bevy_render/src/render_phase/draw.rs index a12d336018508..9a093d0c0797a 100644 --- a/crates/bevy_render/src/render_phase/draw.rs +++ b/crates/bevy_render/src/render_phase/draw.rs @@ -213,8 +213,8 @@ pub trait RenderCommand { /// issuing draw calls, etc.) via the [`TrackedRenderPass`]. fn render<'w>( item: &P, - view: ROQueryItem<'w, Self::ViewQuery>, - entity: Option>, + view: ROQueryItem<'w, '_, Self::ViewQuery>, + entity: Option>, 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>, + ($($view,)*): ROQueryItem<'w, '_, Self::ViewQuery>, + maybe_entities: Option>, ($($name,)*): SystemParamItem<'w, '_, Self::Param>, _pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index 83fabd40fd670..d661f013dc232 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -277,7 +277,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}, }; @@ -285,22 +285,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) @@ -310,9 +310,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, ) { @@ -323,9 +323,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`. @@ -360,18 +360,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) }; @@ -382,25 +384,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) @@ -410,8 +418,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, @@ -423,9 +431,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`. @@ -460,18 +468,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() @@ -480,6 +490,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)] diff --git a/crates/bevy_sprite/src/mesh2d/mesh.rs b/crates/bevy_sprite/src/mesh2d/mesh.rs index 5822d47ed6231..8d355f36c1a9a 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh.rs +++ b/crates/bevy_sprite/src/mesh2d/mesh.rs @@ -817,7 +817,7 @@ impl RenderCommand

for SetMesh2dViewBindGroup( _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>, diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index b188ebbc1aa47..7651abe31ec5b 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -823,7 +823,7 @@ impl RenderCommand

for SetSpriteViewBindGroup( _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>, @@ -840,7 +840,7 @@ impl RenderCommand

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>, @@ -870,7 +870,7 @@ impl RenderCommand

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>, diff --git a/crates/bevy_ui/src/render/ui_material_pipeline.rs b/crates/bevy_ui/src/render/ui_material_pipeline.rs index 2162b92373c9d..e1ca672c66a3d 100644 --- a/crates/bevy_ui/src/render/ui_material_pipeline.rs +++ b/crates/bevy_ui/src/render/ui_material_pipeline.rs @@ -296,7 +296,7 @@ impl RenderCommand

fn render<'w>( _item: &P, _view: (), - material_handle: Option>, + material_handle: Option>, materials: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/examples/ecs/custom_query_param.rs b/examples/ecs/custom_query_param.rs index 39b3e6f072812..8960557ef4e85 100644 --- a/examples/ecs/custom_query_param.rs +++ b/examples/ecs/custom_query_param.rs @@ -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); diff --git a/examples/shader/custom_phase_item.rs b/examples/shader/custom_phase_item.rs index fe69c5b8125ac..984aaffcbfbe4 100644 --- a/examples/shader/custom_phase_item.rs +++ b/examples/shader/custom_phase_item.rs @@ -73,8 +73,8 @@ where fn render<'w>( _: &P, - _: ROQueryItem<'w, Self::ViewQuery>, - _: Option>, + _: ROQueryItem<'w, '_, Self::ViewQuery>, + _: Option>, custom_phase_item_buffers: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/examples/shader/custom_render_phase.rs b/examples/shader/custom_render_phase.rs index 47aad1b88faef..d4a7680f4cb5c 100644 --- a/examples/shader/custom_render_phase.rs +++ b/examples/shader/custom_render_phase.rs @@ -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 diff --git a/examples/shader/custom_shader_instancing.rs b/examples/shader/custom_shader_instancing.rs index cd5909c36fff1..9ff05a3f9cd47 100644 --- a/examples/shader/custom_shader_instancing.rs +++ b/examples/shader/custom_shader_instancing.rs @@ -88,7 +88,7 @@ impl ExtractComponent for InstanceMaterialData { type QueryFilter = (); type Out = Self; - fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(InstanceMaterialData(item.0.clone())) } }