Rename track_change_detection flag to track_location (#17075)

# Objective

- As stated in the related issue, this PR is to better align the feature
flag name with what it actually does and the plans for the future.
- Fixes #16852 

## Solution

- Simple find / replace

## Testing

- Local run of `cargo run -p ci`

## Migration Guide

The `track_change_detection` feature flag has been renamed to
`track_location` to better reflect its extended capabilities.
This commit is contained in:
Sean Kim 2025-01-01 10:43:47 -08:00 committed by GitHub
parent fd330c834f
commit 294e0db719
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 289 additions and 289 deletions

View File

@ -455,7 +455,7 @@ ios_simulator = ["bevy_internal/ios_simulator"]
bevy_state = ["bevy_internal/bevy_state"] bevy_state = ["bevy_internal/bevy_state"]
# Enables source location tracking for change detection and spawning/despawning, which can assist with debugging # Enables source location tracking for change detection and spawning/despawning, which can assist with debugging
track_change_detection = ["bevy_internal/track_change_detection"] track_location = ["bevy_internal/track_location"]
# Enable function reflection # Enable function reflection
reflect_functions = ["bevy_internal/reflect_functions"] reflect_functions = ["bevy_internal/reflect_functions"]
@ -1853,7 +1853,7 @@ wasm = false
name = "change_detection" name = "change_detection"
path = "examples/ecs/change_detection.rs" path = "examples/ecs/change_detection.rs"
doc-scrape-examples = true doc-scrape-examples = true
required-features = ["track_change_detection"] required-features = ["track_location"]
[package.metadata.example.change_detection] [package.metadata.example.change_detection]
name = "Change Detection" name = "Change Detection"

View File

@ -43,7 +43,7 @@ bevy_debug_stepping = []
## Provides more detailed tracking of the cause of various effects within the ECS. ## Provides more detailed tracking of the cause of various effects within the ECS.
## This will often provide more detailed error messages. ## This will often provide more detailed error messages.
track_change_detection = [] track_location = []
# Executor Backend # Executor Backend

View File

@ -23,7 +23,7 @@ use crate::{
use alloc::{boxed::Box, vec, vec::Vec}; use alloc::{boxed::Box, vec, vec::Vec};
use bevy_ptr::{ConstNonNull, OwningPtr}; use bevy_ptr::{ConstNonNull, OwningPtr};
use bevy_utils::{HashMap, HashSet, TypeIdMap}; use bevy_utils::{HashMap, HashSet, TypeIdMap};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use core::{any::TypeId, ptr::NonNull}; use core::{any::TypeId, ptr::NonNull};
use variadics_please::all_tuples; use variadics_please::all_tuples;
@ -516,7 +516,7 @@ impl BundleInfo {
change_tick: Tick, change_tick: Tick,
bundle: T, bundle: T,
insert_mode: InsertMode, insert_mode: InsertMode,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) { ) {
// NOTE: get_components calls this closure on each component in "bundle order". // NOTE: get_components calls this closure on each component in "bundle order".
// bundle_info.component_ids are also in "bundle order" // bundle_info.component_ids are also in "bundle order"
@ -535,14 +535,14 @@ impl BundleInfo {
table_row, table_row,
component_ptr, component_ptr,
change_tick, change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
), ),
(ComponentStatus::Existing, InsertMode::Replace) => column.replace( (ComponentStatus::Existing, InsertMode::Replace) => column.replace(
table_row, table_row,
component_ptr, component_ptr,
change_tick, change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
), ),
(ComponentStatus::Existing, InsertMode::Keep) => { (ComponentStatus::Existing, InsertMode::Keep) => {
@ -561,7 +561,7 @@ impl BundleInfo {
entity, entity,
component_ptr, component_ptr,
change_tick, change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -576,7 +576,7 @@ impl BundleInfo {
change_tick, change_tick,
table_row, table_row,
entity, entity,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -604,7 +604,7 @@ impl BundleInfo {
component_id: ComponentId, component_id: ComponentId,
storage_type: StorageType, storage_type: StorageType,
component_ptr: OwningPtr, component_ptr: OwningPtr,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) { ) {
{ {
match storage_type { match storage_type {
@ -617,7 +617,7 @@ impl BundleInfo {
table_row, table_row,
component_ptr, component_ptr,
change_tick, change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -630,7 +630,7 @@ impl BundleInfo {
entity, entity,
component_ptr, component_ptr,
change_tick, change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -1019,7 +1019,7 @@ impl<'w> BundleInserter<'w> {
location: EntityLocation, location: EntityLocation,
bundle: T, bundle: T,
insert_mode: InsertMode, insert_mode: InsertMode,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) -> EntityLocation { ) -> EntityLocation {
let bundle_info = self.bundle_info.as_ref(); let bundle_info = self.bundle_info.as_ref();
let archetype_after_insert = self.archetype_after_insert.as_ref(); let archetype_after_insert = self.archetype_after_insert.as_ref();
@ -1070,7 +1070,7 @@ impl<'w> BundleInserter<'w> {
self.change_tick, self.change_tick,
bundle, bundle,
insert_mode, insert_mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
@ -1112,7 +1112,7 @@ impl<'w> BundleInserter<'w> {
self.change_tick, self.change_tick,
bundle, bundle,
insert_mode, insert_mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
@ -1195,7 +1195,7 @@ impl<'w> BundleInserter<'w> {
self.change_tick, self.change_tick,
bundle, bundle,
insert_mode, insert_mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
@ -1330,7 +1330,7 @@ impl<'w> BundleSpawner<'w> {
&mut self, &mut self,
entity: Entity, entity: Entity,
bundle: T, bundle: T,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) -> EntityLocation { ) -> EntityLocation {
// SAFETY: We do not make any structural changes to the archetype graph through self.world so these pointers always remain valid // SAFETY: We do not make any structural changes to the archetype graph through self.world so these pointers always remain valid
let bundle_info = self.bundle_info.as_ref(); let bundle_info = self.bundle_info.as_ref();
@ -1355,7 +1355,7 @@ impl<'w> BundleSpawner<'w> {
self.change_tick, self.change_tick,
bundle, bundle,
InsertMode::Replace, InsertMode::Replace,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
entities.set(entity.index(), location); entities.set(entity.index(), location);
@ -1404,7 +1404,7 @@ impl<'w> BundleSpawner<'w> {
pub unsafe fn spawn<T: Bundle>( pub unsafe fn spawn<T: Bundle>(
&mut self, &mut self,
bundle: T, bundle: T,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) -> Entity { ) -> Entity {
let entity = self.entities().alloc(); let entity = self.entities().alloc();
// SAFETY: entity is allocated (but non-existent), `T` matches this BundleInfo's type // SAFETY: entity is allocated (but non-existent), `T` matches this BundleInfo's type
@ -1412,7 +1412,7 @@ impl<'w> BundleSpawner<'w> {
self.spawn_non_existent( self.spawn_non_existent(
entity, entity,
bundle, bundle,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }

View File

@ -11,7 +11,7 @@ use core::{
mem, mem,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
}; };
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use { use {
bevy_ptr::ThinSlicePtr, bevy_ptr::ThinSlicePtr,
core::{cell::UnsafeCell, panic::Location}, core::{cell::UnsafeCell, panic::Location},
@ -73,7 +73,7 @@ pub trait DetectChanges {
fn last_changed(&self) -> Tick; fn last_changed(&self) -> Tick;
/// The location that last caused this to change. /// The location that last caused this to change.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
fn changed_by(&self) -> &'static Location<'static>; fn changed_by(&self) -> &'static Location<'static>;
} }
@ -343,7 +343,7 @@ macro_rules! change_detection_impl {
} }
#[inline] #[inline]
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
fn changed_by(&self) -> &'static Location<'static> { fn changed_by(&self) -> &'static Location<'static> {
self.changed_by self.changed_by
} }
@ -376,7 +376,7 @@ macro_rules! change_detection_mut_impl {
#[track_caller] #[track_caller]
fn set_changed(&mut self) { fn set_changed(&mut self) {
*self.ticks.changed = self.ticks.this_run; *self.ticks.changed = self.ticks.this_run;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
*self.changed_by = Location::caller(); *self.changed_by = Location::caller();
} }
@ -386,7 +386,7 @@ macro_rules! change_detection_mut_impl {
#[track_caller] #[track_caller]
fn set_last_changed(&mut self, last_changed: Tick) { fn set_last_changed(&mut self, last_changed: Tick) {
*self.ticks.changed = last_changed; *self.ticks.changed = last_changed;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
*self.changed_by = Location::caller(); *self.changed_by = Location::caller();
} }
@ -403,7 +403,7 @@ macro_rules! change_detection_mut_impl {
#[track_caller] #[track_caller]
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
self.set_changed(); self.set_changed();
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
*self.changed_by = Location::caller(); *self.changed_by = Location::caller();
} }
@ -444,7 +444,7 @@ macro_rules! impl_methods {
last_run: self.ticks.last_run, last_run: self.ticks.last_run,
this_run: self.ticks.this_run, this_run: self.ticks.this_run,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: self.changed_by, changed_by: self.changed_by,
} }
} }
@ -475,7 +475,7 @@ macro_rules! impl_methods {
Mut { Mut {
value: f(self.value), value: f(self.value),
ticks: self.ticks, ticks: self.ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: self.changed_by, changed_by: self.changed_by,
} }
} }
@ -489,7 +489,7 @@ macro_rules! impl_methods {
value.map(|value| Mut { value.map(|value| Mut {
value, value,
ticks: self.ticks, ticks: self.ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: self.changed_by, changed_by: self.changed_by,
}) })
} }
@ -600,7 +600,7 @@ impl<'w> From<TicksMut<'w>> for Ticks<'w> {
pub struct Res<'w, T: ?Sized + Resource> { pub struct Res<'w, T: ?Sized + Resource> {
pub(crate) value: &'w T, pub(crate) value: &'w T,
pub(crate) ticks: Ticks<'w>, pub(crate) ticks: Ticks<'w>,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub(crate) changed_by: &'static Location<'static>, pub(crate) changed_by: &'static Location<'static>,
} }
@ -614,7 +614,7 @@ impl<'w, T: Resource> Res<'w, T> {
Self { Self {
value: this.value, value: this.value,
ticks: this.ticks.clone(), ticks: this.ticks.clone(),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: this.changed_by, changed_by: this.changed_by,
} }
} }
@ -632,7 +632,7 @@ impl<'w, T: Resource> From<ResMut<'w, T>> for Res<'w, T> {
Self { Self {
value: res.value, value: res.value,
ticks: res.ticks.into(), ticks: res.ticks.into(),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: res.changed_by, changed_by: res.changed_by,
} }
} }
@ -645,7 +645,7 @@ impl<'w, T: Resource> From<Res<'w, T>> for Ref<'w, T> {
Self { Self {
value: res.value, value: res.value,
ticks: res.ticks, ticks: res.ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: res.changed_by, changed_by: res.changed_by,
} }
} }
@ -678,7 +678,7 @@ impl_debug!(Res<'w, T>, Resource);
pub struct ResMut<'w, T: ?Sized + Resource> { pub struct ResMut<'w, T: ?Sized + Resource> {
pub(crate) value: &'w mut T, pub(crate) value: &'w mut T,
pub(crate) ticks: TicksMut<'w>, pub(crate) ticks: TicksMut<'w>,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub(crate) changed_by: &'w mut &'static Location<'static>, pub(crate) changed_by: &'w mut &'static Location<'static>,
} }
@ -719,7 +719,7 @@ impl<'w, T: Resource> From<ResMut<'w, T>> for Mut<'w, T> {
Mut { Mut {
value: other.value, value: other.value,
ticks: other.ticks, ticks: other.ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: other.changed_by, changed_by: other.changed_by,
} }
} }
@ -739,7 +739,7 @@ impl<'w, T: Resource> From<ResMut<'w, T>> for Mut<'w, T> {
pub struct NonSendMut<'w, T: ?Sized + 'static> { pub struct NonSendMut<'w, T: ?Sized + 'static> {
pub(crate) value: &'w mut T, pub(crate) value: &'w mut T,
pub(crate) ticks: TicksMut<'w>, pub(crate) ticks: TicksMut<'w>,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub(crate) changed_by: &'w mut &'static Location<'static>, pub(crate) changed_by: &'w mut &'static Location<'static>,
} }
@ -755,7 +755,7 @@ impl<'w, T: 'static> From<NonSendMut<'w, T>> for Mut<'w, T> {
Mut { Mut {
value: other.value, value: other.value,
ticks: other.ticks, ticks: other.ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: other.changed_by, changed_by: other.changed_by,
} }
} }
@ -788,7 +788,7 @@ impl<'w, T: 'static> From<NonSendMut<'w, T>> for Mut<'w, T> {
pub struct Ref<'w, T: ?Sized> { pub struct Ref<'w, T: ?Sized> {
pub(crate) value: &'w T, pub(crate) value: &'w T,
pub(crate) ticks: Ticks<'w>, pub(crate) ticks: Ticks<'w>,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub(crate) changed_by: &'static Location<'static>, pub(crate) changed_by: &'static Location<'static>,
} }
@ -806,7 +806,7 @@ impl<'w, T: ?Sized> Ref<'w, T> {
Ref { Ref {
value: f(self.value), value: f(self.value),
ticks: self.ticks, ticks: self.ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: self.changed_by, changed_by: self.changed_by,
} }
} }
@ -828,7 +828,7 @@ impl<'w, T: ?Sized> Ref<'w, T> {
changed: &'w Tick, changed: &'w Tick,
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) -> Ref<'w, T> { ) -> Ref<'w, T> {
Ref { Ref {
value, value,
@ -838,7 +838,7 @@ impl<'w, T: ?Sized> Ref<'w, T> {
last_run, last_run,
this_run, this_run,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: caller, changed_by: caller,
} }
} }
@ -921,7 +921,7 @@ impl_debug!(Ref<'w, T>,);
pub struct Mut<'w, T: ?Sized> { pub struct Mut<'w, T: ?Sized> {
pub(crate) value: &'w mut T, pub(crate) value: &'w mut T,
pub(crate) ticks: TicksMut<'w>, pub(crate) ticks: TicksMut<'w>,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub(crate) changed_by: &'w mut &'static Location<'static>, pub(crate) changed_by: &'w mut &'static Location<'static>,
} }
@ -947,7 +947,7 @@ impl<'w, T: ?Sized> Mut<'w, T> {
last_changed: &'w mut Tick, last_changed: &'w mut Tick,
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
#[cfg(feature = "track_change_detection")] caller: &'w mut &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'w mut &'static Location<'static>,
) -> Self { ) -> Self {
Self { Self {
value, value,
@ -957,7 +957,7 @@ impl<'w, T: ?Sized> Mut<'w, T> {
last_run, last_run,
this_run, this_run,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: caller, changed_by: caller,
} }
} }
@ -968,7 +968,7 @@ impl<'w, T: ?Sized> From<Mut<'w, T>> for Ref<'w, T> {
Self { Self {
value: mut_ref.value, value: mut_ref.value,
ticks: mut_ref.ticks.into(), ticks: mut_ref.ticks.into(),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: mut_ref.changed_by, changed_by: mut_ref.changed_by,
} }
} }
@ -1015,7 +1015,7 @@ impl_debug!(Mut<'w, T>,);
pub struct MutUntyped<'w> { pub struct MutUntyped<'w> {
pub(crate) value: PtrMut<'w>, pub(crate) value: PtrMut<'w>,
pub(crate) ticks: TicksMut<'w>, pub(crate) ticks: TicksMut<'w>,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub(crate) changed_by: &'w mut &'static Location<'static>, pub(crate) changed_by: &'w mut &'static Location<'static>,
} }
@ -1041,7 +1041,7 @@ impl<'w> MutUntyped<'w> {
last_run: self.ticks.last_run, last_run: self.ticks.last_run,
this_run: self.ticks.this_run, this_run: self.ticks.this_run,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: self.changed_by, changed_by: self.changed_by,
} }
} }
@ -1093,7 +1093,7 @@ impl<'w> MutUntyped<'w> {
Mut { Mut {
value: f(self.value), value: f(self.value),
ticks: self.ticks, ticks: self.ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: self.changed_by, changed_by: self.changed_by,
} }
} }
@ -1108,7 +1108,7 @@ impl<'w> MutUntyped<'w> {
value: unsafe { self.value.deref_mut() }, value: unsafe { self.value.deref_mut() },
ticks: self.ticks, ticks: self.ticks,
// SAFETY: `caller` is `Aligned`. // SAFETY: `caller` is `Aligned`.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: self.changed_by, changed_by: self.changed_by,
} }
} }
@ -1135,7 +1135,7 @@ impl<'w> DetectChanges for MutUntyped<'w> {
} }
#[inline] #[inline]
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
fn changed_by(&self) -> &'static Location<'static> { fn changed_by(&self) -> &'static Location<'static> {
self.changed_by self.changed_by
} }
@ -1148,7 +1148,7 @@ impl<'w> DetectChangesMut for MutUntyped<'w> {
#[track_caller] #[track_caller]
fn set_changed(&mut self) { fn set_changed(&mut self) {
*self.ticks.changed = self.ticks.this_run; *self.ticks.changed = self.ticks.this_run;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
*self.changed_by = Location::caller(); *self.changed_by = Location::caller();
} }
@ -1158,7 +1158,7 @@ impl<'w> DetectChangesMut for MutUntyped<'w> {
#[track_caller] #[track_caller]
fn set_last_changed(&mut self, last_changed: Tick) { fn set_last_changed(&mut self, last_changed: Tick) {
*self.ticks.changed = last_changed; *self.ticks.changed = last_changed;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
*self.changed_by = Location::caller(); *self.changed_by = Location::caller();
} }
@ -1184,13 +1184,13 @@ impl<'w, T> From<Mut<'w, T>> for MutUntyped<'w> {
MutUntyped { MutUntyped {
value: value.value.into(), value: value.value.into(),
ticks: value.ticks, ticks: value.ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: value.changed_by, changed_by: value.changed_by,
} }
} }
} }
/// A type alias to [`&'static Location<'static>`](std::panic::Location) when the `track_change_detection` feature is /// A type alias to [`&'static Location<'static>`](std::panic::Location) when the `track_location` feature is
/// enabled, and the unit type `()` when it is not. /// enabled, and the unit type `()` when it is not.
/// ///
/// This is primarily used in places where `#[cfg(...)]` attributes are not allowed, such as /// This is primarily used in places where `#[cfg(...)]` attributes are not allowed, such as
@ -1198,10 +1198,10 @@ impl<'w, T> From<Mut<'w, T>> for MutUntyped<'w> {
/// `Location` at all. /// `Location` at all.
/// ///
/// Please use this type sparingly: prefer normal `#[cfg(...)]` attributes when possible. /// Please use this type sparingly: prefer normal `#[cfg(...)]` attributes when possible.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub(crate) type MaybeLocation = &'static Location<'static>; pub(crate) type MaybeLocation = &'static Location<'static>;
/// A type alias to [`&'static Location<'static>`](std::panic::Location) when the `track_change_detection` feature is /// A type alias to [`&'static Location<'static>`](std::panic::Location) when the `track_location` feature is
/// enabled, and the unit type `()` when it is not. /// enabled, and the unit type `()` when it is not.
/// ///
/// This is primarily used in places where `#[cfg(...)]` attributes are not allowed, such as /// This is primarily used in places where `#[cfg(...)]` attributes are not allowed, such as
@ -1209,36 +1209,36 @@ pub(crate) type MaybeLocation = &'static Location<'static>;
/// `Location` at all. /// `Location` at all.
/// ///
/// Please use this type sparingly: prefer normal `#[cfg(...)]` attributes when possible. /// Please use this type sparingly: prefer normal `#[cfg(...)]` attributes when possible.
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
pub(crate) type MaybeLocation = (); pub(crate) type MaybeLocation = ();
/// A type alias to `&UnsafeCell<&'static Location<'static>>` when the `track_change_detection` /// A type alias to `&UnsafeCell<&'static Location<'static>>` when the `track_location`
/// feature is enabled, and the unit type `()` when it is not. /// feature is enabled, and the unit type `()` when it is not.
/// ///
/// See [`MaybeLocation`] for further information. /// See [`MaybeLocation`] for further information.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub(crate) type MaybeUnsafeCellLocation<'a> = &'a UnsafeCell<&'static Location<'static>>; pub(crate) type MaybeUnsafeCellLocation<'a> = &'a UnsafeCell<&'static Location<'static>>;
/// A type alias to `&UnsafeCell<&'static Location<'static>>` when the `track_change_detection` /// A type alias to `&UnsafeCell<&'static Location<'static>>` when the `track_location`
/// feature is enabled, and the unit type `()` when it is not. /// feature is enabled, and the unit type `()` when it is not.
/// ///
/// See [`MaybeLocation`] for further information. /// See [`MaybeLocation`] for further information.
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
pub(crate) type MaybeUnsafeCellLocation<'a> = (); pub(crate) type MaybeUnsafeCellLocation<'a> = ();
/// A type alias to `ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>` when the /// A type alias to `ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>` when the
/// `track_change_detection` feature is enabled, and the unit type `()` when it is not. /// `track_location` feature is enabled, and the unit type `()` when it is not.
/// ///
/// See [`MaybeLocation`] for further information. /// See [`MaybeLocation`] for further information.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub(crate) type MaybeThinSlicePtrLocation<'w> = pub(crate) type MaybeThinSlicePtrLocation<'w> =
ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>; ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>;
/// A type alias to `ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>` when the /// A type alias to `ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>` when the
/// `track_change_detection` feature is enabled, and the unit type `()` when it is not. /// `track_location` feature is enabled, and the unit type `()` when it is not.
/// ///
/// See [`MaybeLocation`] for further information. /// See [`MaybeLocation`] for further information.
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
pub(crate) type MaybeThinSlicePtrLocation<'w> = (); pub(crate) type MaybeThinSlicePtrLocation<'w> = ();
#[cfg(test)] #[cfg(test)]
@ -1247,7 +1247,7 @@ mod tests {
use bevy_ptr::PtrMut; use bevy_ptr::PtrMut;
use bevy_reflect::{FromType, ReflectFromPtr}; use bevy_reflect::{FromType, ReflectFromPtr};
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use crate::{ use crate::{
@ -1379,13 +1379,13 @@ mod tests {
this_run: Tick::new(4), this_run: Tick::new(4),
}; };
let mut res = R {}; let mut res = R {};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let mut caller = Location::caller(); let mut caller = Location::caller();
let res_mut = ResMut { let res_mut = ResMut {
value: &mut res, value: &mut res,
ticks, ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: &mut caller, changed_by: &mut caller,
}; };
@ -1403,7 +1403,7 @@ mod tests {
changed: Tick::new(3), changed: Tick::new(3),
}; };
let mut res = R {}; let mut res = R {};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let mut caller = Location::caller(); let mut caller = Location::caller();
let val = Mut::new( let val = Mut::new(
@ -1412,7 +1412,7 @@ mod tests {
&mut component_ticks.changed, &mut component_ticks.changed,
Tick::new(2), // last_run Tick::new(2), // last_run
Tick::new(4), // this_run Tick::new(4), // this_run
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
&mut caller, &mut caller,
); );
@ -1433,13 +1433,13 @@ mod tests {
this_run: Tick::new(4), this_run: Tick::new(4),
}; };
let mut res = R {}; let mut res = R {};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let mut caller = Location::caller(); let mut caller = Location::caller();
let non_send_mut = NonSendMut { let non_send_mut = NonSendMut {
value: &mut res, value: &mut res,
ticks, ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: &mut caller, changed_by: &mut caller,
}; };
@ -1469,13 +1469,13 @@ mod tests {
}; };
let mut outer = Outer(0); let mut outer = Outer(0);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let mut caller = Location::caller(); let mut caller = Location::caller();
let ptr = Mut { let ptr = Mut {
value: &mut outer, value: &mut outer,
ticks, ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: &mut caller, changed_by: &mut caller,
}; };
assert!(!ptr.is_changed()); assert!(!ptr.is_changed());
@ -1559,13 +1559,13 @@ mod tests {
}; };
let mut value: i32 = 5; let mut value: i32 = 5;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let mut caller = Location::caller(); let mut caller = Location::caller();
let value = MutUntyped { let value = MutUntyped {
value: PtrMut::from(&mut value), value: PtrMut::from(&mut value),
ticks, ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: &mut caller, changed_by: &mut caller,
}; };
@ -1597,13 +1597,13 @@ mod tests {
this_run: Tick::new(4), this_run: Tick::new(4),
}; };
let mut c = C {}; let mut c = C {};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let mut caller = Location::caller(); let mut caller = Location::caller();
let mut_typed = Mut { let mut_typed = Mut {
value: &mut c, value: &mut c,
ticks, ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: &mut caller, changed_by: &mut caller,
}; };

