diff --git a/crates/bevy_ecs/macros/src/world_query.rs b/crates/bevy_ecs/macros/src/world_query.rs index eba619c468bbf..1e9e3f847a185 100644 --- a/crates/bevy_ecs/macros/src/world_query.rs +++ b/crates/bevy_ecs/macros/src/world_query.rs @@ -97,6 +97,16 @@ pub(crate) fn world_query_impl( type Fetch<'__w> = #fetch_struct_name #user_ty_generics_with_world; type State = #state_struct_name #user_ty_generics; + fn shrink<'__wlong: '__wshort, '__wshort>( + item: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wlong> + ) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wshort> { + #item_struct_name { + #( + #field_idents: <#field_types>::shrink(item.#field_idents), + )* + } + } + unsafe fn init_fetch<'__w>( _world: #path::world::unsafe_world_cell::UnsafeWorldCell<'__w>, state: &Self::State, diff --git a/crates/bevy_ecs/macros/src/world_query_data.rs b/crates/bevy_ecs/macros/src/world_query_data.rs index a793b2e3c393c..c1bd078389871 100644 --- a/crates/bevy_ecs/macros/src/world_query_data.rs +++ b/crates/bevy_ecs/macros/src/world_query_data.rs @@ -277,19 +277,7 @@ pub fn derive_world_query_data_impl(input: TokenStream) -> TokenStream { unsafe impl #user_impl_generics #path::query::WorldQueryData for #read_only_struct_name #user_ty_generics #user_where_clauses { type ReadOnly = #read_only_struct_name #user_ty_generics; - - fn shrink<'__wlong: '__wshort, '__wshort>( - item: <#read_only_struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wlong> - ) -> <#read_only_struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wshort> { - #read_only_item_struct_name { - #( - #field_idents: <#read_only_field_types>::shrink(item.#field_idents), - )* - } - } } - - } } else { quote! {} @@ -300,16 +288,6 @@ pub fn derive_world_query_data_impl(input: TokenStream) -> TokenStream { unsafe impl #user_impl_generics #path::query::WorldQueryData for #struct_name #user_ty_generics #user_where_clauses { type ReadOnly = #read_only_struct_name #user_ty_generics; - - fn shrink<'__wlong: '__wshort, '__wshort>( - item: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wlong> - ) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wshort> { - #item_struct_name { - #( - #field_idents: <#field_types>::shrink(item.#field_idents), - )* - } - } } #read_only_data_impl diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 3eb67b329714b..f322c5d14572b 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -260,9 +260,6 @@ use std::{cell::UnsafeCell, marker::PhantomData}; pub unsafe trait WorldQueryData: WorldQuery { /// The read-only variant of this [`WorldQueryData`], which satisfies the [`ReadOnlyWorldQueryData`] trait. type ReadOnly: ReadOnlyWorldQueryData::State>; - - /// This function manually implements subtyping for the query items. - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort>; } /// A [`WorldQueryData`] that is read only. @@ -285,6 +282,10 @@ unsafe impl WorldQuery for Entity { type Item<'w> = Entity; type State = (); + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + item + } + const IS_DENSE: bool = true; unsafe fn init_fetch<'w>( @@ -339,10 +340,6 @@ unsafe impl WorldQuery for Entity { /// SAFETY: `Self` is the same as `Self::ReadOnly` unsafe impl WorldQueryData for Entity { type ReadOnly = Self; - - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { - item - } } /// SAFETY: access is read only @@ -357,6 +354,10 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> { type Item<'w> = EntityRef<'w>; type State = (); + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + item + } + const IS_DENSE: bool = true; unsafe fn init_fetch<'w>( @@ -424,10 +425,6 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> { /// SAFETY: `Self` is the same as `Self::ReadOnly` unsafe impl<'a> WorldQueryData for EntityRef<'a> { type ReadOnly = Self; - - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { - item - } } /// SAFETY: access is read only @@ -439,6 +436,10 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> { type Item<'w> = EntityMut<'w>; type State = (); + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + item + } + const IS_DENSE: bool = true; unsafe fn init_fetch<'w>( @@ -506,10 +507,6 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> { /// SAFETY: access of `EntityRef` is a subset of `EntityMut` unsafe impl<'a> WorldQueryData for EntityMut<'a> { type ReadOnly = EntityRef<'a>; - - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { - item - } } #[doc(hidden)] @@ -537,6 +534,10 @@ unsafe impl WorldQuery for &T { type Item<'w> = &'w T; type State = ComponentId; + fn shrink<'wlong: 'wshort, 'wshort>(item: &'wlong T) -> &'wshort T { + item + } + const IS_DENSE: bool = { match T::Storage::STORAGE_TYPE { StorageType::Table => true, @@ -652,10 +653,6 @@ unsafe impl WorldQuery for &T { /// SAFETY: `Self` is the same as `Self::ReadOnly` unsafe impl WorldQueryData for &T { type ReadOnly = Self; - - fn shrink<'wlong: 'wshort, 'wshort>(item: &'wlong T) -> &'wshort T { - item - } } /// SAFETY: access is read only @@ -693,6 +690,10 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> { type Item<'w> = Ref<'w, T>; type State = ComponentId; + fn shrink<'wlong: 'wshort, 'wshort>(item: Ref<'wlong, T>) -> Ref<'wshort, T> { + item + } + const IS_DENSE: bool = { match T::Storage::STORAGE_TYPE { StorageType::Table => true, @@ -819,10 +820,6 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> { /// SAFETY: `Self` is the same as `Self::ReadOnly` unsafe impl<'__w, T: Component> WorldQueryData for Ref<'__w, T> { type ReadOnly = Self; - - fn shrink<'wlong: 'wshort, 'wshort>(item: Ref<'wlong, T>) -> Ref<'wshort, T> { - item - } } /// SAFETY: access is read only @@ -860,6 +857,10 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T { type Item<'w> = Mut<'w, T>; type State = ComponentId; + fn shrink<'wlong: 'wshort, 'wshort>(item: Mut<'wlong, T>) -> Mut<'wshort, T> { + item + } + const IS_DENSE: bool = { match T::Storage::STORAGE_TYPE { StorageType::Table => true, @@ -986,10 +987,6 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T { /// SAFETY: access of `&T` is a subset of `&mut T` unsafe impl<'__w, T: Component> WorldQueryData for &'__w mut T { type ReadOnly = &'__w T; - - fn shrink<'wlong: 'wshort, 'wshort>(item: Mut<'wlong, T>) -> Mut<'wshort, T> { - item - } } #[doc(hidden)] @@ -1016,6 +1013,10 @@ unsafe impl WorldQuery for Option { type Item<'w> = Option>; type State = T::State; + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + item.map(T::shrink) + } + const IS_DENSE: bool = T::IS_DENSE; #[inline] @@ -1103,10 +1104,6 @@ unsafe impl WorldQuery for Option { // SAFETY: defers to soundness of `T: WorldQuery` impl unsafe impl WorldQueryData for Option { type ReadOnly = Option; - - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { - item.map(T::shrink) - } } /// SAFETY: [`OptionFetch`] is read only because `T` is read only @@ -1175,6 +1172,10 @@ unsafe impl WorldQuery for Has { type Item<'w> = bool; type State = ComponentId; + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + item + } + const IS_DENSE: bool = { match T::Storage::STORAGE_TYPE { StorageType::Table => true, @@ -1243,10 +1244,6 @@ unsafe impl WorldQuery for Has { /// SAFETY: `Self` is the same as `Self::ReadOnly` unsafe impl WorldQueryData for Has { type ReadOnly = Self; - - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { - item - } } /// SAFETY: [`Has`] is read only @@ -1267,13 +1264,6 @@ macro_rules! impl_tuple_world_query_data { // SAFETY: defers to soundness `$name: WorldQuery` impl unsafe impl<$($name: WorldQueryData),*> WorldQueryData for ($($name,)*) { type ReadOnly = ($($name::ReadOnly,)*); - - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { - let ($($name,)*) = item; - ($( - $name::shrink($name), - )*) - } } /// SAFETY: each item in the tuple is read only @@ -1297,6 +1287,13 @@ macro_rules! impl_anytuple_fetch { type Item<'w> = ($(Option<$name::Item<'w>>,)*); type State = ($($name::State,)*); + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + let ($($name,)*) = item; + ($( + $name.map($name::shrink), + )*) + } + #[inline] #[allow(clippy::unused_unit)] unsafe fn init_fetch<'w>(_world: UnsafeWorldCell<'w>, state: &Self::State, _last_run: Tick, _this_run: Tick) -> Self::Fetch<'w> { @@ -1306,8 +1303,6 @@ macro_rules! impl_anytuple_fetch { const IS_DENSE: bool = true $(&& $name::IS_DENSE)*; - - #[inline] unsafe fn set_archetype<'w>( _fetch: &mut Self::Fetch<'w>, @@ -1394,13 +1389,6 @@ macro_rules! impl_anytuple_fetch { // SAFETY: defers to soundness of `$name: WorldQuery` impl unsafe impl<$($name: WorldQueryData),*> WorldQueryData for AnyOf<($($name,)*)> { type ReadOnly = AnyOf<($($name::ReadOnly,)*)>; - - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { - let ($($name,)*) = item; - ($( - $name.map($name::shrink), - )*) - } } /// SAFETY: each item in the tuple is read only @@ -1424,6 +1412,8 @@ unsafe impl WorldQuery for NopWorldQuery { type Item<'w> = (); type State = Q::State; + fn shrink<'wlong: 'wshort, 'wshort>(_: ()) {} + const IS_DENSE: bool = Q::IS_DENSE; #[inline(always)] @@ -1479,8 +1469,6 @@ unsafe impl WorldQuery for NopWorldQuery { /// SAFETY: `Self::ReadOnly` is `Self` unsafe impl WorldQueryData for NopWorldQuery { type ReadOnly = Self; - - fn shrink<'wlong: 'wshort, 'wshort>(_: ()) {} } /// SAFETY: `NopFetch` never accesses any data @@ -1495,6 +1483,8 @@ unsafe impl WorldQuery for PhantomData { type State = (); + fn shrink<'wlong: 'wshort, 'wshort>(_item: Self::Item<'wlong>) -> Self::Item<'wshort> {} + unsafe fn init_fetch<'w>( _world: UnsafeWorldCell<'w>, _state: &Self::State, @@ -1547,8 +1537,6 @@ unsafe impl WorldQuery for PhantomData { /// SAFETY: `Self::ReadOnly` is `Self` unsafe impl WorldQueryData for PhantomData { type ReadOnly = Self; - - fn shrink<'wlong: 'wshort, 'wshort>(_item: Self::Item<'wlong>) -> Self::Item<'wshort> {} } /// SAFETY: `PhantomData` never accesses any world data. diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index 77bd3461b793b..5056e78f3e920 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -136,6 +136,8 @@ unsafe impl WorldQuery for With { type Item<'w> = (); type State = ComponentId; + fn shrink<'wlong: 'wshort, 'wshort>(_: Self::Item<'wlong>) -> Self::Item<'wshort> {} + #[inline] unsafe fn init_fetch( _world: UnsafeWorldCell, @@ -246,6 +248,8 @@ unsafe impl WorldQuery for Without { type Item<'w> = (); type State = ComponentId; + fn shrink<'wlong: 'wshort, 'wshort>(_: Self::Item<'wlong>) -> Self::Item<'wshort> {} + #[inline] unsafe fn init_fetch( _world: UnsafeWorldCell, @@ -382,6 +386,10 @@ macro_rules! impl_query_filter_tuple { type Item<'w> = bool; type State = ($($filter::State,)*); + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + item + } + const IS_DENSE: bool = true $(&& $filter::IS_DENSE)*; #[inline] @@ -555,6 +563,10 @@ unsafe impl WorldQuery for Added { type Item<'w> = bool; type State = ComponentId; + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + item + } + #[inline] unsafe fn init_fetch<'w>( world: UnsafeWorldCell<'w>, @@ -720,6 +732,10 @@ unsafe impl WorldQuery for Changed { type Item<'w> = bool; type State = ComponentId; + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + item + } + #[inline] unsafe fn init_fetch<'w>( world: UnsafeWorldCell<'w>, diff --git a/crates/bevy_ecs/src/query/world_query.rs b/crates/bevy_ecs/src/query/world_query.rs index c14290bd19afc..8e867750a6050 100644 --- a/crates/bevy_ecs/src/query/world_query.rs +++ b/crates/bevy_ecs/src/query/world_query.rs @@ -53,6 +53,9 @@ pub unsafe trait WorldQuery { /// constructing [`Self::Fetch`](crate::query::WorldQuery::Fetch). type State: Send + Sync + Sized; + /// This function manually implements subtyping for the query items. + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort>; + /// Creates a new instance of this fetch. /// /// # Safety @@ -154,9 +157,15 @@ macro_rules! impl_tuple_world_query { unsafe impl<$($name: WorldQuery),*> WorldQuery for ($($name,)*) { type Fetch<'w> = ($($name::Fetch<'w>,)*); type Item<'w> = ($($name::Item<'w>,)*); - type State = ($($name::State,)*); + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + let ($($name,)*) = item; + ($( + $name::shrink($name), + )*) + } + #[inline] #[allow(clippy::unused_unit)] unsafe fn init_fetch<'w>(_world: UnsafeWorldCell<'w>, state: &Self::State, _last_run: Tick, _this_run: Tick) -> Self::Fetch<'w> { @@ -206,7 +215,6 @@ macro_rules! impl_tuple_world_query { $($name::update_archetype_component_access($name, _archetype, _access);)* } - fn init_state(_world: &mut World) -> Self::State { ($($name::init_state(_world),)*) }