T: Sync means safe code can't cause UB such as data races by sending &T: Sync to another thread, no more (and no less).
Preserving the invariants of a struct isn't a Sync-specific concern. That's something you have to bake into the public API and preserve in your private code.
That's true, but also, it is an important fact that one cannot simply take a data structure, replace RefCell with Mutex (or Cell with Atomic*), see it is now Sync, and conclude it is also correct under access from multiple threads.
Sync is an unsafe trait, so that would require unsafe impl in a lot of places.
Structs containing Mutex are not the typical case. The typical case is structs with no interior mutability at all, which should implement Sync if their contents do.
Arguably, Rust should have avoided the auto-trait system and had #[derive(Send, Sync)] — but then we would have a lot more errors where types are not marked thread-safe when they should be. It's a tradeoff.