View File

@ -19,7 +19,7 @@ use bevy_ptr::{OwningPtr, UnsafeCellDeref};
#[cfg(feature = "bevy_reflect")] #[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect; use bevy_reflect::Reflect;
use bevy_utils::{HashMap, HashSet, TypeIdMap}; use bevy_utils::{HashMap, HashSet, TypeIdMap};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use core::{ use core::{
alloc::Layout, alloc::Layout,
@ -1901,14 +1901,14 @@ pub enum RequiredComponentsError {
} }
/// A Required Component constructor. See [`Component`] for details. /// A Required Component constructor. See [`Component`] for details.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
#[derive(Clone)] #[derive(Clone)]
pub struct RequiredComponentConstructor( pub struct RequiredComponentConstructor(
pub Arc<dyn Fn(&mut Table, &mut SparseSets, Tick, TableRow, Entity, &'static Location<'static>)>, pub Arc<dyn Fn(&mut Table, &mut SparseSets, Tick, TableRow, Entity, &'static Location<'static>)>,
); );
/// A Required Component constructor. See [`Component`] for details. /// A Required Component constructor. See [`Component`] for details.
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
#[derive(Clone)] #[derive(Clone)]
pub struct RequiredComponentConstructor( pub struct RequiredComponentConstructor(
pub Arc<dyn Fn(&mut Table, &mut SparseSets, Tick, TableRow, Entity)>, pub Arc<dyn Fn(&mut Table, &mut SparseSets, Tick, TableRow, Entity)>,
@ -1931,7 +1931,7 @@ impl RequiredComponentConstructor {
change_tick: Tick, change_tick: Tick,
table_row: TableRow, table_row: TableRow,
entity: Entity, entity: Entity,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) { ) {
(self.0)( (self.0)(
table, table,
@ -1939,7 +1939,7 @@ impl RequiredComponentConstructor {
change_tick, change_tick,
table_row, table_row,
entity, entity,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -2046,7 +2046,7 @@ impl RequiredComponents {
#[cfg(feature = "portable-atomic")] #[cfg(feature = "portable-atomic")]
use alloc::boxed::Box; use alloc::boxed::Box;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
type Constructor = dyn for<'a, 'b> Fn( type Constructor = dyn for<'a, 'b> Fn(
&'a mut Table, &'a mut Table,
&'b mut SparseSets, &'b mut SparseSets,
@ -2056,7 +2056,7 @@ impl RequiredComponents {
&'static Location<'static>, &'static Location<'static>,
); );
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
type Constructor = type Constructor =
dyn for<'a, 'b> Fn(&'a mut Table, &'b mut SparseSets, Tick, TableRow, Entity); dyn for<'a, 'b> Fn(&'a mut Table, &'b mut SparseSets, Tick, TableRow, Entity);
@ -2072,7 +2072,7 @@ impl RequiredComponents {
change_tick, change_tick,
table_row, table_row,
entity, entity,
#[cfg(feature = "track_change_detection")] caller| { #[cfg(feature = "track_location")] caller| {
OwningPtr::make(constructor(), |ptr| { OwningPtr::make(constructor(), |ptr| {
// SAFETY: This will only be called in the context of `BundleInfo::write_components`, which will // SAFETY: This will only be called in the context of `BundleInfo::write_components`, which will
// pass in a valid table_row and entity requiring a C constructor // pass in a valid table_row and entity requiring a C constructor
@ -2088,7 +2088,7 @@ impl RequiredComponents {
component_id, component_id,
C::STORAGE_TYPE, C::STORAGE_TYPE,
ptr, ptr,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }

View File

@ -73,7 +73,7 @@ use alloc::{borrow::ToOwned, string::String, vec::Vec};
use core::{fmt, hash::Hash, mem, num::NonZero}; use core::{fmt, hash::Hash, mem, num::NonZero};
use log::warn; use log::warn;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
#[cfg(feature = "serialize")] #[cfg(feature = "serialize")]
@ -968,7 +968,7 @@ impl Entities {
/// Sets the source code location from which this entity has last been spawned /// Sets the source code location from which this entity has last been spawned
/// or despawned. /// or despawned.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
#[inline] #[inline]
pub(crate) fn set_spawned_or_despawned_by(&mut self, index: u32, caller: &'static Location) { pub(crate) fn set_spawned_or_despawned_by(&mut self, index: u32, caller: &'static Location) {
let meta = self let meta = self
@ -980,7 +980,7 @@ impl Entities {
/// Returns the source code location from which this entity has last been spawned /// Returns the source code location from which this entity has last been spawned
/// or despawned. Returns `None` if this entity has never existed. /// or despawned. Returns `None` if this entity has never existed.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn entity_get_spawned_or_despawned_by( pub fn entity_get_spawned_or_despawned_by(
&self, &self,
entity: Entity, entity: Entity,
@ -992,7 +992,7 @@ impl Entities {
/// Constructs a message explaining why an entity does not exists, if known. /// Constructs a message explaining why an entity does not exists, if known.
pub(crate) fn entity_does_not_exist_error_details_message(&self, _entity: Entity) -> String { pub(crate) fn entity_does_not_exist_error_details_message(&self, _entity: Entity) -> String {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
if let Some(location) = self.entity_get_spawned_or_despawned_by(_entity) { if let Some(location) = self.entity_get_spawned_or_despawned_by(_entity) {
format!("was despawned by {location}",) format!("was despawned by {location}",)
@ -1000,9 +1000,9 @@ impl Entities {
"was never spawned".to_owned() "was never spawned".to_owned()
} }
} }
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
{ {
"does not exist (enable `track_change_detection` feature for more details)".to_owned() "does not exist (enable `track_location` feature for more details)".to_owned()
} }
} }
} }
@ -1014,7 +1014,7 @@ struct EntityMeta {
/// The current location of the [`Entity`] /// The current location of the [`Entity`]
pub location: EntityLocation, pub location: EntityLocation,
/// Location of the last spawn or despawn of this entity /// Location of the last spawn or despawn of this entity
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
spawned_or_despawned_by: Option<&'static Location<'static>>, spawned_or_despawned_by: Option<&'static Location<'static>>,
} }
@ -1023,7 +1023,7 @@ impl EntityMeta {
const EMPTY: EntityMeta = EntityMeta { const EMPTY: EntityMeta = EntityMeta {
generation: NonZero::<u32>::MIN, generation: NonZero::<u32>::MIN,
location: EntityLocation::INVALID, location: EntityLocation::INVALID,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
spawned_or_despawned_by: None, spawned_or_despawned_by: None,
}; };
} }

View File

@ -1,7 +1,7 @@
use crate::{component::Component, traversal::Traversal}; use crate::{component::Component, traversal::Traversal};
#[cfg(feature = "bevy_reflect")] #[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect; use bevy_reflect::Reflect;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use core::{ use core::{
cmp::Ordering, cmp::Ordering,
@ -62,7 +62,7 @@ pub struct EventId<E: Event> {
// This value corresponds to the order in which each event was added to the world. // This value corresponds to the order in which each event was added to the world.
pub id: usize, pub id: usize,
/// The source code location that triggered this event. /// The source code location that triggered this event.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub caller: &'static Location<'static>, pub caller: &'static Location<'static>,
#[cfg_attr(feature = "bevy_reflect", reflect(ignore))] #[cfg_attr(feature = "bevy_reflect", reflect(ignore))]
pub(super) _marker: PhantomData<E>, pub(super) _marker: PhantomData<E>,

View File

@ -4,7 +4,7 @@ use bevy_ecs::{
event::{Event, EventCursor, EventId, EventInstance}, event::{Event, EventCursor, EventId, EventInstance},
system::Resource, system::Resource,
}; };
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use core::{ use core::{
marker::PhantomData, marker::PhantomData,
@ -126,7 +126,7 @@ impl<E: Event> Events<E> {
pub fn send(&mut self, event: E) -> EventId<E> { pub fn send(&mut self, event: E) -> EventId<E> {
self.send_with_caller( self.send_with_caller(
event, event,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
) )
} }
@ -134,11 +134,11 @@ impl<E: Event> Events<E> {
pub(crate) fn send_with_caller( pub(crate) fn send_with_caller(
&mut self, &mut self,
event: E, event: E,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) -> EventId<E> { ) -> EventId<E> {
let event_id = EventId { let event_id = EventId {
id: self.event_count, id: self.event_count,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
_marker: PhantomData, _marker: PhantomData,
}; };
@ -308,7 +308,7 @@ impl<E: Event> Extend<E> for Events<E> {
let events = iter.into_iter().map(|event| { let events = iter.into_iter().map(|event| {
let event_id = EventId { let event_id = EventId {
id: event_count, id: event_count,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller: Location::caller(), caller: Location::caller(),
_marker: PhantomData, _marker: PhantomData,
}; };
@ -379,7 +379,7 @@ impl<E: Event> Iterator for SendBatchIds<E> {
let result = Some(EventId { let result = Some(EventId {
id: self.last_count, id: self.last_count,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller: Location::caller(), caller: Location::caller(),
_marker: PhantomData, _marker: PhantomData,
}); });

View File

@ -1322,9 +1322,9 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> {
column.get_data_slice(table.entity_count()).into(), column.get_data_slice(table.entity_count()).into(),
column.get_added_ticks_slice(table.entity_count()).into(), column.get_added_ticks_slice(table.entity_count()).into(),
column.get_changed_ticks_slice(table.entity_count()).into(), column.get_changed_ticks_slice(table.entity_count()).into(),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
column.get_changed_by_slice(table.entity_count()).into(), column.get_changed_by_slice(table.entity_count()).into(),
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
(), (),
)); ));
// SAFETY: set_table is only called when T::STORAGE_TYPE = StorageType::Table // SAFETY: set_table is only called when T::STORAGE_TYPE = StorageType::Table
@ -1350,7 +1350,7 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> {
// SAFETY: The caller ensures `table_row` is in range. // SAFETY: The caller ensures `table_row` is in range.
let changed = unsafe { changed_ticks.get(table_row.as_usize()) }; let changed = unsafe { changed_ticks.get(table_row.as_usize()) };
// SAFETY: The caller ensures `table_row` is in range. // SAFETY: The caller ensures `table_row` is in range.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = unsafe { _callers.get(table_row.as_usize()) }; let caller = unsafe { _callers.get(table_row.as_usize()) };
Ref { Ref {
@ -1361,7 +1361,7 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> {
this_run: fetch.this_run, this_run: fetch.this_run,
last_run: fetch.last_run, last_run: fetch.last_run,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: caller.deref(), changed_by: caller.deref(),
} }
}, },
@ -1373,7 +1373,7 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> {
Ref { Ref {
value: component.deref(), value: component.deref(),
ticks: Ticks::from_tick_cells(ticks, fetch.last_run, fetch.this_run), ticks: Ticks::from_tick_cells(ticks, fetch.last_run, fetch.this_run),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref(), changed_by: _caller.deref(),
} }
}, },
@ -1521,9 +1521,9 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
column.get_data_slice(table.entity_count()).into(), column.get_data_slice(table.entity_count()).into(),
column.get_added_ticks_slice(table.entity_count()).into(), column.get_added_ticks_slice(table.entity_count()).into(),
column.get_changed_ticks_slice(table.entity_count()).into(), column.get_changed_ticks_slice(table.entity_count()).into(),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
column.get_changed_by_slice(table.entity_count()).into(), column.get_changed_by_slice(table.entity_count()).into(),
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
(), (),
)); ));
// SAFETY: set_table is only called when T::STORAGE_TYPE = StorageType::Table // SAFETY: set_table is only called when T::STORAGE_TYPE = StorageType::Table
@ -1549,7 +1549,7 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
// SAFETY: The caller ensures `table_row` is in range. // SAFETY: The caller ensures `table_row` is in range.
let changed = unsafe { changed_ticks.get(table_row.as_usize()) }; let changed = unsafe { changed_ticks.get(table_row.as_usize()) };
// SAFETY: The caller ensures `table_row` is in range. // SAFETY: The caller ensures `table_row` is in range.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = unsafe { _callers.get(table_row.as_usize()) }; let caller = unsafe { _callers.get(table_row.as_usize()) };
Mut { Mut {
@ -1560,7 +1560,7 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
this_run: fetch.this_run, this_run: fetch.this_run,
last_run: fetch.last_run, last_run: fetch.last_run,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: caller.deref_mut(), changed_by: caller.deref_mut(),
} }
}, },
@ -1572,7 +1572,7 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
Mut { Mut {
value: component.assert_unique().deref_mut(), value: component.assert_unique().deref_mut(),
ticks: TicksMut::from_tick_cells(ticks, fetch.last_run, fetch.this_run), ticks: TicksMut::from_tick_cells(ticks, fetch.last_run, fetch.this_run),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref_mut(), changed_by: _caller.deref_mut(),
} }
}, },

View File

@ -6,7 +6,7 @@ use crate::{
}; };
use alloc::string::String; use alloc::string::String;
use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref}; use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use core::{cell::UnsafeCell, mem::ManuallyDrop}; use core::{cell::UnsafeCell, mem::ManuallyDrop};
@ -30,7 +30,7 @@ pub struct ResourceData<const SEND: bool> {
id: ArchetypeComponentId, id: ArchetypeComponentId,
#[cfg(feature = "std")] #[cfg(feature = "std")]
origin_thread_id: Option<ThreadId>, origin_thread_id: Option<ThreadId>,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: UnsafeCell<&'static Location<'static>>, changed_by: UnsafeCell<&'static Location<'static>>,
} }
@ -146,9 +146,9 @@ impl<const SEND: bool> ResourceData<SEND> {
added: &self.added_ticks, added: &self.added_ticks,
changed: &self.changed_ticks, changed: &self.changed_ticks,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
&self.changed_by, &self.changed_by,
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
(), (),
) )
}) })
@ -166,7 +166,7 @@ impl<const SEND: bool> ResourceData<SEND> {
value: unsafe { ptr.assert_unique() }, value: unsafe { ptr.assert_unique() },
// SAFETY: We have exclusive access to the underlying storage. // SAFETY: We have exclusive access to the underlying storage.
ticks: unsafe { TicksMut::from_tick_cells(ticks, last_run, this_run) }, ticks: unsafe { TicksMut::from_tick_cells(ticks, last_run, this_run) },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
// SAFETY: We have exclusive access to the underlying storage. // SAFETY: We have exclusive access to the underlying storage.
changed_by: unsafe { _caller.deref_mut() }, changed_by: unsafe { _caller.deref_mut() },
}) })
@ -186,7 +186,7 @@ impl<const SEND: bool> ResourceData<SEND> {
&mut self, &mut self,
value: OwningPtr<'_>, value: OwningPtr<'_>,
change_tick: Tick, change_tick: Tick,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) { ) {
if self.is_present() { if self.is_present() {
self.validate_access(); self.validate_access();
@ -205,7 +205,7 @@ impl<const SEND: bool> ResourceData<SEND> {
*self.added_ticks.deref_mut() = change_tick; *self.added_ticks.deref_mut() = change_tick;
} }
*self.changed_ticks.deref_mut() = change_tick; *self.changed_ticks.deref_mut() = change_tick;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
*self.changed_by.deref_mut() = caller; *self.changed_by.deref_mut() = caller;
} }
@ -225,7 +225,7 @@ impl<const SEND: bool> ResourceData<SEND> {
&mut self, &mut self,
value: OwningPtr<'_>, value: OwningPtr<'_>,
change_ticks: ComponentTicks, change_ticks: ComponentTicks,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) { ) {
if self.is_present() { if self.is_present() {
self.validate_access(); self.validate_access();
@ -244,7 +244,7 @@ impl<const SEND: bool> ResourceData<SEND> {
} }
*self.added_ticks.deref_mut() = change_ticks.added; *self.added_ticks.deref_mut() = change_ticks.added;
*self.changed_ticks.deref_mut() = change_ticks.changed; *self.changed_ticks.deref_mut() = change_ticks.changed;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
*self.changed_by.deref_mut() = caller; *self.changed_by.deref_mut() = caller;
} }
@ -268,9 +268,9 @@ impl<const SEND: bool> ResourceData<SEND> {
let res = unsafe { self.data.swap_remove_and_forget_unchecked(Self::ROW) }; let res = unsafe { self.data.swap_remove_and_forget_unchecked(Self::ROW) };
// SAFETY: This function is being called through an exclusive mutable reference to Self // SAFETY: This function is being called through an exclusive mutable reference to Self
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = unsafe { *self.changed_by.deref_mut() }; let caller = unsafe { *self.changed_by.deref_mut() };
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
let caller = (); let caller = ();
// SAFETY: This function is being called through an exclusive mutable reference to Self, which // SAFETY: This function is being called through an exclusive mutable reference to Self, which
@ -392,7 +392,7 @@ impl<const SEND: bool> Resources<SEND> {
id: f(), id: f(),
#[cfg(feature = "std")] #[cfg(feature = "std")]
origin_thread_id: None, origin_thread_id: None,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: UnsafeCell::new(Location::caller()) changed_by: UnsafeCell::new(Location::caller())
} }
}) })

