Isn't this a bug in the definition of AtomicBool::compare_and_swap()? In particular, it takes &self as a parameter, but it should take &mut self instead. It wasn't noticed because compare_exchange() also has the same problem.
Hm, isn't it precisely the point of atomic types to provide interior mutability? If you require &mut self, then you can issue compare_and_swap from one thread only.
It definitely helps if you think of &T as "shared reference" instead of "immutable reference." For most types, mutation through shared references is unsafe, but atomic operations (AtomicBool et al.), locks (Mutex, RwLock), run-time checks (RefCell), and/or compile-time checks (all of the above, plus Cell) can be used to make it safe.
The surprising thing is that rustc is apparently letting you take &self on a interior-mutable const here, whereas it does stop you if you do this at a global level.
error[E0492]: cannot borrow a constant which contains interior mutability, create a static instead
--> src/main.rs:4:36
|
4 | static REPO: &'static AtomicBool = &REPO_LOCK;
| ^^^^^^^^^^
But I guess what's happening with REPO_LOCK.compare_and_swap(...) is that it's making a local copy of the constant, and then referencing that for the &self call. It's pretty similar to what happens with mutating a literal constant, like let x = &mut 42; *x += 1;.
No, AtomicBool and the other atomic types are intended to be updated concurrently via & (shared) references. If they required &mut then there would be no point using them over a plain value.
The issue here is that a const creates a new copy of itself every time it's used, even if the value's type is not Copy (it's kind of magic like that). It's like if you stuck a .clone() before each method call.
Conversely, static marks a value as a global which you can take references to and even update in-place if it contains UnsafeCell (which all the atomics do), which is what @matklad's friend intended.
The point of atomic types is to have atomic updates, not interior mutability. UnsafeCell is "the core primitive for interior mutability in Rust," so I would have expected that any interior mutability should be done inside an UnsafeCell and if that mutability needs to be atomic, then there would be an atomic type inside the UnsafeCell.
But, it's too late to argue that because it's already been decided to do something different.
However, this example seems to show the type system is unsound. After all, any change to a constant needs to be forbidden by the definition of “constant.” So some fix to the type system is needed.
I misunderstood. The atomic types are wrappers around UnsafeCell and so the problem I thought was going to occur isn't an issue, AFAICT.
But, then, doesn't that RFC also provide the key to resolving this: Just don't allow const values to use UnsafeCell constructors, similar to how that RFC handles UnsafeCell?