I have a doubt about a case of implementing interior mutability and whether it is in fact safe. If a struct A provides closure-controlled access to the aliasing and mutability of a T value, is it safe? Follow the pseudo code.
struct A<T> {
cell: UnsafeCell<T>,
}
impl A {
...
pub fn mutate<M: FnMut(&mut T)>(&self, mut mutator: M) {
let inner = unsafe { &mut *self.cell.get() };
mutator(inner);
}
pub fn access<A: Fn(&T)>(&self, accessor: A) {
let inner = unsafe { &*self.cell.get() };
accessor(inner);
}
}
this struct does not allow in any way to obtain a reference to the value beyond the described methods.
Any closures passed as mutator
could itself call mutate, which would make two &muts alive at once.
1 Like
hmm... if reentrance were somehow prevented, would it still be unsafe otherwise?
Yes, assuming it is !Sync
(if it was Sync
you would have to treat concurrent access like reentrance).
Though the only way I can see that working is if you were to reimplement RefCell
with a worse API surface.
1 Like
"references" can't really meaningfully be prevented here. Some important cases to consider include &'static A
and Arc<A>
, which you can't generally prevent users from creating if they have an A.
1 Like
Reading a bit of refcell's code I understood how they control aliasing and mutability through the guard. The way described by me would never work correctly.