diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 6d0fd231fc81f..314bea0d4d82b 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1248,13 +1248,7 @@ impl World { // SAFETY: column is of type R and has been allocated above column.push(value, ComponentTicks::new(change_tick)); } else { - let ptr = column.get_data_unchecked_mut(0); - std::ptr::copy_nonoverlapping::( - value.as_ptr(), - ptr.as_ptr(), - column.item_layout().size(), - ); - column.get_ticks_unchecked_mut(0).set_changed(change_tick); + column.replace(0, value, change_tick); } } @@ -1593,7 +1587,7 @@ mod tests { Drop(ID), } - #[derive(Component)] + #[derive(Resource, Component)] struct MayPanicInDrop { drop_log: Arc>>, expected_panic_flag: Arc, @@ -1786,6 +1780,48 @@ mod tests { assert_eq!(DROP_COUNT.load(std::sync::atomic::Ordering::SeqCst), 1); } + #[test] + fn insert_resource_by_id_drop_old() { + let drop_test_helper = DropTestHelper::new(); + let res = std::panic::catch_unwind(|| { + let mut world = World::new(); + + world.insert_resource(drop_test_helper.make_component(false, 0)); + let component_id = world + .components() + .get_resource_id(std::any::TypeId::of::()) + .unwrap(); + + OwningPtr::make(drop_test_helper.make_component(true, 1), |ptr| { + // SAFETY: value is valid for the component layout + unsafe { + world.insert_resource_by_id(component_id, ptr); + } + }); + + OwningPtr::make(drop_test_helper.make_component(false, 2), |ptr| { + // SAFETY: value is valid for the component layout + unsafe { + world.insert_resource_by_id(component_id, ptr); + } + }); + }); + + let drop_log = drop_test_helper.finish(res); + + assert_eq!( + drop_log, + [ + DropLogItem::Create(0), + DropLogItem::Create(1), + DropLogItem::Drop(0), // inserting 1 drops 0 + DropLogItem::Create(2), + DropLogItem::Drop(1), // inserting 2 drops 1 + DropLogItem::Drop(2), // 2 could not be inserted because dropping 1 panicked, so it is dropped as well + ] + ); + } + #[test] #[should_panic = "insert_resource_by_id called with component id which doesn't exist in this world"] fn insert_resource_by_id_invalid_component_id() {