I just want to add to this that:
Freeze
is 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 trait
machinery.UnwindSafe
andRefUnwindSafe
are, 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
&mut
to be unique to!Unpin
types (or something similar; it's complicated and I'm not exactly sure on the specifics). (NO YOU MAY NOT USE THIS PROPERTY IN YOURunsafe
CODE.) This is due to the issue that self-referential types (mostly,async
createdFuture
s) 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. ↩︎