Forbid writes to `Arc::as_ptr(&a) as *mut _`

MIRI allows to write to Arc like this:

unsafe { *(Arc::as_ptr(&a) as *mut _) = v };

Playground example

This is expected, since Arc internally uses interior mutability. It is hard to imagine any way to implement Arc without using interior mutability and with Stacked Borrows. However i believe Arc's interior mutability is an implementation detail, and may change with smarter memory model.

So i think we should have something to forbid this code within MIRI. The way i see it is to add some sort of std::hint::forbid_writes<T>(p: *const T) -> *const T, which would "tag" the pointer read-only, while pointee is allowed to be modified with other *mut T, which would also allow Arc::get_mut_unchecked, compared to just using shared references to forbid the Arc writes.

Or we could remove any Arc's api implying interior mutability, if possible?

Or we could add Arc::as_mut_ptr and make it's interior mutability official.

That's essentially Arc::get_mut_unchecked, which exposes the shared mutability.

Note that whether a method takes &Arc or &mut Arc is irrelevant to whether the pointee is shared. In fact, get_mut_unchecked could be taking &Arc and not &mut Arc now that I think about it; the only reason to take &mut Arc is to kill the returned reference when the owning Arc is next used... but there are potentially other owning Arcs, so this might be more restrictive than useful.

Originally, Arc::as_ptr did disallow writes. It did this because it was roughly implemented as self.deref() as *const _. It would be trivial to make it do so again, so long as internal users (such as into_raw) are adjusted to use the "as_mut_ptr" path instead. This is likely clearer to intent internally as well.

I don't think the current Stacked Borrows supports having both RawShrRW and RawShrRO tags live interchangeably, so std::hint::forbid_writes wouldn't be possible. (In fact, IIRC the difference is just whether the tag is derived from a ShrRO tag and not directly encoded in the raw pointer tag at all.)

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.