- 
                Notifications
    
You must be signed in to change notification settings  - Fork 24
 
Description
Proposal
Problem statement
There should be a safe API that converts an &mut T reference into an &mut UnsafeCell<T> reference within a certain scope.
Motivation, use-cases
When dealing with exclusive references, sometimes you may wish to opt in to temporary shared mutable access. If your type implements Copy, you can use Cell::from_mut to convert a mutable reference to a Cell, which allows interior mutability. For non-Copy types, it is often required to use UnsafeCell to allow interior mutability. Converting from &mut T to &mut UnsafeCell<T> is always sound, however there is currently no safe way to do this so the user is required to use std::mem::transmute. Use of this function is potentially error-prone, as a simple mistake might result in the returned reference having an incorrect lifetime.
For an example of a situation where this would be useful, consider this code I wrote for the bevy game engine:
// SAFETY: Converting `&mut T` -> `&UnsafeCell<T>`
// is explicitly allowed in the docs for `UnsafeCell`.
let world: &'w UnsafeCell<World> = unsafe { std::mem::transmute(world) };
Func::combine(
    input,
    // SAFETY: Since these closures are `!Send + !Sync + !'static`, they can never
    // be called in parallel. Since mutable access to `world` only exists within
    // the scope of either closure, we can be sure they will never alias one another.
    |input| self.a.run(input, unsafe { world.deref_mut() }),
    |input| self.b.run(input, unsafe { world.deref_mut() }),
)Solution sketches
We should add an associated fn to the UnsafeCell type:
pub fn from_mut(value: &mut T) -> &mut UnsafeCell<T> {
    // SAFETY: UnsafeCell is repr(transparent).
    unsafe { &mut *(value as *mut T as *mut Self) }
}This returns &mut UnsafeCell<T>, unlike Cell::from_mut which returns &Cell. It was a mistake for Cell::from_mut to work this way, since exclusive references are more useful due to the {Unsafe}Cell::get_mut function.
Links and related work
What happens now?
This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.