Having read a lot of the previous threads on volatile reads and writes using the provided functions on pointers. I came to think if it was possible to have VolatileCellRw<T>, VolatileCellRo<T>, and VolatileCellWo<T>. Where they were respectively implement Deref and DerefMut which could be used with the provided functions (or even better not need then at all).
Would this be enough to guarantee no spurious reads or writes?
Note that std::cell::Cell doesn’t impl Deref for the reason @ExpHP mentioned. Imo VolatileCell* families should follow the interface of std::cell::Cell
Unfortunately, “volatile cell” does not work because you are still using references. A &VolatileCell<T> is still marked as dereferencable and thus the compiler is allowed to introduce spurious reads. As such, the vcell crate is unfortunately not solving this problem.
To solve the problem with volatile references, we need either a wrapper around a raw pointer – something like VolatileRef<'a, T> which is basically a newtype around NonNull<T>; or we need a language change to no longer allow spurious dereferences of all references. Note that this does not just affect volatile accesses, we also have a case in libstd that is in conflict with this.
So this happens even though VolatileCell<T> is wrapping an UnsafeCell<T>? In other words, UnsafeCell<T> prevents the aliasing analysis of a &UnsafeCell<T> to cross the wrapper boundary and be applied to the wrappee, but it does not prevent the dereferenceable attribute from crossing the wrapper boundaries, is that it?
In that case, a new #[lang] wrapper seems to be needed, to act as a barrier on the dereferenceable attribute, is it not?
I mean, I don't think that VolatileRef[Mut]<'a, T> can suffice for all use cases, although this one can indeed be already implemented in Rust (comments on the code are welcome), even if it is very hard to get a value in Rust that has not been a reference before (need for the &raw operator, here).
For instance, how valid is the example currently provided by the documentation?
If we want to use references for this, yes. The alternative is to make UnsafeCell that wrapper, i.e. to also make it remove the dereferencable attribute.
That example is valid as in there is no UB, but it allows spurious reads. x is not an MMIO location so that's not a problem.