Use ManuallyDrop instead of forget in insert_resource_with_id (#2947)

# Objective

Calling forget would invalidate the data pointer before it is used.

## Solution

Use `ManuallyDrop` to prevent the value from being dropped without moving it.
This commit is contained in:
bjorn3 2022-02-03 22:34:31 +00:00
parent 6ac9d6876f
commit af22cc1dc3

View file

@ -20,6 +20,7 @@ use crate::{
use std::{ use std::{
any::TypeId, any::TypeId,
fmt, fmt,
mem::ManuallyDrop,
sync::atomic::{AtomicU32, Ordering}, sync::atomic::{AtomicU32, Ordering},
}; };
@ -1003,13 +1004,13 @@ impl World {
/// # Safety /// # Safety
/// `component_id` must be valid and correspond to a resource component of type T /// `component_id` must be valid and correspond to a resource component of type T
#[inline] #[inline]
unsafe fn insert_resource_with_id<T>(&mut self, component_id: ComponentId, mut value: T) { unsafe fn insert_resource_with_id<T>(&mut self, component_id: ComponentId, value: T) {
let change_tick = self.change_tick(); let change_tick = self.change_tick();
let column = self.initialize_resource_internal(component_id); let column = self.initialize_resource_internal(component_id);
if column.is_empty() { if column.is_empty() {
let mut value = ManuallyDrop::new(value);
// SAFE: column is of type T and has been allocated above // SAFE: column is of type T and has been allocated above
let data = (&mut value as *mut T).cast::<u8>(); let data = (&mut *value as *mut T).cast::<u8>();
std::mem::forget(value);
column.push(data, ComponentTicks::new(change_tick)); column.push(data, ComponentTicks::new(change_tick));
} else { } else {
// SAFE: column is of type T and has already been allocated // SAFE: column is of type T and has already been allocated