It seems to me that if a data structure requires a lock for its contents to be accessed, then it doesn't matter what sort of data structure is inside. Even if the stuff on the inside is not thread safe (neither Send
nor Sync
), there will never be a situation where data races occur since only one thread will be allowed to work on it at a given time.
Yet, in Rust, Mutex
is Send
or Sync
only if the interior is correspondingly Send
or Sync
.
Is there a case where we lose memory safety despite requiring a lock?
Consider the reason why a type may not be Send
, and then consider if Mutex
remedies that reason.
The type Rc
is !Send
because it holds a shared resource that is not managed atomically. Thus it could cause a data race if two handles to the same resource were used on separate threads simultaneously. Even if one or both were wrapped in mutexes, that doesn't address the thread-safety of the type.
Another case (though weird in this situation) is a MutexGuard
itself is !Send
because it relies on system facilities that requires the unlock to happen on the same thread as the lock was acquired (source). If a Mutex
was Send
regardless of its contents, then you could use it to smuggle the guard to another thread and violate those invariants (and cause UB as far as the source above reports).
So a Mutex
providing exclusivity does not automatically protect the type from other reasons why thread-locality is a concern.