diff --git a/crates/bevy_ecs/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index 74c77546dc863a..28b43fc8c1b322 100644 --- a/crates/bevy_ecs/src/bundle.rs +++ b/crates/bevy_ecs/src/bundle.rs @@ -387,7 +387,7 @@ impl BundleInfo { table_row: TableRow, change_tick: Tick, bundle: T, - caller: String, + caller: core::panic::Location<'static>, ) { // NOTE: get_components calls this closure on each component in "bundle order". // bundle_info.component_ids are also in "bundle order" @@ -404,15 +404,10 @@ impl BundleInfo { let status = unsafe { bundle_component_status.get_status(bundle_component) }; match status { ComponentStatus::Added => { - column.initialize( - table_row, - component_ptr, - change_tick, - caller.clone(), - ); + column.initialize(table_row, component_ptr, change_tick, caller); } ComponentStatus::Mutated => { - column.replace(table_row, component_ptr, change_tick, caller.clone()); + column.replace(table_row, component_ptr, change_tick, caller); } } } @@ -421,7 +416,7 @@ impl BundleInfo { // SAFETY: If component_id is in self.component_ids, BundleInfo::new requires that // a sparse set exists for the component. unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() }; - sparse_set.insert(entity, component_ptr, change_tick, caller.clone()); + sparse_set.insert(entity, component_ptr, change_tick, caller); } } bundle_component += 1; @@ -642,17 +637,18 @@ impl<'w> BundleInserter<'w> { /// `entity` must currently exist in the source archetype for this inserter. `location` /// must be `entity`'s location in the archetype. `T` must match this [`BundleInfo`]'s type #[inline] + #[track_caller] pub(crate) unsafe fn insert( &mut self, entity: Entity, location: EntityLocation, bundle: T, - caller: String, ) -> EntityLocation { let bundle_info = self.bundle_info.as_ref(); let add_bundle = self.add_bundle.as_ref(); let table = self.table.as_mut(); let archetype = self.archetype.as_mut(); + let caller = *core::panic::Location::caller(); let (new_archetype, new_location) = match &mut self.result { InsertBundleResult::SameArchetype => { @@ -891,7 +887,7 @@ impl<'w> BundleSpawner<'w> { &mut self, entity: Entity, bundle: T, - caller: String, + caller: core::panic::Location<'static>, ) -> EntityLocation { let table = self.table.as_mut(); let archetype = self.archetype.as_mut(); @@ -939,7 +935,11 @@ impl<'w> BundleSpawner<'w> { /// # Safety /// `T` must match this [`BundleInfo`]'s type #[inline] - pub unsafe fn spawn(&mut self, bundle: T, caller: String) -> Entity { + pub unsafe fn spawn( + &mut self, + bundle: T, + caller: core::panic::Location<'static>, + ) -> Entity { let entity = self.entities().alloc(); // SAFETY: entity is allocated (but non-existent), `T` matches this BundleInfo's type unsafe { diff --git a/crates/bevy_ecs/src/change_detection.rs b/crates/bevy_ecs/src/change_detection.rs index 53833a12b1c612..74d3e8608b795e 100644 --- a/crates/bevy_ecs/src/change_detection.rs +++ b/crates/bevy_ecs/src/change_detection.rs @@ -65,7 +65,7 @@ pub trait DetectChanges { fn last_changed(&self) -> Tick; /// The location that last caused this to change. - fn changed_by(&self) -> &str; + fn changed_by(&self) -> core::panic::Location<'static>; } /// Types that implement reliable change detection. @@ -286,8 +286,8 @@ macro_rules! change_detection_impl { } #[inline] - fn changed_by(&self) -> &str { - self.caller + fn changed_by(&self) -> core::panic::Location<'static> { + *self.caller } } @@ -318,14 +318,14 @@ macro_rules! change_detection_mut_impl { #[track_caller] fn set_changed(&mut self) { *self.ticks.changed = self.ticks.this_run; - *self.caller = core::panic::Location::caller().to_string(); + *self.caller = *core::panic::Location::caller(); } #[inline] #[track_caller] fn set_last_changed(&mut self, last_changed: Tick) { *self.ticks.changed = last_changed; - *self.caller = core::panic::Location::caller().to_string(); + *self.caller = *core::panic::Location::caller(); } #[inline] @@ -339,7 +339,7 @@ macro_rules! change_detection_mut_impl { #[track_caller] fn deref_mut(&mut self) -> &mut Self::Target { self.set_changed(); - *self.caller = format!("{:?}", std::panic::Location::caller()); + *self.caller = *core::panic::Location::caller(); self.value } } @@ -518,7 +518,7 @@ impl<'w> From> for Ticks<'w> { pub struct Res<'w, T: ?Sized + Resource> { pub(crate) value: &'w T, pub(crate) ticks: Ticks<'w>, - pub(crate) caller: &'w str, + pub(crate) caller: &'w core::panic::Location<'static>, } impl<'w, T: Resource> Res<'w, T> { @@ -581,7 +581,7 @@ impl_debug!(Res<'w, T>, Resource); pub struct ResMut<'w, T: ?Sized + Resource> { pub(crate) value: &'w mut T, pub(crate) ticks: TicksMut<'w>, - pub(crate) caller: &'w mut String, + pub(crate) caller: &'w mut core::panic::Location<'static>, } impl<'w, 'a, T: Resource> IntoIterator for &'a ResMut<'w, T> @@ -641,7 +641,7 @@ impl<'w, T: Resource> From> for Mut<'w, T> { pub struct NonSendMut<'w, T: ?Sized + 'static> { pub(crate) value: &'w mut T, pub(crate) ticks: TicksMut<'w>, - pub(crate) caller: &'w mut String, + pub(crate) caller: &'w mut core::panic::Location<'static>, } change_detection_impl!(NonSendMut<'w, T>, T,); @@ -688,7 +688,7 @@ impl<'w, T: 'static> From> for Mut<'w, T> { pub struct Ref<'w, T: ?Sized> { pub(crate) value: &'w T, pub(crate) ticks: Ticks<'w>, - pub(crate) caller: &'w str, + pub(crate) caller: &'w core::panic::Location<'static>, } impl<'w, T: ?Sized> Ref<'w, T> { @@ -726,7 +726,7 @@ impl<'w, T: ?Sized> Ref<'w, T> { changed: &'w Tick, last_run: Tick, this_run: Tick, - caller: &'w str, + caller: &'w core::panic::Location<'static>, ) -> Ref<'w, T> { Ref { value, @@ -818,7 +818,7 @@ impl_debug!(Ref<'w, T>,); pub struct Mut<'w, T: ?Sized> { pub(crate) value: &'w mut T, pub(crate) ticks: TicksMut<'w>, - pub(crate) caller: &'w mut String, + pub(crate) caller: &'w mut core::panic::Location<'static>, } impl<'w, T: ?Sized> Mut<'w, T> { @@ -843,7 +843,7 @@ impl<'w, T: ?Sized> Mut<'w, T> { last_changed: &'w mut Tick, last_run: Tick, this_run: Tick, - caller: &'w mut String, + caller: &'w mut core::panic::Location<'static>, ) -> Self { Self { value, @@ -909,7 +909,7 @@ impl_debug!(Mut<'w, T>,); pub struct MutUntyped<'w> { pub(crate) value: PtrMut<'w>, pub(crate) ticks: TicksMut<'w>, - pub(crate) caller: &'w mut String, + pub(crate) caller: &'w mut core::panic::Location<'static>, } impl<'w> MutUntyped<'w> { @@ -1024,8 +1024,8 @@ impl<'w> DetectChanges for MutUntyped<'w> { } #[inline] - fn changed_by(&self) -> &str { - self.caller + fn changed_by(&self) -> core::panic::Location<'static> { + *self.caller } } @@ -1036,14 +1036,14 @@ impl<'w> DetectChangesMut for MutUntyped<'w> { #[track_caller] fn set_changed(&mut self) { *self.ticks.changed = self.ticks.this_run; - *self.caller = core::panic::Location::caller().to_string(); + *self.caller = *core::panic::Location::caller(); } #[inline] #[track_caller] fn set_last_changed(&mut self, last_changed: Tick) { *self.ticks.changed = last_changed; - *self.caller = core::panic::Location::caller().to_string(); + *self.caller = *core::panic::Location::caller(); } #[inline] @@ -1206,10 +1206,11 @@ mod tests { this_run: Tick::new(4), }; let mut res = R {}; + let mut caller = *core::panic::Location::caller(); let res_mut = ResMut { value: &mut res, ticks, - caller: &mut "".into(), + caller: &mut caller, }; let into_mut: Mut = res_mut.into(); @@ -1226,7 +1227,7 @@ mod tests { changed: Tick::new(3), }; let mut res = R {}; - let mut caller = String::new(); + let mut caller = *core::panic::Location::caller(); let val = Mut::new( &mut res, @@ -1254,10 +1255,11 @@ mod tests { this_run: Tick::new(4), }; let mut res = R {}; + let mut caller = *core::panic::Location::caller(); let non_send_mut = NonSendMut { value: &mut res, ticks, - caller: &mut "".into(), + caller: &mut caller, }; let into_mut: Mut = non_send_mut.into(); @@ -1286,10 +1288,11 @@ mod tests { }; let mut outer = Outer(0); + let mut caller = *core::panic::Location::caller(); let ptr = Mut { value: &mut outer, ticks, - caller: &mut "".into(), + caller: &mut caller, }; assert!(!ptr.is_changed()); @@ -1372,10 +1375,11 @@ mod tests { }; let mut value: i32 = 5; + let mut caller = *core::panic::Location::caller(); let value = MutUntyped { value: PtrMut::from(&mut value), ticks, - caller: &mut "".into(), + caller: &mut caller, }; let reflect_from_ptr = >::from_type(); @@ -1406,10 +1410,11 @@ mod tests { this_run: Tick::new(4), }; let mut c = C {}; + let mut caller = *core::panic::Location::caller(); let mut_typed = Mut { value: &mut c, ticks, - caller: &mut "".into(), + caller: &mut caller, }; let into_mut: MutUntyped = mut_typed.into(); diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index b4840c79f91379..998644579ce5e4 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -12,7 +12,7 @@ use crate::{ }; use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; use bevy_utils::all_tuples; -use std::{cell::UnsafeCell, marker::PhantomData, ops::Deref}; +use std::{cell::UnsafeCell, marker::PhantomData}; /// Types that can be fetched from a [`World`] using a [`Query`]. /// @@ -1026,7 +1026,7 @@ pub struct RefFetch<'w, T> { ThinSlicePtr<'w, UnsafeCell>, ThinSlicePtr<'w, UnsafeCell>, ThinSlicePtr<'w, UnsafeCell>, - ThinSlicePtr<'w, UnsafeCell>, + ThinSlicePtr<'w, UnsafeCell>>, )>, // T::STORAGE_TYPE = StorageType::SparseSet sparse_set: Option<&'w ComponentSparseSet>, @@ -1215,7 +1215,7 @@ pub struct WriteFetch<'w, T> { ThinSlicePtr<'w, UnsafeCell>, ThinSlicePtr<'w, UnsafeCell>, ThinSlicePtr<'w, UnsafeCell>, - ThinSlicePtr<'w, UnsafeCell>, + ThinSlicePtr<'w, UnsafeCell>>, )>, // T::STORAGE_TYPE = StorageType::SparseSet sparse_set: Option<&'w ComponentSparseSet>, @@ -1326,7 +1326,8 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T { // SAFETY: The caller ensures `table_row` is in range. let added = unsafe { added_ticks.get(table_row.as_usize()) }; // SAFETY: The caller ensures `table_row` is in range. - let changed = unsafe { changed_ticks.get(table_row.as_usize()) }; // SAFETY: The caller ensures `table_row` is in range. + let changed = unsafe { changed_ticks.get(table_row.as_usize()) }; + // SAFETY: The caller ensures `table_row` is in range. let caller = unsafe { callers.get(table_row.as_usize()) }; Mut { diff --git a/crates/bevy_ecs/src/storage/resource.rs b/crates/bevy_ecs/src/storage/resource.rs index ae3f4e8411000b..de76f8c94df054 100644 --- a/crates/bevy_ecs/src/storage/resource.rs +++ b/crates/bevy_ecs/src/storage/resource.rs @@ -17,7 +17,7 @@ pub struct ResourceData { type_name: String, id: ArchetypeComponentId, origin_thread_id: Option, - caller: UnsafeCell, + caller: UnsafeCell>, } impl Drop for ResourceData { @@ -110,7 +110,13 @@ impl ResourceData { /// If `SEND` is false, this will panic if a value is present and is not accessed from the /// original thread it was inserted in. #[inline] - pub(crate) fn get_with_ticks(&self) -> Option<(Ptr<'_>, TickCells<'_>, &UnsafeCell)> { + pub(crate) fn get_with_ticks( + &self, + ) -> Option<( + Ptr<'_>, + TickCells<'_>, + &UnsafeCell>, + )> { self.is_present().then(|| { self.validate_access(); ( @@ -211,7 +217,13 @@ impl ResourceData { /// original thread it was inserted from. #[inline] #[must_use = "The returned pointer to the removed component should be used or dropped"] - pub(crate) fn remove(&mut self) -> Option<(OwningPtr<'_>, ComponentTicks, String)> { + pub(crate) fn remove( + &mut self, + ) -> Option<( + OwningPtr<'_>, + ComponentTicks, + core::panic::Location<'static>, + )> { if !self.is_present() { return None; } @@ -222,7 +234,7 @@ impl ResourceData { 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 - let caller = unsafe { std::mem::take(self.caller.deref_mut()) }; + let caller = unsafe { *self.caller.deref_mut() }; // SAFETY: This function is being called through an exclusive mutable reference to Self, which // makes it sound to read these ticks. @@ -342,7 +354,7 @@ impl Resources { type_name: String::from(component_info.name()), id: f(), origin_thread_id: None, - caller: UnsafeCell::new("init".into()) + caller: UnsafeCell::new(*core::panic::Location::caller()) } }) } diff --git a/crates/bevy_ecs/src/storage/sparse_set.rs b/crates/bevy_ecs/src/storage/sparse_set.rs index d629521a5d44bd..d9733043688b70 100644 --- a/crates/bevy_ecs/src/storage/sparse_set.rs +++ b/crates/bevy_ecs/src/storage/sparse_set.rs @@ -3,7 +3,7 @@ use crate::{ entity::Entity, storage::{Column, TableRow}, }; -use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref}; +use bevy_ptr::{OwningPtr, Ptr}; use nonmax::NonMaxUsize; use std::{cell::UnsafeCell, hash::Hash, marker::PhantomData}; @@ -169,7 +169,7 @@ impl ComponentSparseSet { entity: Entity, value: OwningPtr<'_>, change_tick: Tick, - caller: String, + caller: core::panic::Location<'static>, ) { if let Some(&dense_index) = self.sparse.get(entity.index()) { #[cfg(debug_assertions)] @@ -227,7 +227,11 @@ impl ComponentSparseSet { pub fn get_with_ticks( &self, entity: Entity, - ) -> Option<(Ptr<'_>, TickCells<'_>, &UnsafeCell)> { + ) -> Option<( + Ptr<'_>, + TickCells<'_>, + &UnsafeCell>, + )> { let dense_index = *self.sparse.get(entity.index())?; #[cfg(debug_assertions)] assert_eq!(entity, self.entities[dense_index.as_usize()]); diff --git a/crates/bevy_ecs/src/storage/table.rs b/crates/bevy_ecs/src/storage/table.rs index d8a17514d4e1fc..686a322deb095f 100644 --- a/crates/bevy_ecs/src/storage/table.rs +++ b/crates/bevy_ecs/src/storage/table.rs @@ -152,7 +152,7 @@ pub struct Column { data: BlobVec, added_ticks: Vec>, changed_ticks: Vec>, - callers: Vec>, + callers: Vec>>, } impl Column { @@ -186,7 +186,7 @@ impl Column { row: TableRow, data: OwningPtr<'_>, tick: Tick, - caller: String, + caller: core::panic::Location<'static>, ) { debug_assert!(row.as_usize() < self.len()); self.data.initialize_unchecked(row.as_usize(), data); @@ -209,7 +209,7 @@ impl Column { row: TableRow, data: OwningPtr<'_>, change_tick: Tick, - caller: String, + caller: core::panic::Location<'static>, ) { debug_assert!(row.as_usize() < self.len()); self.data.replace_unchecked(row.as_usize(), data); @@ -266,7 +266,11 @@ impl Column { pub(crate) unsafe fn swap_remove_and_forget_unchecked( &mut self, row: TableRow, - ) -> (OwningPtr<'_>, ComponentTicks, String) { + ) -> ( + OwningPtr<'_>, + ComponentTicks, + core::panic::Location<'static>, + ) { 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 changed = self.changed_ticks.swap_remove(row.as_usize()).into_inner(); @@ -311,7 +315,7 @@ impl Column { &mut self, ptr: OwningPtr<'_>, ticks: ComponentTicks, - caller: String, + caller: core::panic::Location<'static>, ) { self.data.push(ptr); self.added_ticks.push(UnsafeCell::new(ticks.added)); @@ -369,8 +373,13 @@ impl Column { &self.changed_ticks } + /// Fetches the slice to the [`Column`]'s caller locations. + /// + /// Note: The values stored within are [`UnsafeCell`]. + /// Users of this API must ensure that accesses to each individual element + /// adhere to the safety invariants of [`UnsafeCell`]. #[inline] - pub fn get_callers_slice(&self) -> &[UnsafeCell] { + pub fn get_callers_slice(&self) -> &[UnsafeCell>] { &self.callers } @@ -378,7 +387,14 @@ impl Column { /// /// Returns `None` if `row` is out of bounds. #[inline] - pub fn get(&self, row: TableRow) -> Option<(Ptr<'_>, TickCells<'_>, &UnsafeCell)> { + pub fn get( + &self, + row: TableRow, + ) -> Option<( + Ptr<'_>, + TickCells<'_>, + &UnsafeCell>, + )> { (row.as_usize() < self.data.len()) // SAFETY: The row is length checked before fetching the pointer. This is being // accessed through a read-only reference to the column. @@ -507,7 +523,10 @@ impl Column { /// # Safety /// `row` must be within the range `[0, self.len())`. #[inline] - pub unsafe fn get_caller_unchecked(&self, row: TableRow) -> &UnsafeCell { + pub unsafe fn get_caller_unchecked( + &self, + row: TableRow, + ) -> &UnsafeCell> { debug_assert!(row.as_usize() < self.callers.len()); self.callers.get_unchecked(row.as_usize()) } @@ -785,7 +804,9 @@ impl Table { column.data.set_len(self.entities.len()); column.added_ticks.push(UnsafeCell::new(Tick::new(0))); column.changed_ticks.push(UnsafeCell::new(Tick::new(0))); - column.callers.push(UnsafeCell::new(String::new())); + column + .callers + .push(UnsafeCell::new(*core::panic::Location::caller())); } TableRow::from_usize(index) } @@ -993,7 +1014,7 @@ mod tests { row, value_ptr, Tick::new(0), - "".into(), + *core::panic::Location::caller(), ); }); }; diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 60ddac3f11a683..72ac4cb6959a3b 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1044,7 +1044,7 @@ pub struct NonSend<'w, T: 'static> { ticks: ComponentTicks, last_run: Tick, this_run: Tick, - caller: &'w str, + caller: &'w core::panic::Location<'static>, } // SAFETY: Only reads a single World non-send resource @@ -1071,8 +1071,8 @@ impl<'w, T: 'static> NonSend<'w, T> { } /// The location that last caused this to change. - pub fn changed_by(&self) -> &str { - self.caller + pub fn changed_by(&self) -> core::panic::Location<'static> { + *self.caller } } diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index b74cf247228e1d..abdb898bee9ff2 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -767,13 +767,12 @@ impl<'w> EntityWorldMut<'w> { /// This will overwrite any previous value(s) of the same component type. #[track_caller] pub fn insert(&mut self, bundle: T) -> &mut Self { - let caller = core::panic::Location::caller().to_string(); let change_tick = self.world.change_tick(); let mut bundle_inserter = BundleInserter::new::(self.world, self.location.archetype_id, change_tick); self.location = // SAFETY: location matches current entity. `T` matches `bundle_info` - unsafe { bundle_inserter.insert(self.entity, self.location, bundle, caller) }; + unsafe { bundle_inserter.insert(self.entity, self.location, bundle) }; self } @@ -787,11 +786,11 @@ impl<'w> EntityWorldMut<'w> { /// /// - [`ComponentId`] must be from the same world as [`EntityWorldMut`] /// - [`OwningPtr`] must be a valid reference to the type represented by [`ComponentId`] + #[track_caller] pub unsafe fn insert_by_id( &mut self, component_id: ComponentId, component: OwningPtr<'_>, - caller: String, ) -> &mut Self { let change_tick = self.world.change_tick(); let bundle_id = self @@ -813,7 +812,6 @@ impl<'w> EntityWorldMut<'w> { self.location, Some(component).into_iter(), Some(storage_type).iter().cloned(), - caller, ); self } @@ -830,11 +828,11 @@ impl<'w> EntityWorldMut<'w> { /// # Safety /// - Each [`ComponentId`] must be from the same world as [`EntityWorldMut`] /// - Each [`OwningPtr`] must be a valid reference to the type represented by [`ComponentId`] + #[track_caller] pub unsafe fn insert_by_ids<'a, I: Iterator>>( &mut self, component_ids: &[ComponentId], iter_components: I, - caller: String, ) -> &mut Self { let change_tick = self.world.change_tick(); let bundle_id = self @@ -856,7 +854,6 @@ impl<'w> EntityWorldMut<'w> { self.location, iter_components, (*storage_types).iter().cloned(), - caller, ); *self.world.bundles.get_storages_unchecked(bundle_id) = std::mem::take(&mut storage_types); self @@ -2255,6 +2252,7 @@ pub enum TryFromFilteredError { /// - [`OwningPtr`] and [`StorageType`] iterators must correspond to the /// [`BundleInfo`] used to construct [`BundleInserter`] /// - [`Entity`] must correspond to [`EntityLocation`] +#[track_caller] unsafe fn insert_dynamic_bundle< 'a, I: Iterator>, @@ -2265,7 +2263,6 @@ unsafe fn insert_dynamic_bundle< location: EntityLocation, components: I, storage_types: S, - caller: String, ) -> EntityLocation { struct DynamicInsertBundle<'a, I: Iterator)>> { components: I, @@ -2284,7 +2281,7 @@ unsafe fn insert_dynamic_bundle< }; // SAFETY: location matches current entity. - unsafe { bundle_inserter.insert(entity, location, bundle, caller) } + unsafe { bundle_inserter.insert(entity, location, bundle) } } /// Removes a bundle from the given archetype and returns the resulting archetype (or None if the @@ -2775,7 +2772,7 @@ mod tests { let mut entity = world.spawn_empty(); OwningPtr::make(TestComponent(42), |ptr| { // SAFETY: `ptr` matches the component id - unsafe { entity.insert_by_id(test_component_id, ptr, "".into()) }; + unsafe { entity.insert_by_id(test_component_id, ptr) }; }); let components: Vec<_> = world.query::<&TestComponent>().iter(&world).collect(); @@ -2787,7 +2784,7 @@ mod tests { let mut entity = world.spawn_empty(); OwningPtr::make(TestComponent(84), |ptr| { // SAFETY: `ptr` matches the component id - unsafe { entity.insert_by_ids(&[test_component_id], vec![ptr].into_iter(), "".into()) }; + unsafe { entity.insert_by_ids(&[test_component_id], vec![ptr].into_iter()) }; }); let components: Vec<_> = world.query::<&TestComponent>().iter(&world).collect(); @@ -2809,9 +2806,7 @@ mod tests { OwningPtr::make(test_component_value, |ptr1| { OwningPtr::make(test_component_2_value, |ptr2| { // SAFETY: `ptr1` and `ptr2` match the component ids - unsafe { - entity.insert_by_ids(&component_ids, vec![ptr1, ptr2].into_iter(), "".into()) - }; + unsafe { entity.insert_by_ids(&component_ids, vec![ptr1, ptr2].into_iter()) }; }); }); diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index f7e86717ad1924..7503be653aca5d 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -960,11 +960,7 @@ impl World { let mut bundle_spawner = BundleSpawner::new::(self, change_tick); // SAFETY: bundle's type matches `bundle_info`, entity is allocated but non-existent unsafe { - bundle_spawner.spawn_non_existent( - entity, - bundle, - core::panic::Location::caller().to_string(), - ) + bundle_spawner.spawn_non_existent(entity, bundle, *core::panic::Location::caller()) } }; @@ -1779,14 +1775,7 @@ impl World { if location.archetype_id == archetype => { // SAFETY: `entity` is valid, `location` matches entity, bundle matches inserter - unsafe { - inserter.insert( - entity, - location, - bundle, - core::panic::Location::caller().to_string(), - ) - }; + unsafe { inserter.insert(entity, location, bundle) }; } _ => { // SAFETY: we initialized this bundle_id in `init_info` @@ -1799,14 +1788,7 @@ impl World { ) }; // SAFETY: `entity` is valid, `location` matches entity, bundle matches inserter - unsafe { - inserter.insert( - entity, - location, - bundle, - core::panic::Location::caller().to_string(), - ) - }; + unsafe { inserter.insert(entity, location, bundle) }; spawn_or_insert = SpawnOrInsert::Insert(inserter, location.archetype_id); } @@ -1819,7 +1801,7 @@ impl World { spawner.spawn_non_existent( entity, bundle, - core::panic::Location::caller().to_string(), + *core::panic::Location::caller(), ) }; } else { @@ -1831,7 +1813,7 @@ impl World { spawner.spawn_non_existent( entity, bundle, - core::panic::Location::caller().to_string(), + *core::panic::Location::caller(), ) }; spawn_or_insert = SpawnOrInsert::Spawn(spawner); @@ -2526,6 +2508,9 @@ impl World { // - We iterate one resource at a time, and we let go of each `PtrMut` before getting the next one value: unsafe { ptr.assert_unique() }, ticks, + // SAFETY: + // - 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 caller: unsafe { caller.deref_mut() }, }; diff --git a/crates/bevy_ecs/src/world/spawn_batch.rs b/crates/bevy_ecs/src/world/spawn_batch.rs index 0fcfdb860d7ab3..bb575f67a410ae 100644 --- a/crates/bevy_ecs/src/world/spawn_batch.rs +++ b/crates/bevy_ecs/src/world/spawn_batch.rs @@ -16,7 +16,7 @@ where { inner: I, spawner: BundleSpawner<'w>, - caller: String, + caller: core::panic::Location<'static>, } impl<'w, I> SpawnBatchIter<'w, I> @@ -43,7 +43,7 @@ where Self { inner: iter, spawner, - caller: core::panic::Location::caller().to_string(), + caller: *core::panic::Location::caller(), } } } @@ -72,7 +72,7 @@ where fn next(&mut self) -> Option { let bundle = self.inner.next()?; // SAFETY: bundle matches spawner type - unsafe { Some(self.spawner.spawn(bundle, self.caller.clone())) } + unsafe { Some(self.spawner.spawn(bundle, self.caller)) } } fn size_hint(&self) -> (usize, Option) { diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index 4657de5dfc7e74..fad87f17be0b13 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -538,7 +538,11 @@ impl<'w> UnsafeWorldCell<'w> { pub(crate) unsafe fn get_resource_with_ticks( self, component_id: ComponentId, - ) -> Option<(Ptr<'w>, TickCells<'w>, &'w UnsafeCell)> { + ) -> Option<( + Ptr<'w>, + TickCells<'w>, + &'w UnsafeCell>, + )> { // SAFETY: // - caller ensures there is no `&mut World` // - caller ensures there are no mutable borrows of this resource @@ -562,7 +566,11 @@ impl<'w> UnsafeWorldCell<'w> { pub(crate) unsafe fn get_non_send_with_ticks( self, component_id: ComponentId, - ) -> Option<(Ptr<'w>, TickCells<'w>, &'w UnsafeCell)> { + ) -> Option<( + Ptr<'w>, + TickCells<'w>, + &'w UnsafeCell>, + )> { // SAFETY: // - caller ensures there is no `&mut World` // - caller ensures there are no mutable borrows of this resource @@ -972,7 +980,11 @@ unsafe fn get_component_and_ticks( storage_type: StorageType, entity: Entity, location: EntityLocation, -) -> Option<(Ptr<'_>, TickCells<'_>, &UnsafeCell)> { +) -> Option<( + Ptr<'_>, + TickCells<'_>, + &UnsafeCell>, +)> { match storage_type { StorageType::Table => { let components = world.fetch_table(location, component_id)?; diff --git a/examples/ecs/dynamic.rs b/examples/ecs/dynamic.rs index 5127c0e5ddf35e..ad4bb0bc7752bc 100644 --- a/examples/ecs/dynamic.rs +++ b/examples/ecs/dynamic.rs @@ -142,7 +142,7 @@ fn main() { entity.insert_by_ids( &to_insert_ids, to_insert_ptr.into_iter(), - "dynamic".into(), + *core::panic::Location::caller(), ); }