View File

@ -6,7 +6,7 @@ use crate::{
}; };
use alloc::{boxed::Box, vec::Vec}; use alloc::{boxed::Box, vec::Vec};
use bevy_ptr::{OwningPtr, Ptr}; use bevy_ptr::{OwningPtr, Ptr};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use core::{cell::UnsafeCell, hash::Hash, marker::PhantomData}; use core::{cell::UnsafeCell, hash::Hash, marker::PhantomData};
use nonmax::NonMaxUsize; use nonmax::NonMaxUsize;
@ -173,7 +173,7 @@ impl ComponentSparseSet {
entity: Entity, entity: Entity,
value: OwningPtr<'_>, value: OwningPtr<'_>,
change_tick: Tick, change_tick: Tick,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) { ) {
if let Some(&dense_index) = self.sparse.get(entity.index()) { if let Some(&dense_index) = self.sparse.get(entity.index()) {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -182,7 +182,7 @@ impl ComponentSparseSet {
dense_index, dense_index,
value, value,
change_tick, change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} else { } else {
@ -190,7 +190,7 @@ impl ComponentSparseSet {
self.dense.push( self.dense.push(
value, value,
ComponentTicks::new(change_tick), ComponentTicks::new(change_tick),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
self.sparse self.sparse
@ -253,9 +253,9 @@ impl ComponentSparseSet {
added: self.dense.get_added_tick_unchecked(dense_index), added: self.dense.get_added_tick_unchecked(dense_index),
changed: self.dense.get_changed_tick_unchecked(dense_index), changed: self.dense.get_changed_tick_unchecked(dense_index),
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.dense.get_changed_by_unchecked(dense_index), self.dense.get_changed_by_unchecked(dense_index),
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
(), (),
)) ))
} }
@ -301,7 +301,7 @@ impl ComponentSparseSet {
/// ///
/// Returns `None` if `entity` does not have a component in the sparse set. /// Returns `None` if `entity` does not have a component in the sparse set.
#[inline] #[inline]
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn get_changed_by( pub fn get_changed_by(
&self, &self,
entity: Entity, entity: Entity,

View File

@ -17,7 +17,7 @@ pub struct ThinColumn {
pub(super) data: BlobArray, pub(super) data: BlobArray,
pub(super) added_ticks: ThinArrayPtr<UnsafeCell<Tick>>, pub(super) added_ticks: ThinArrayPtr<UnsafeCell<Tick>>,
pub(super) changed_ticks: ThinArrayPtr<UnsafeCell<Tick>>, pub(super) changed_ticks: ThinArrayPtr<UnsafeCell<Tick>>,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub(super) changed_by: ThinArrayPtr<UnsafeCell<&'static Location<'static>>>, pub(super) changed_by: ThinArrayPtr<UnsafeCell<&'static Location<'static>>>,
} }
@ -31,7 +31,7 @@ impl ThinColumn {
}, },
added_ticks: ThinArrayPtr::with_capacity(capacity), added_ticks: ThinArrayPtr::with_capacity(capacity),
changed_ticks: ThinArrayPtr::with_capacity(capacity), changed_ticks: ThinArrayPtr::with_capacity(capacity),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: ThinArrayPtr::with_capacity(capacity), changed_by: ThinArrayPtr::with_capacity(capacity),
} }
} }
@ -54,7 +54,7 @@ impl ThinColumn {
.swap_remove_unchecked_nonoverlapping(row.as_usize(), last_element_index); .swap_remove_unchecked_nonoverlapping(row.as_usize(), last_element_index);
self.changed_ticks self.changed_ticks
.swap_remove_unchecked_nonoverlapping(row.as_usize(), last_element_index); .swap_remove_unchecked_nonoverlapping(row.as_usize(), last_element_index);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by self.changed_by
.swap_remove_unchecked_nonoverlapping(row.as_usize(), last_element_index); .swap_remove_unchecked_nonoverlapping(row.as_usize(), last_element_index);
} }
@ -76,7 +76,7 @@ impl ThinColumn {
.swap_remove_and_drop_unchecked(row.as_usize(), last_element_index); .swap_remove_and_drop_unchecked(row.as_usize(), last_element_index);
self.changed_ticks self.changed_ticks
.swap_remove_and_drop_unchecked(row.as_usize(), last_element_index); .swap_remove_and_drop_unchecked(row.as_usize(), last_element_index);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by self.changed_by
.swap_remove_and_drop_unchecked(row.as_usize(), last_element_index); .swap_remove_and_drop_unchecked(row.as_usize(), last_element_index);
} }
@ -99,7 +99,7 @@ impl ThinColumn {
.swap_remove_unchecked(row.as_usize(), last_element_index); .swap_remove_unchecked(row.as_usize(), last_element_index);
self.changed_ticks self.changed_ticks
.swap_remove_unchecked(row.as_usize(), last_element_index); .swap_remove_unchecked(row.as_usize(), last_element_index);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by self.changed_by
.swap_remove_unchecked(row.as_usize(), last_element_index); .swap_remove_unchecked(row.as_usize(), last_element_index);
} }
@ -117,7 +117,7 @@ impl ThinColumn {
self.data.realloc(current_capacity, new_capacity); self.data.realloc(current_capacity, new_capacity);
self.added_ticks.realloc(current_capacity, new_capacity); self.added_ticks.realloc(current_capacity, new_capacity);
self.changed_ticks.realloc(current_capacity, new_capacity); self.changed_ticks.realloc(current_capacity, new_capacity);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by.realloc(current_capacity, new_capacity); self.changed_by.realloc(current_capacity, new_capacity);
} }
@ -127,7 +127,7 @@ impl ThinColumn {
self.data.alloc(new_capacity); self.data.alloc(new_capacity);
self.added_ticks.alloc(new_capacity); self.added_ticks.alloc(new_capacity);
self.changed_ticks.alloc(new_capacity); self.changed_ticks.alloc(new_capacity);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by.alloc(new_capacity); self.changed_by.alloc(new_capacity);
} }
@ -144,7 +144,7 @@ impl ThinColumn {
row: TableRow, row: TableRow,
data: OwningPtr<'_>, data: OwningPtr<'_>,
tick: Tick, tick: Tick,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) { ) {
self.data.initialize_unchecked(row.as_usize(), data); self.data.initialize_unchecked(row.as_usize(), data);
*self.added_ticks.get_unchecked_mut(row.as_usize()).get_mut() = tick; *self.added_ticks.get_unchecked_mut(row.as_usize()).get_mut() = tick;
@ -152,7 +152,7 @@ impl ThinColumn {
.changed_ticks .changed_ticks
.get_unchecked_mut(row.as_usize()) .get_unchecked_mut(row.as_usize())
.get_mut() = tick; .get_mut() = tick;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
*self.changed_by.get_unchecked_mut(row.as_usize()).get_mut() = caller; *self.changed_by.get_unchecked_mut(row.as_usize()).get_mut() = caller;
} }
@ -169,14 +169,14 @@ impl ThinColumn {
row: TableRow, row: TableRow,
data: OwningPtr<'_>, data: OwningPtr<'_>,
change_tick: Tick, change_tick: Tick,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) { ) {
self.data.replace_unchecked(row.as_usize(), data); self.data.replace_unchecked(row.as_usize(), data);
*self *self
.changed_ticks .changed_ticks
.get_unchecked_mut(row.as_usize()) .get_unchecked_mut(row.as_usize())
.get_mut() = change_tick; .get_mut() = change_tick;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
*self.changed_by.get_unchecked_mut(row.as_usize()).get_mut() = caller; *self.changed_by.get_unchecked_mut(row.as_usize()).get_mut() = caller;
} }
@ -218,11 +218,11 @@ impl ThinColumn {
.swap_remove_unchecked(src_row.as_usize(), other_last_element_index); .swap_remove_unchecked(src_row.as_usize(), other_last_element_index);
self.changed_ticks self.changed_ticks
.initialize_unchecked(dst_row.as_usize(), changed_tick); .initialize_unchecked(dst_row.as_usize(), changed_tick);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let changed_by = other let changed_by = other
.changed_by .changed_by
.swap_remove_unchecked(src_row.as_usize(), other_last_element_index); .swap_remove_unchecked(src_row.as_usize(), other_last_element_index);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by self.changed_by
.initialize_unchecked(dst_row.as_usize(), changed_by); .initialize_unchecked(dst_row.as_usize(), changed_by);
} }
@ -258,7 +258,7 @@ impl ThinColumn {
self.added_ticks.clear_elements(len); self.added_ticks.clear_elements(len);
self.changed_ticks.clear_elements(len); self.changed_ticks.clear_elements(len);
self.data.clear(len); self.data.clear(len);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by.clear_elements(len); self.changed_by.clear_elements(len);
} }
@ -273,7 +273,7 @@ impl ThinColumn {
self.added_ticks.drop(cap, len); self.added_ticks.drop(cap, len);
self.changed_ticks.drop(cap, len); self.changed_ticks.drop(cap, len);
self.data.drop(cap, len); self.data.drop(cap, len);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by.drop(cap, len); self.changed_by.drop(cap, len);
} }
@ -285,7 +285,7 @@ impl ThinColumn {
pub(crate) unsafe fn drop_last_component(&mut self, last_element_index: usize) { pub(crate) unsafe fn drop_last_component(&mut self, last_element_index: usize) {
core::ptr::drop_in_place(self.added_ticks.get_unchecked_raw(last_element_index)); core::ptr::drop_in_place(self.added_ticks.get_unchecked_raw(last_element_index));
core::ptr::drop_in_place(self.changed_ticks.get_unchecked_raw(last_element_index)); core::ptr::drop_in_place(self.changed_ticks.get_unchecked_raw(last_element_index));
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
core::ptr::drop_in_place(self.changed_by.get_unchecked_raw(last_element_index)); core::ptr::drop_in_place(self.changed_by.get_unchecked_raw(last_element_index));
self.data.drop_last_element(last_element_index); self.data.drop_last_element(last_element_index);
} }
@ -319,7 +319,7 @@ impl ThinColumn {
/// ///
/// # Safety /// # Safety
/// - `len` must match the actual length of this column (number of elements stored) /// - `len` must match the actual length of this column (number of elements stored)
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub unsafe fn get_changed_by_slice( pub unsafe fn get_changed_by_slice(
&self, &self,
len: usize, len: usize,
@ -343,7 +343,7 @@ pub struct Column {
pub(super) data: BlobVec, pub(super) data: BlobVec,
pub(super) added_ticks: Vec<UnsafeCell<Tick>>, pub(super) added_ticks: Vec<UnsafeCell<Tick>>,
pub(super) changed_ticks: Vec<UnsafeCell<Tick>>, pub(super) changed_ticks: Vec<UnsafeCell<Tick>>,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: Vec<UnsafeCell<&'static Location<'static>>>, changed_by: Vec<UnsafeCell<&'static Location<'static>>>,
} }
@ -356,7 +356,7 @@ impl Column {
data: unsafe { BlobVec::new(component_info.layout(), component_info.drop(), capacity) }, data: unsafe { BlobVec::new(component_info.layout(), component_info.drop(), capacity) },
added_ticks: Vec::with_capacity(capacity), added_ticks: Vec::with_capacity(capacity),
changed_ticks: Vec::with_capacity(capacity), changed_ticks: Vec::with_capacity(capacity),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: Vec::with_capacity(capacity), changed_by: Vec::with_capacity(capacity),
} }
} }
@ -378,7 +378,7 @@ impl Column {
row: TableRow, row: TableRow,
data: OwningPtr<'_>, data: OwningPtr<'_>,
change_tick: Tick, change_tick: Tick,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) { ) {
debug_assert!(row.as_usize() < self.len()); debug_assert!(row.as_usize() < self.len());
self.data.replace_unchecked(row.as_usize(), data); self.data.replace_unchecked(row.as_usize(), data);
@ -386,7 +386,7 @@ impl Column {
.changed_ticks .changed_ticks
.get_unchecked_mut(row.as_usize()) .get_unchecked_mut(row.as_usize())
.get_mut() = change_tick; .get_mut() = change_tick;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
*self.changed_by.get_unchecked_mut(row.as_usize()).get_mut() = caller; *self.changed_by.get_unchecked_mut(row.as_usize()).get_mut() = caller;
} }
@ -418,7 +418,7 @@ impl Column {
self.data.swap_remove_and_drop_unchecked(row.as_usize()); self.data.swap_remove_and_drop_unchecked(row.as_usize());
self.added_ticks.swap_remove(row.as_usize()); self.added_ticks.swap_remove(row.as_usize());
self.changed_ticks.swap_remove(row.as_usize()); self.changed_ticks.swap_remove(row.as_usize());
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by.swap_remove(row.as_usize()); self.changed_by.swap_remove(row.as_usize());
} }
@ -442,9 +442,9 @@ impl Column {
let data = self.data.swap_remove_and_forget_unchecked(row.as_usize()); let data = self.data.swap_remove_and_forget_unchecked(row.as_usize());
let added = self.added_ticks.swap_remove(row.as_usize()).into_inner(); let added = self.added_ticks.swap_remove(row.as_usize()).into_inner();
let changed = self.changed_ticks.swap_remove(row.as_usize()).into_inner(); let changed = self.changed_ticks.swap_remove(row.as_usize()).into_inner();
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = self.changed_by.swap_remove(row.as_usize()).into_inner(); let caller = self.changed_by.swap_remove(row.as_usize()).into_inner();
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
let caller = (); let caller = ();
(data, ComponentTicks { added, changed }, caller) (data, ComponentTicks { added, changed }, caller)
} }
@ -457,12 +457,12 @@ impl Column {
&mut self, &mut self,
ptr: OwningPtr<'_>, ptr: OwningPtr<'_>,
ticks: ComponentTicks, ticks: ComponentTicks,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, #[cfg(feature = "track_location")] caller: &'static Location<'static>,
) { ) {
self.data.push(ptr); self.data.push(ptr);
self.added_ticks.push(UnsafeCell::new(ticks.added)); self.added_ticks.push(UnsafeCell::new(ticks.added));
self.changed_ticks.push(UnsafeCell::new(ticks.changed)); self.changed_ticks.push(UnsafeCell::new(ticks.changed));
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by.push(UnsafeCell::new(caller)); self.changed_by.push(UnsafeCell::new(caller));
} }
@ -644,7 +644,7 @@ impl Column {
self.data.clear(); self.data.clear();
self.added_ticks.clear(); self.added_ticks.clear();
self.changed_ticks.clear(); self.changed_ticks.clear();
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.changed_by.clear(); self.changed_by.clear();
} }
@ -666,7 +666,7 @@ impl Column {
/// Users of this API must ensure that accesses to each individual element /// Users of this API must ensure that accesses to each individual element
/// adhere to the safety invariants of [`UnsafeCell`]. /// adhere to the safety invariants of [`UnsafeCell`].
#[inline] #[inline]
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn get_changed_by(&self, row: TableRow) -> Option<&UnsafeCell<&'static Location<'static>>> { pub fn get_changed_by(&self, row: TableRow) -> Option<&UnsafeCell<&'static Location<'static>>> {
self.changed_by.get(row.as_usize()) self.changed_by.get(row.as_usize())
} }
@ -678,7 +678,7 @@ impl Column {
/// # Safety /// # Safety
/// `row` must be within the range `[0, self.len())`. /// `row` must be within the range `[0, self.len())`.
#[inline] #[inline]
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub unsafe fn get_changed_by_unchecked( pub unsafe fn get_changed_by_unchecked(
&self, &self,
row: TableRow, row: TableRow,

View File

@ -9,7 +9,7 @@ use alloc::{boxed::Box, vec, vec::Vec};
use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref}; use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref};
use bevy_utils::HashMap; use bevy_utils::HashMap;
pub use column::*; pub use column::*;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use core::{ use core::{
alloc::Layout, alloc::Layout,
@ -390,7 +390,7 @@ impl Table {
} }
/// Fetches the calling locations that last changed the each component /// Fetches the calling locations that last changed the each component
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn get_changed_by_slice_for( pub fn get_changed_by_slice_for(
&self, &self,
component_id: ComponentId, component_id: ComponentId,
@ -433,7 +433,7 @@ impl Table {
} }
/// Get the specific calling location that changed the component matching `component_id` in `row` /// Get the specific calling location that changed the component matching `component_id` in `row`
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn get_changed_by( pub fn get_changed_by(
&self, &self,
component_id: ComponentId, component_id: ComponentId,
@ -571,7 +571,7 @@ impl Table {
.initialize_unchecked(len, UnsafeCell::new(Tick::new(0))); .initialize_unchecked(len, UnsafeCell::new(Tick::new(0)));
col.changed_ticks col.changed_ticks
.initialize_unchecked(len, UnsafeCell::new(Tick::new(0))); .initialize_unchecked(len, UnsafeCell::new(Tick::new(0)));
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
col.changed_by col.changed_by
.initialize_unchecked(len, UnsafeCell::new(Location::caller())); .initialize_unchecked(len, UnsafeCell::new(Location::caller()));
} }
@ -822,7 +822,7 @@ mod tests {
ptr::OwningPtr, ptr::OwningPtr,
storage::{Storages, TableBuilder, TableId, TableRow, Tables}, storage::{Storages, TableBuilder, TableId, TableRow, Tables},
}; };
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
#[derive(Component)] #[derive(Component)]
@ -860,7 +860,7 @@ mod tests {
row, row,
value_ptr, value_ptr,
Tick::new(0), Tick::new(0),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
); );
}); });

