diff --git a/src/design_notes/auto_traits.md b/src/design_notes/auto_traits.md index 59c6e48..506ccb1 100644 --- a/src/design_notes/auto_traits.md +++ b/src/design_notes/auto_traits.md @@ -14,9 +14,10 @@ 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][freeze 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. +to be added or stabilized. See [discussion][freeze 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. @@ -30,8 +31,36 @@ 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 is -currently unlikely. +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][Ungil] 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][AutoreleaseSafe] in a similar +manner to `pyo3`'s `Ungil`. + +[As of October 2023][2020-10-03 triage meeting], the lang team no longer feels +that stabilizing any form of auto traits is entirely out of the question. [rust-lang/rust#13231]: https://github.com/rust-lang/rust/issues/13231 [freeze discussion]: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Freeze.20stabilization.20and.20auto-trait.20backcompat/near/214251682 +[Ungil]: https://docs.rs/pyo3/0.20.0/pyo3/marker/trait.Ungil.html +[AutoreleaseSafe]: https://docs.rs/objc2/latest/objc2/rc/trait.AutoreleaseSafe.html] +[2020-10-03 triage meeting]: https://hackmd.io/tRjWZXdJQyOoD1d9rLeRGQ?view#%E2%80%9CPrepare-removal-of-auto-trait-syntax-in-favor-of-new-attribute-rustc_auto_trait%E2%80%9D-rust116126