Why is AtomicPtr Send + Sync

I have noticed that AtomicPtr, despite being just a way to atomically set a pointer (the address not the value being pointed to), is Send + Sync, therefore providing a Send + Sync *mut T.

*mut T is explicitly !Send + !Sync, because it is possible to cause race conditions with *mut T.
This is still entirely true for AtomicPtr.

So why is AtomicPtr Send + Sync?

Edit: The moment i created the thread i see another one from 2015. AtomicPtr used to be !Send + !Sync.

An alternative question:

You can't cause UB sending a *mut T (or &*mut T) without unsafe somewhere else (relatedly: *mut T are Copy). So why make them !Send and !Sync?

Answer: While this can't cause UB on its own, its very hard to get correct and the compiler can't really help you do so. Therefore they are !Send and !Sync as a sort of non-negotiable lint to try to force you to write some unsafe specifically considering the Send/Sync requirements.

(At least, that was the original reasoning as I recall it.)

This still holds true for AtomicPtr, which is why it was !Send + !Sync, so why is it Send + Sync now?

Because otherwise it's relatively useless as an atomic; you couldn't share it between threads without, say, making a wrapper around AtomicPtr that does implement Send and/or Sync.

And I think it's safe to say that anyone using AtomicPtr<T> and writing unsafe code is probably going to think about threadsafety much more than the average person using *mut T.

I didn't find any evidence that was actually the case[1] (but pre-1.0 discussion is hard to find, and auto-traits were in flux when the type was being fleshed out, so I'd welcome any citation).

E.g.


  1. that the impls were intentionally missing or that the same motivation was why ↩︎