Replace some unsafe system executor code with safe code (#8274)

# Objective

The function `SyncUnsafeCell::from_mut` returns `&SyncUnsafeCell<T>`,
even though it could return `&mut SyncUnsafeCell<T>`. This means it is
not possible to call `get_mut` on the returned value, so you need to use
unsafe code to get exclusive access back.

## Solution

Return `&mut Self` instead of `&Self` in `SyncUnsafeCell::from_mut`.
This is consistent with my proposal for `UnsafeCell::from_mut`:
https://github.com/rust-lang/libs-team/issues/198.

Replace an unsafe pointer dereference with a safe call to `get_mut`.

---

## Changelog

+ The function `bevy_utils::SyncUnsafeCell::get_mut` now returns a value
of type `&mut SyncUnsafeCell<T>`. Previously, this returned an immutable
reference.

## Migration Guide

The function `bevy_utils::SyncUnsafeCell::get_mut` now returns a value
of type `&mut SyncUnsafeCell<T>`. Previously, this returned an immutable
reference.
This commit is contained in:
JoJoJet 2023-03-31 17:56:49 -04:00 committed by GitHub
parent 711efed018
commit ae39b07d26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 8 additions and 8 deletions

View file

@ -216,10 +216,8 @@ impl SystemExecutor for MultiThreadedExecutor {
if self.apply_final_buffers {
// Do one final apply buffers after all systems have completed
// SAFETY: all systems have completed, and so no outstanding accesses remain
let world = unsafe { &mut *world.get() };
// Commands should be applied while on the scope's thread, not the executor's thread
apply_system_buffers(&self.unapplied_systems, systems, world);
apply_system_buffers(&self.unapplied_systems, systems, world.get_mut());
self.unapplied_systems.clear();
debug_assert!(self.unapplied_systems.is_clear());
}

View file

@ -76,11 +76,13 @@ impl<T: ?Sized> SyncUnsafeCell<T> {
}
#[inline]
/// Returns a `&SyncUnsafeCell<T>` from a `&mut T`.
pub fn from_mut(t: &mut T) -> &SyncUnsafeCell<T> {
// SAFETY: `&mut` ensures unique access, and `UnsafeCell<T>` and `SyncUnsafeCell<T>`
// have #[repr(transparent)]
unsafe { &*(t as *mut T as *const SyncUnsafeCell<T>) }
/// Returns a `&mut SyncUnsafeCell<T>` from a `&mut T`.
pub fn from_mut(t: &mut T) -> &mut SyncUnsafeCell<T> {
let ptr = t as *mut T as *mut SyncUnsafeCell<T>;
// SAFETY: `ptr` must be safe to mutably dereference, since it was originally
// obtained from a mutable reference. `SyncUnsafeCell` has the same representation
// as the original type `T`, since the former is annotated with #[repr(transparent)].
unsafe { &mut *ptr }
}
}