Auto traits
Auto traits permit automatically implementing a trait for types which contain
fields implementing the trait. That is, they are fairly close to an automatic
derive. They describe properties of types rather than behaviors; current stable
Rust has several auto traits: Send, Sync, Unpin, UnwindSafe,
RefUnwindSafe.
Freeze is also an auto trait indirectly observable on stable; it is used by
the compiler to determine which types can be placed in read-only memory, for
example.
Auto traits are tracked in rust-lang/rust#13231, and are also sometimes referred to as OIBITs (“opt-in built-in traits”).
As of November 2020, the language team feels that new auto traits are unlikely
to be added or stabilized. See discussion on the addition
of Freeze for context. There is a fairly high burden to doing so on the
ecosystem, as it becomes a concern of every library author whether to implement
the trait or not.
Each auto trait represents a semver compatibility hazard for Rust libraries, as adding private fields can remove the auto trait unintentionally from a type.
Stabilizing the ability to define auto traits also allows “testing” for the absence of a specific type:
auto trait NoString {}
impl !NoString for String {}
This is not something we generally want to allow, as it makes almost any change to types semver breaking. That means that stabilizing defining new auto traits with no restrictions on negative impls is currently unlikely.
Restrictions on negative impls
Not all use-cases for auto traits require unrestricted “type absence testing”
capabilities. pyo3’s Ungil trait provides a good case study. pyo3
is a Python interoperability library, and it uses the Ungil trait to denote
types that are safe to access when the Python Global Interpeter Lock (GIL) is
not held. pyo3 provides explicit !Ungil impls only for types defined in the
pyo3 crate itself. Because of this, all types that do not implement Ungil
are defined either by pyo3 itself, or by downstream dependencies of pyo3. As
long as pyo3 does not introduce new negative impls for existing types in new
minor versions of itself, the backward compatibility hazard is mostly avoided.
However, there is still one problematic case. Trait objects only implement the
traits they list explicitly, so even with the restrictions described previously,
downstream crates would be able to test for the presence of trait objects inside
upstream types. One potential solution is to change dyn Trait to mean
dyn Trait + AllAutoTraitsDefinedInDownstreamCrates or
dyn Trait + AllAutoTraitsDefinedOutsideOfCore.
obj2c uses its AutoreleaseSafe auto trait in a similar
manner to pyo3’s Ungil.
As of October 2023, the lang team no longer feels that stabilizing any form of auto traits is entirely out of the question.