I just want to add to this that:
Freezeis explicitly a compiler-internal optimization (it would be valid to treat every type as containingUnsafeCell) and not user facing; rather it's a compiler feature re-using theauto traitmachinery.UnwindSafeandRefUnwindSafeare, depending on who you ask, somewhere between an agressive lint, useless, or an outright mistake.Unpin(currently?) has deep ties into the validity semantics of the Rust Abstract Machine[1].
So only two auto traits (Send and Sync) are both unambiguously good and purely library concepts. (They encapsulate abstract machine concepts—whether and when it's valid to use a value from multiple threads—but the traits themselves have no impact on the operation of the abstract machine.)
Pod falls into the same category of purely library concepts, but they both have requirements beyond that of a simple auto trait (that being the padding requirements). (Zeroable also can't be a normal auto trait, due to the requirements of inhabitability.)
Miri, the rustc const engine and implementation of the Stacked Borrows proposal for the Rust Abstract Machine semantics currently removes the requirement for
&mutto be unique to!Unpintypes (or something similar; it's complicated and I'm not exactly sure on the specifics). (NO YOU MAY NOT USE THIS PROPERTY IN YOURunsafeCODE.) This is due to the issue that self-referential types (mostly,asynccreatedFutures) maintain internal-pointing&mut, and then are called via aPin<&mut>to the entireFuture—an aliasing&mut. Additionally, the async executor/reactor necessarily are holding some sort of pointer/reference to the future to facilitate their work. The exact way to formalize how this works on the Abstract Machine is still under the subject of evolving discussion. ↩︎