View File

@ -332,12 +332,12 @@ impl<'w, 's> Commands<'w, 's> {
#[deprecated(since = "0.15.0", note = "use Commands::spawn instead")] #[deprecated(since = "0.15.0", note = "use Commands::spawn instead")]
#[track_caller] #[track_caller]
pub fn get_or_spawn(&mut self, entity: Entity) -> EntityCommands { pub fn get_or_spawn(&mut self, entity: Entity) -> EntityCommands {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
self.queue(move |world: &mut World| { self.queue(move |world: &mut World| {
world.get_or_spawn_with_caller( world.get_or_spawn_with_caller(
entity, entity,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
}); });
@ -547,13 +547,13 @@ impl<'w, 's> Commands<'w, 's> {
I: IntoIterator + Send + Sync + 'static, I: IntoIterator + Send + Sync + 'static,
I::Item: Bundle, I::Item: Bundle,
{ {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
self.queue(move |world: &mut World| { self.queue(move |world: &mut World| {
SpawnBatchIter::new( SpawnBatchIter::new(
world, world,
bundles_iter.into_iter(), bundles_iter.into_iter(),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
}); });
@ -633,12 +633,12 @@ impl<'w, 's> Commands<'w, 's> {
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static, I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle, B: Bundle,
{ {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
self.queue(move |world: &mut World| { self.queue(move |world: &mut World| {
if let Err(invalid_entities) = world.insert_or_spawn_batch_with_caller( if let Err(invalid_entities) = world.insert_or_spawn_batch_with_caller(
bundles_iter, bundles_iter,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
) { ) {
error!( error!(
@ -812,12 +812,12 @@ impl<'w, 's> Commands<'w, 's> {
/// ``` /// ```
#[track_caller] #[track_caller]
pub fn insert_resource<R: Resource>(&mut self, resource: R) { pub fn insert_resource<R: Resource>(&mut self, resource: R) {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
self.queue(move |world: &mut World| { self.queue(move |world: &mut World| {
world.insert_resource_with_caller( world.insert_resource_with_caller(
resource, resource,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
}); });
@ -1060,13 +1060,13 @@ impl<'w, 's> Commands<'w, 's> {
/// [`EventWriter`]: crate::event::EventWriter /// [`EventWriter`]: crate::event::EventWriter
#[track_caller] #[track_caller]
pub fn send_event<E: Event>(&mut self, event: E) -> &mut Self { pub fn send_event<E: Event>(&mut self, event: E) -> &mut Self {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
self.queue(move |world: &mut World| { self.queue(move |world: &mut World| {
let mut events = world.resource_mut::<Events<E>>(); let mut events = world.resource_mut::<Events<E>>();
events.send_with_caller( events.send_with_caller(
event, event,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
}); });
@ -2142,7 +2142,7 @@ impl<'a, T: Component> EntityEntryCommands<'a, T> {
entity.insert_with_caller( entity.insert_with_caller(
value, value,
InsertMode::Keep, InsertMode::Keep,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} else { } else {
@ -2190,13 +2190,13 @@ where
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static, I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle, B: Bundle,
{ {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
move |world: &mut World| { move |world: &mut World| {
world.insert_batch_with_caller( world.insert_batch_with_caller(
batch, batch,
mode, mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -2212,13 +2212,13 @@ where
I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static, I: IntoIterator<Item = (Entity, B)> + Send + Sync + 'static,
B: Bundle, B: Bundle,
{ {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
move |world: &mut World| { move |world: &mut World| {
world.try_insert_batch_with_caller( world.try_insert_batch_with_caller(
batch, batch,
mode, mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -2248,7 +2248,7 @@ fn insert<T: Bundle>(bundle: T, mode: InsertMode) -> impl EntityCommand {
entity.insert_with_caller( entity.insert_with_caller(
bundle, bundle,
mode, mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} else { } else {
@ -2261,14 +2261,14 @@ fn insert<T: Bundle>(bundle: T, mode: InsertMode) -> impl EntityCommand {
/// Does nothing if the entity does not exist. /// Does nothing if the entity does not exist.
#[track_caller] #[track_caller]
fn try_insert(bundle: impl Bundle, mode: InsertMode) -> impl EntityCommand { fn try_insert(bundle: impl Bundle, mode: InsertMode) -> impl EntityCommand {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
move |entity: Entity, world: &mut World| { move |entity: Entity, world: &mut World| {
if let Ok(mut entity) = world.get_entity_mut(entity) { if let Ok(mut entity) = world.get_entity_mut(entity) {
entity.insert_with_caller( entity.insert_with_caller(
bundle, bundle,
mode, mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }

View File

@ -20,7 +20,7 @@ use alloc::{borrow::ToOwned, boxed::Box, vec::Vec};
pub use bevy_ecs_macros::{Resource, SystemParam}; pub use bevy_ecs_macros::{Resource, SystemParam};
use bevy_ptr::UnsafeCellDeref; use bevy_ptr::UnsafeCellDeref;
use bevy_utils::synccell::SyncCell; use bevy_utils::synccell::SyncCell;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use core::{ use core::{
any::Any, any::Any,
@ -914,7 +914,7 @@ unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
last_run: system_meta.last_run, last_run: system_meta.last_run,
this_run: change_tick, this_run: change_tick,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref(), changed_by: _caller.deref(),
} }
} }
@ -949,7 +949,7 @@ unsafe impl<'a, T: Resource> SystemParam for Option<Res<'a, T>> {
last_run: system_meta.last_run, last_run: system_meta.last_run,
this_run: change_tick, this_run: change_tick,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref(), changed_by: _caller.deref(),
}) })
} }
@ -1027,7 +1027,7 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
last_run: system_meta.last_run, last_run: system_meta.last_run,
this_run: change_tick, this_run: change_tick,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: value.changed_by, changed_by: value.changed_by,
} }
} }
@ -1059,7 +1059,7 @@ unsafe impl<'a, T: Resource> SystemParam for Option<ResMut<'a, T>> {
last_run: system_meta.last_run, last_run: system_meta.last_run,
this_run: change_tick, this_run: change_tick,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: value.changed_by, changed_by: value.changed_by,
}) })
} }
@ -1448,7 +1448,7 @@ pub struct NonSend<'w, T: 'static> {
ticks: ComponentTicks, ticks: ComponentTicks,
last_run: Tick, last_run: Tick,
this_run: Tick, this_run: Tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: &'static Location<'static>, changed_by: &'static Location<'static>,
} }
@ -1476,7 +1476,7 @@ impl<'w, T: 'static> NonSend<'w, T> {
} }
/// The location that last caused this to change. /// The location that last caused this to change.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn changed_by(&self) -> &'static Location<'static> { pub fn changed_by(&self) -> &'static Location<'static> {
self.changed_by self.changed_by
} }
@ -1499,7 +1499,7 @@ impl<'a, T> From<NonSendMut<'a, T>> for NonSend<'a, T> {
}, },
this_run: nsm.ticks.this_run, this_run: nsm.ticks.this_run,
last_run: nsm.ticks.last_run, last_run: nsm.ticks.last_run,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: nsm.changed_by, changed_by: nsm.changed_by,
} }
} }
@ -1575,7 +1575,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
ticks: ticks.read(), ticks: ticks.read(),
last_run: system_meta.last_run, last_run: system_meta.last_run,
this_run: change_tick, this_run: change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref(), changed_by: _caller.deref(),
} }
} }
@ -1607,7 +1607,7 @@ unsafe impl<T: 'static> SystemParam for Option<NonSend<'_, T>> {
ticks: ticks.read(), ticks: ticks.read(),
last_run: system_meta.last_run, last_run: system_meta.last_run,
this_run: change_tick, this_run: change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref(), changed_by: _caller.deref(),
}) })
} }
@ -1683,7 +1683,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
NonSendMut { NonSendMut {
value: ptr.assert_unique().deref_mut(), value: ptr.assert_unique().deref_mut(),
ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick), ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref_mut(), changed_by: _caller.deref_mut(),
} }
} }
@ -1710,7 +1710,7 @@ unsafe impl<'a, T: 'static> SystemParam for Option<NonSendMut<'a, T>> {
.map(|(ptr, ticks, _caller)| NonSendMut { .map(|(ptr, ticks, _caller)| NonSendMut {
value: ptr.assert_unique().deref_mut(), value: ptr.assert_unique().deref_mut(),
ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick), ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref_mut(), changed_by: _caller.deref_mut(),
}) })
} }

View File

@ -17,7 +17,7 @@ use crate::{
use alloc::vec::Vec; use alloc::vec::Vec;
use bevy_ptr::{OwningPtr, Ptr}; use bevy_ptr::{OwningPtr, Ptr};
use bevy_utils::{HashMap, HashSet}; use bevy_utils::{HashMap, HashSet};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use core::{ use core::{
any::TypeId, any::TypeId,
@ -285,7 +285,7 @@ impl<'w> EntityRef<'w> {
} }
/// Returns the source code location from which this entity has been spawned. /// Returns the source code location from which this entity has been spawned.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn spawned_by(&self) -> &'static Location<'static> { pub fn spawned_by(&self) -> &'static Location<'static> {
self.0.spawned_by() self.0.spawned_by()
} }
@ -859,7 +859,7 @@ impl<'w> EntityMut<'w> {
} }
/// Returns the source code location from which this entity has been spawned. /// Returns the source code location from which this entity has been spawned.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn spawned_by(&self) -> &'static Location<'static> { pub fn spawned_by(&self) -> &'static Location<'static> {
self.0.spawned_by() self.0.spawned_by()
} }
@ -1461,7 +1461,7 @@ impl<'w> EntityWorldMut<'w> {
self.insert_with_caller( self.insert_with_caller(
bundle, bundle,
InsertMode::Replace, InsertMode::Replace,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
) )
} }
@ -1479,7 +1479,7 @@ impl<'w> EntityWorldMut<'w> {
self.insert_with_caller( self.insert_with_caller(
bundle, bundle,
InsertMode::Keep, InsertMode::Keep,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
) )
} }
@ -1491,7 +1491,7 @@ impl<'w> EntityWorldMut<'w> {
&mut self, &mut self,
bundle: T, bundle: T,
mode: InsertMode, mode: InsertMode,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) -> &mut Self { ) -> &mut Self {
self.assert_not_despawned(); self.assert_not_despawned();
let change_tick = self.world.change_tick(); let change_tick = self.world.change_tick();
@ -1500,7 +1500,7 @@ impl<'w> EntityWorldMut<'w> {
self.location = self.location =
// SAFETY: location matches current entity. `T` matches `bundle_info` // SAFETY: location matches current entity. `T` matches `bundle_info`
unsafe { unsafe {
bundle_inserter.insert(self.entity, self.location, bundle, mode, #[cfg(feature = "track_change_detection")] caller) bundle_inserter.insert(self.entity, self.location, bundle, mode, #[cfg(feature = "track_location")] caller)
}; };
self.world.flush(); self.world.flush();
self.update_location(); self.update_location();
@ -2034,14 +2034,14 @@ impl<'w> EntityWorldMut<'w> {
#[track_caller] #[track_caller]
pub fn despawn(self) { pub fn despawn(self) {
self.despawn_with_caller( self.despawn_with_caller(
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
); );
} }
pub(crate) fn despawn_with_caller( pub(crate) fn despawn_with_caller(
self, self,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) { ) {
self.assert_not_despawned(); self.assert_not_despawned();
let world = self.world; let world = self.world;
@ -2132,7 +2132,7 @@ impl<'w> EntityWorldMut<'w> {
} }
world.flush(); world.flush();
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
{ {
// SAFETY: No structural changes // SAFETY: No structural changes
unsafe { unsafe {
@ -2468,7 +2468,7 @@ impl<'w> EntityWorldMut<'w> {
} }
/// Returns the source code location from which this entity has last been spawned. /// Returns the source code location from which this entity has last been spawned.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn spawned_by(&self) -> &'static Location<'static> { pub fn spawned_by(&self) -> &'static Location<'static> {
self.world() self.world()
.entities() .entities()
@ -3010,7 +3010,7 @@ impl<'w> FilteredEntityRef<'w> {
} }
/// Returns the source code location from which this entity has been spawned. /// Returns the source code location from which this entity has been spawned.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn spawned_by(&self) -> &'static Location<'static> { pub fn spawned_by(&self) -> &'static Location<'static> {
self.entity.spawned_by() self.entity.spawned_by()
} }
@ -3375,7 +3375,7 @@ impl<'w> FilteredEntityMut<'w> {
} }
/// Returns the source code location from which this entity has last been spawned. /// Returns the source code location from which this entity has last been spawned.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn spawned_by(&self) -> &'static Location<'static> { pub fn spawned_by(&self) -> &'static Location<'static> {
self.entity.spawned_by() self.entity.spawned_by()
} }
@ -3556,7 +3556,7 @@ where
} }
/// Returns the source code location from which this entity has been spawned. /// Returns the source code location from which this entity has been spawned.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn spawned_by(&self) -> &'static Location<'static> { pub fn spawned_by(&self) -> &'static Location<'static> {
self.entity.spawned_by() self.entity.spawned_by()
} }
@ -3715,7 +3715,7 @@ where
} }
/// Returns the source code location from which this entity has been spawned. /// Returns the source code location from which this entity has been spawned.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn spawned_by(&self) -> &'static Location<'static> { pub fn spawned_by(&self) -> &'static Location<'static> {
self.entity.spawned_by() self.entity.spawned_by()
} }
@ -3814,7 +3814,7 @@ unsafe fn insert_dynamic_bundle<
location, location,
bundle, bundle,
InsertMode::Replace, InsertMode::Replace,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
) )
} }
@ -4117,9 +4117,9 @@ unsafe impl DynamicComponentFetch for &'_ HashSet<ComponentId> {
mod tests { mod tests {
use bevy_ptr::{OwningPtr, Ptr}; use bevy_ptr::{OwningPtr, Ptr};
use core::panic::AssertUnwindSafe; use core::panic::AssertUnwindSafe;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use std::sync::OnceLock; use std::sync::OnceLock;
use crate::{ use crate::{
@ -5401,7 +5401,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
fn update_despawned_by_after_observers() { fn update_despawned_by_after_observers() {
let mut world = World::new(); let mut world = World::new();

View File

@ -6,7 +6,7 @@ use crate::{
world::{unsafe_world_cell::UnsafeWorldCell, World}, world::{unsafe_world_cell::UnsafeWorldCell, World},
}; };
use bevy_ptr::Ptr; use bevy_ptr::Ptr;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use bevy_ptr::UnsafeCellDeref; use bevy_ptr::UnsafeCellDeref;
/// Provides read-only access to a set of [`Resource`]s defined by the contained [`Access`]. /// Provides read-only access to a set of [`Resource`]s defined by the contained [`Access`].
@ -165,7 +165,7 @@ impl<'w, 's> FilteredResources<'w, 's> {
value: unsafe { value.deref() }, value: unsafe { value.deref() },
// SAFETY: We have read access to the resource, so no mutable reference can exist. // SAFETY: We have read access to the resource, so no mutable reference can exist.
ticks: unsafe { Ticks::from_tick_cells(ticks, self.last_run, self.this_run) }, ticks: unsafe { Ticks::from_tick_cells(ticks, self.last_run, self.this_run) },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
// SAFETY: We have read access to the resource, so no mutable reference can exist. // SAFETY: We have read access to the resource, so no mutable reference can exist.
changed_by: unsafe { _caller.deref() }, changed_by: unsafe { _caller.deref() },
}, },
@ -483,7 +483,7 @@ impl<'w, 's> FilteredResourcesMut<'w, 's> {
value: unsafe { value.assert_unique() }, value: unsafe { value.assert_unique() },
// SAFETY: We have exclusive access to the underlying storage. // SAFETY: We have exclusive access to the underlying storage.
ticks: unsafe { TicksMut::from_tick_cells(ticks, self.last_run, self.this_run) }, ticks: unsafe { TicksMut::from_tick_cells(ticks, self.last_run, self.this_run) },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
// SAFETY: We have exclusive access to the underlying storage. // SAFETY: We have exclusive access to the underlying storage.
changed_by: unsafe { _caller.deref_mut() }, changed_by: unsafe { _caller.deref_mut() },
}, },

View File

@ -62,7 +62,7 @@ use core::sync::atomic::{AtomicU32, Ordering};
#[cfg(feature = "portable-atomic")] #[cfg(feature = "portable-atomic")]
use portable_atomic::{AtomicU32, Ordering}; use portable_atomic::{AtomicU32, Ordering};
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use bevy_ptr::UnsafeCellDeref; use bevy_ptr::UnsafeCellDeref;
use core::panic::Location; use core::panic::Location;
@ -891,7 +891,7 @@ impl World {
pub fn get_or_spawn(&mut self, entity: Entity) -> Option<EntityWorldMut> { pub fn get_or_spawn(&mut self, entity: Entity) -> Option<EntityWorldMut> {
self.get_or_spawn_with_caller( self.get_or_spawn_with_caller(
entity, entity,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
) )
} }
@ -900,7 +900,7 @@ impl World {
pub(crate) fn get_or_spawn_with_caller( pub(crate) fn get_or_spawn_with_caller(
&mut self, &mut self,
entity: Entity, entity: Entity,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) -> Option<EntityWorldMut> { ) -> Option<EntityWorldMut> {
self.flush(); self.flush();
match self.entities.alloc_at_without_replacement(entity) { match self.entities.alloc_at_without_replacement(entity) {
@ -913,7 +913,7 @@ impl World {
Some(unsafe { Some(unsafe {
self.spawn_at_empty_internal( self.spawn_at_empty_internal(
entity, entity,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
) )
}) })
@ -1083,7 +1083,7 @@ impl World {
unsafe { unsafe {
self.spawn_at_empty_internal( self.spawn_at_empty_internal(
entity, entity,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
) )
} }
@ -1161,13 +1161,13 @@ impl World {
bundle_spawner.spawn_non_existent( bundle_spawner.spawn_non_existent(
entity, entity,
bundle, bundle,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
) )
} }
}; };
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.entities self.entities
.set_spawned_or_despawned_by(entity.index(), Location::caller()); .set_spawned_or_despawned_by(entity.index(), Location::caller());
@ -1180,7 +1180,7 @@ impl World {
unsafe fn spawn_at_empty_internal( unsafe fn spawn_at_empty_internal(
&mut self, &mut self,
entity: Entity, entity: Entity,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) -> EntityWorldMut { ) -> EntityWorldMut {
let archetype = self.archetypes.empty_mut(); let archetype = self.archetypes.empty_mut();
// PERF: consider avoiding allocating entities in the empty archetype unless needed // PERF: consider avoiding allocating entities in the empty archetype unless needed
@ -1190,7 +1190,7 @@ impl World {
let location = unsafe { archetype.allocate(entity, table_row) }; let location = unsafe { archetype.allocate(entity, table_row) };
self.entities.set(entity.index(), location); self.entities.set(entity.index(), location);
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.entities self.entities
.set_spawned_or_despawned_by(entity.index(), caller); .set_spawned_or_despawned_by(entity.index(), caller);
@ -1228,7 +1228,7 @@ impl World {
SpawnBatchIter::new( SpawnBatchIter::new(
self, self,
iter.into_iter(), iter.into_iter(),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
) )
} }
@ -1383,7 +1383,7 @@ impl World {
self.flush(); self.flush();
if let Ok(entity) = self.get_entity_mut(entity) { if let Ok(entity) = self.get_entity_mut(entity) {
entity.despawn_with_caller( entity.despawn_with_caller(
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
true true
@ -1656,7 +1656,7 @@ impl World {
#[inline] #[inline]
#[track_caller] #[track_caller]
pub fn init_resource<R: Resource + FromWorld>(&mut self) -> ComponentId { pub fn init_resource<R: Resource + FromWorld>(&mut self) -> ComponentId {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
let component_id = self.components.register_resource::<R>(); let component_id = self.components.register_resource::<R>();
if self if self
@ -1672,7 +1672,7 @@ impl World {
self.insert_resource_by_id( self.insert_resource_by_id(
component_id, component_id,
ptr, ptr,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -1691,7 +1691,7 @@ impl World {
pub fn insert_resource<R: Resource>(&mut self, value: R) { pub fn insert_resource<R: Resource>(&mut self, value: R) {
self.insert_resource_with_caller( self.insert_resource_with_caller(
value, value,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
); );
} }
@ -1702,7 +1702,7 @@ impl World {
pub(crate) fn insert_resource_with_caller<R: Resource>( pub(crate) fn insert_resource_with_caller<R: Resource>(
&mut self, &mut self,
value: R, value: R,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) { ) {
let component_id = self.components.register_resource::<R>(); let component_id = self.components.register_resource::<R>();
OwningPtr::make(value, |ptr| { OwningPtr::make(value, |ptr| {
@ -1711,7 +1711,7 @@ impl World {
self.insert_resource_by_id( self.insert_resource_by_id(
component_id, component_id,
ptr, ptr,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -1732,7 +1732,7 @@ impl World {
#[inline] #[inline]
#[track_caller] #[track_caller]
pub fn init_non_send_resource<R: 'static + FromWorld>(&mut self) -> ComponentId { pub fn init_non_send_resource<R: 'static + FromWorld>(&mut self) -> ComponentId {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
let component_id = self.components.register_non_send::<R>(); let component_id = self.components.register_non_send::<R>();
if self if self
@ -1748,7 +1748,7 @@ impl World {
self.insert_non_send_by_id( self.insert_non_send_by_id(
component_id, component_id,
ptr, ptr,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -1769,7 +1769,7 @@ impl World {
#[inline] #[inline]
#[track_caller] #[track_caller]
pub fn insert_non_send_resource<R: 'static>(&mut self, value: R) { pub fn insert_non_send_resource<R: 'static>(&mut self, value: R) {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
let component_id = self.components.register_non_send::<R>(); let component_id = self.components.register_non_send::<R>();
OwningPtr::make(value, |ptr| { OwningPtr::make(value, |ptr| {
@ -1778,7 +1778,7 @@ impl World {
self.insert_non_send_by_id( self.insert_non_send_by_id(
component_id, component_id,
ptr, ptr,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -2055,7 +2055,7 @@ impl World {
&mut self, &mut self,
func: impl FnOnce() -> R, func: impl FnOnce() -> R,
) -> Mut<'_, R> { ) -> Mut<'_, R> {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
let change_tick = self.change_tick(); let change_tick = self.change_tick();
let last_change_tick = self.last_change_tick(); let last_change_tick = self.last_change_tick();
@ -2069,7 +2069,7 @@ impl World {
data.insert( data.insert(
ptr, ptr,
change_tick, change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -2119,7 +2119,7 @@ impl World {
/// ``` /// ```
#[track_caller] #[track_caller]
pub fn get_resource_or_init<R: Resource + FromWorld>(&mut self) -> Mut<'_, R> { pub fn get_resource_or_init<R: Resource + FromWorld>(&mut self) -> Mut<'_, R> {
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = Location::caller(); let caller = Location::caller();
let change_tick = self.change_tick(); let change_tick = self.change_tick();
let last_change_tick = self.last_change_tick(); let last_change_tick = self.last_change_tick();
@ -2138,7 +2138,7 @@ impl World {
self.insert_resource_by_id( self.insert_resource_by_id(
component_id, component_id,
ptr, ptr,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -2269,7 +2269,7 @@ impl World {
{ {
self.insert_or_spawn_batch_with_caller( self.insert_or_spawn_batch_with_caller(
iter, iter,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
) )
} }
@ -2280,7 +2280,7 @@ impl World {
pub(crate) fn insert_or_spawn_batch_with_caller<I, B>( pub(crate) fn insert_or_spawn_batch_with_caller<I, B>(
&mut self, &mut self,
iter: I, iter: I,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) -> Result<(), Vec<Entity>> ) -> Result<(), Vec<Entity>>
where where
I: IntoIterator, I: IntoIterator,
@ -2330,7 +2330,7 @@ impl World {
location, location,
bundle, bundle,
InsertMode::Replace, InsertMode::Replace,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
) )
}; };
@ -2352,7 +2352,7 @@ impl World {
location, location,
bundle, bundle,
InsertMode::Replace, InsertMode::Replace,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
) )
}; };
@ -2368,7 +2368,7 @@ impl World {
spawner.spawn_non_existent( spawner.spawn_non_existent(
entity, entity,
bundle, bundle,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
) )
}; };
@ -2381,7 +2381,7 @@ impl World {
spawner.spawn_non_existent( spawner.spawn_non_existent(
entity, entity,
bundle, bundle,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
) )
}; };
@ -2426,7 +2426,7 @@ impl World {
self.insert_batch_with_caller( self.insert_batch_with_caller(
batch, batch,
InsertMode::Replace, InsertMode::Replace,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
); );
} }
@ -2456,7 +2456,7 @@ impl World {
self.insert_batch_with_caller( self.insert_batch_with_caller(
batch, batch,
InsertMode::Keep, InsertMode::Keep,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
); );
} }
@ -2473,7 +2473,7 @@ impl World {
&mut self, &mut self,
iter: I, iter: I,
insert_mode: InsertMode, insert_mode: InsertMode,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) where ) where
I: IntoIterator, I: IntoIterator,
I::IntoIter: Iterator<Item = (Entity, B)>, I::IntoIter: Iterator<Item = (Entity, B)>,
@ -2515,7 +2515,7 @@ impl World {
first_location, first_location,
first_bundle, first_bundle,
insert_mode, insert_mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
) )
}; };
@ -2543,7 +2543,7 @@ impl World {
location, location,
bundle, bundle,
insert_mode, insert_mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
) )
}; };
@ -2580,7 +2580,7 @@ impl World {
self.try_insert_batch_with_caller( self.try_insert_batch_with_caller(
batch, batch,
InsertMode::Replace, InsertMode::Replace,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
); );
} }
@ -2607,7 +2607,7 @@ impl World {
self.try_insert_batch_with_caller( self.try_insert_batch_with_caller(
batch, batch,
InsertMode::Keep, InsertMode::Keep,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
Location::caller(), Location::caller(),
); );
} }
@ -2624,7 +2624,7 @@ impl World {
&mut self, &mut self,
iter: I, iter: I,
insert_mode: InsertMode, insert_mode: InsertMode,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) where ) where
I: IntoIterator, I: IntoIterator,
I::IntoIter: Iterator<Item = (Entity, B)>, I::IntoIter: Iterator<Item = (Entity, B)>,
@ -2666,7 +2666,7 @@ impl World {
first_location, first_location,
first_bundle, first_bundle,
insert_mode, insert_mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
) )
}; };
@ -2694,7 +2694,7 @@ impl World {
location, location,
bundle, bundle,
insert_mode, insert_mode,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
) )
}; };
@ -2766,7 +2766,7 @@ impl World {
last_run: last_change_tick, last_run: last_change_tick,
this_run: change_tick, this_run: change_tick,
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: &mut _caller, changed_by: &mut _caller,
}; };
let result = f(self, value_mut); let result = f(self, value_mut);
@ -2782,7 +2782,7 @@ impl World {
info.insert_with_ticks( info.insert_with_ticks(
ptr, ptr,
ticks, ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
_caller, _caller,
); );
}) })
@ -2839,7 +2839,7 @@ impl World {
&mut self, &mut self,
component_id: ComponentId, component_id: ComponentId,
value: OwningPtr<'_>, value: OwningPtr<'_>,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) { ) {
let change_tick = self.change_tick(); let change_tick = self.change_tick();
@ -2849,7 +2849,7 @@ impl World {
resource.insert( resource.insert(
value, value,
change_tick, change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -2873,7 +2873,7 @@ impl World {
&mut self, &mut self,
component_id: ComponentId, component_id: ComponentId,
value: OwningPtr<'_>, value: OwningPtr<'_>,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) { ) {
let change_tick = self.change_tick(); let change_tick = self.change_tick();
@ -2883,7 +2883,7 @@ impl World {
resource.insert( resource.insert(
value, value,
change_tick, change_tick,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
); );
} }
@ -3462,7 +3462,7 @@ impl World {
// - We iterate one resource at a time, and we let go of each `PtrMut` before getting the next one // - We iterate one resource at a time, and we let go of each `PtrMut` before getting the next one
value: unsafe { ptr.assert_unique() }, value: unsafe { ptr.assert_unique() },
ticks, ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
// SAFETY: // SAFETY:
// - We have exclusive access to the world, so no other code can be aliasing the `Ptr` // - We have exclusive access to the world, so no other code can be aliasing the `Ptr`
// - We iterate one resource at a time, and we let go of each `PtrMut` before getting the next one // - We iterate one resource at a time, and we let go of each `PtrMut` before getting the next one
@ -4017,7 +4017,7 @@ mod tests {
world.insert_resource_by_id( world.insert_resource_by_id(
component_id, component_id,
ptr, ptr,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
panic::Location::caller(), panic::Location::caller(),
); );
} }
@ -4065,7 +4065,7 @@ mod tests {
world.insert_resource_by_id( world.insert_resource_by_id(
component_id, component_id,
ptr, ptr,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
panic::Location::caller(), panic::Location::caller(),
); );
} }

View File

@ -4,7 +4,7 @@ use crate::{
world::World, world::World,
}; };
use core::iter::FusedIterator; use core::iter::FusedIterator;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
/// An iterator that spawns a series of entities and returns the [ID](Entity) of /// An iterator that spawns a series of entities and returns the [ID](Entity) of
@ -18,7 +18,7 @@ where
{ {
inner: I, inner: I,
spawner: BundleSpawner<'w>, spawner: BundleSpawner<'w>,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller: &'static Location<'static>, caller: &'static Location<'static>,
} }
@ -32,7 +32,7 @@ where
pub(crate) fn new( pub(crate) fn new(
world: &'w mut World, world: &'w mut World,
iter: I, iter: I,
#[cfg(feature = "track_change_detection")] caller: &'static Location, #[cfg(feature = "track_location")] caller: &'static Location,
) -> Self { ) -> Self {
// Ensure all entity allocations are accounted for so `self.entities` can realloc if // Ensure all entity allocations are accounted for so `self.entities` can realloc if
// necessary // necessary
@ -50,7 +50,7 @@ where
Self { Self {
inner: iter, inner: iter,
spawner, spawner,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
caller, caller,
} }
} }
@ -83,7 +83,7 @@ where
unsafe { unsafe {
Some(self.spawner.spawn( Some(self.spawner.spawn(
bundle, bundle,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
self.caller, self.caller,
)) ))
} }

View File

@ -18,9 +18,9 @@ use crate::{
world::RawCommandQueue, world::RawCommandQueue,
}; };
use bevy_ptr::Ptr; use bevy_ptr::Ptr;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use bevy_ptr::UnsafeCellDeref; use bevy_ptr::UnsafeCellDeref;
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
use core::panic::Location; use core::panic::Location;
use core::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr}; use core::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr};
use thiserror::Error; use thiserror::Error;
@ -377,13 +377,13 @@ impl<'w> UnsafeWorldCell<'w> {
unsafe { Ticks::from_tick_cells(ticks, self.last_change_tick(), self.change_tick()) }; unsafe { Ticks::from_tick_cells(ticks, self.last_change_tick(), self.change_tick()) };
// SAFETY: caller ensures that no mutable reference to the resource exists // SAFETY: caller ensures that no mutable reference to the resource exists
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
let caller = unsafe { _caller.deref() }; let caller = unsafe { _caller.deref() };
Some(Ref { Some(Ref {
value, value,
ticks, ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: caller, changed_by: caller,
}) })
} }
@ -506,7 +506,7 @@ impl<'w> UnsafeWorldCell<'w> {
// - caller ensures that the resource is unaliased // - caller ensures that the resource is unaliased
value: unsafe { ptr.assert_unique() }, value: unsafe { ptr.assert_unique() },
ticks, ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
// SAFETY: // SAFETY:
// - caller ensures that `self` has permission to access the resource // - caller ensures that `self` has permission to access the resource
// - caller ensures that the resource is unaliased // - caller ensures that the resource is unaliased
@ -570,7 +570,7 @@ impl<'w> UnsafeWorldCell<'w> {
// SAFETY: This function has exclusive access to the world so nothing aliases `ptr`. // SAFETY: This function has exclusive access to the world so nothing aliases `ptr`.
value: unsafe { ptr.assert_unique() }, value: unsafe { ptr.assert_unique() },
ticks, ticks,
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
// SAFETY: This function has exclusive access to the world // SAFETY: This function has exclusive access to the world
changed_by: unsafe { _caller.deref_mut() }, changed_by: unsafe { _caller.deref_mut() },
}) })
@ -784,7 +784,7 @@ impl<'w> UnsafeEntityCell<'w> {
// SAFETY: returned component is of type T // SAFETY: returned component is of type T
value: value.deref::<T>(), value: value.deref::<T>(),
ticks: Ticks::from_tick_cells(cells, last_change_tick, change_tick), ticks: Ticks::from_tick_cells(cells, last_change_tick, change_tick),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref(), changed_by: _caller.deref(),
}) })
} }
@ -904,7 +904,7 @@ impl<'w> UnsafeEntityCell<'w> {
// SAFETY: returned component is of type T // SAFETY: returned component is of type T
value: value.assert_unique().deref_mut::<T>(), value: value.assert_unique().deref_mut::<T>(),
ticks: TicksMut::from_tick_cells(cells, last_change_tick, change_tick), ticks: TicksMut::from_tick_cells(cells, last_change_tick, change_tick),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref_mut(), changed_by: _caller.deref_mut(),
}) })
} }
@ -1030,7 +1030,7 @@ impl<'w> UnsafeEntityCell<'w> {
self.world.last_change_tick(), self.world.last_change_tick(),
self.world.change_tick(), self.world.change_tick(),
), ),
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
changed_by: _caller.deref_mut(), changed_by: _caller.deref_mut(),
}) })
.ok_or(GetEntityMutByIdError::ComponentNotFound) .ok_or(GetEntityMutByIdError::ComponentNotFound)
@ -1038,7 +1038,7 @@ impl<'w> UnsafeEntityCell<'w> {
} }
/// Returns the source code location from which this entity has been spawned. /// Returns the source code location from which this entity has been spawned.
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
pub fn spawned_by(self) -> &'static Location<'static> { pub fn spawned_by(self) -> &'static Location<'static> {
self.world() self.world()
.entities() .entities()
@ -1145,11 +1145,11 @@ unsafe fn get_component_and_ticks(
.get_changed_tick(component_id, location.table_row) .get_changed_tick(component_id, location.table_row)
.debug_checked_unwrap(), .debug_checked_unwrap(),
}, },
#[cfg(feature = "track_change_detection")] #[cfg(feature = "track_location")]
table table
.get_changed_by(component_id, location.table_row) .get_changed_by(component_id, location.table_row)
.debug_checked_unwrap(), .debug_checked_unwrap(),
#[cfg(not(feature = "track_change_detection"))] #[cfg(not(feature = "track_location"))]
(), (),
)) ))
} }

View File

@ -250,7 +250,7 @@ ios_simulator = ["bevy_pbr?/ios_simulator", "bevy_render?/ios_simulator"]
bevy_state = ["dep:bevy_state"] bevy_state = ["dep:bevy_state"]
# Enables source location tracking for change detection, which can assist with debugging # Enables source location tracking for change detection, which can assist with debugging
track_change_detection = ["bevy_ecs/track_change_detection"] track_location = ["bevy_ecs/track_location"]
# Enable function reflection # Enable function reflection
reflect_functions = [ reflect_functions = [

View File

@ -107,7 +107,7 @@ The default feature set enables most of the expected features of a game engine,
|trace_chrome|Tracing support, saving a file in Chrome Tracing format| |trace_chrome|Tracing support, saving a file in Chrome Tracing format|
|trace_tracy|Tracing support, exposing a port for Tracy| |trace_tracy|Tracing support, exposing a port for Tracy|
|trace_tracy_memory|Tracing support, with memory profiling, exposing a port for Tracy| |trace_tracy_memory|Tracing support, with memory profiling, exposing a port for Tracy|
|track_change_detection|Enables source location tracking for change detection and spawning/despawning, which can assist with debugging| |track_location|Enables source location tracking for change detection and spawning/despawning, which can assist with debugging|
|wav|WAV audio format support| |wav|WAV audio format support|
|wayland|Wayland display server support| |wayland|Wayland display server support|
|webgpu|Enable support for WebGPU in Wasm. When enabled, this feature will override the `webgl2` feature and you won't be able to run Wasm builds with WebGL2, only with WebGPU.| |webgpu|Enable support for WebGPU in Wasm. When enabled, this feature will override the `webgl2` feature and you won't be able to run Wasm builds with WebGL2, only with WebGPU.|

View File

@ -87,7 +87,7 @@ fn change_detection(
component, component,
component.is_added(), component.is_added(),
component.is_changed(), component.is_changed(),
// If you enable the `track_change_detection` feature, you can unlock the `changed_by()` // If you enable the `track_location` feature, you can unlock the `changed_by()`
// method. It returns the file and line number that the component or resource was // method. It returns the file and line number that the component or resource was
// changed in. It's not recommended for released games, but great for debugging! // changed in. It's not recommended for released games, but great for debugging!
component.changed_by() component.changed_by()
@ -100,7 +100,7 @@ fn change_detection(
my_resource, my_resource,
my_resource.is_added(), my_resource.is_added(),
my_resource.is_changed(), my_resource.is_changed(),
my_resource.changed_by() // Like components, requires `track_change_detection` feature. my_resource.changed_by() // Like components, requires `track_location` feature.
); );
} }
} }