Inspired by OwningRef
, I was thinking about whether an OwningMut
type would be sound. A potential soundness hole occurred to me, and I'm not sure where the blame should go.
For completeness, here are the operations that could cause a problem, where T: ?Sized
:
fn new(o: O) -> Self
where O: StableAddress, O: DerefMut<Target=T>
fn map<F, U: ?Sized>(self, f: F) -> OwningMut<O, U>
where O: StableAddress, F: FnOnce(&mut T) -> &mut U
fn owner(&self) -> &O
fn deref(&self) -> &T
(StableAddress
just ensures that moving the owning value doesn't invalidate references into it created by calling <O as DerefMut>::deref_mut
.)
The conflict is with a hypothetical method on Cell
:
fn deref_mut(&mut self) -> &mut T
This would allow you to do:
let mut v = OwningMut::new(Box::new(Cell::new(Some(3))));
let mut r = v.map(|cell| cell.deref_mut().as_mut().unwrap());
r.owner().set(None);
r.map(|invalid_reference| ...); // oops!
The problem is coming from an interaction between incompatible assumptions. The hypothetical Cell::deref_mut
method assumes that the mutable reference it gives out must be permanently inaccessible by the time Cell::set
can be called. Freezing it temporarily is insufficient. On the other hand, OwningMut::owner
assumes that accessing a value through a shared reference cannot invalidate any references into it, however derived. Both assumptions can't be true, so I'm wondering which, if either, is sound.
If OwningMut::owner
is unsound, would it be sound if there were a NoInteriorMutability
bound to O
?