Field-dependent trait bounds, or "are auto traits the right model?"

I just want to add to this that:

  • Freeze is explicitly a compiler-internal optimization (it would be valid to treat every type as containing UnsafeCell) and not user facing; rather it's a compiler feature re-using the auto trait machinery.
  • UnwindSafe and RefUnwindSafe 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.)


  1. 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 YOUR unsafe CODE.) This is due to the issue that self-referential types (mostly, async created Futures) maintain internal-pointing &mut, and then are called via a Pin<&mut> to the entire Future—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. ↩︎