External Publication
Visit Post

Pre-RFC: Unsafe traits conditionally depending on safe trait behaviour

Rust Internals [Unofficial] May 27, 2026
Source

It is currently impossible for a dyn-compatible unsafe trait A to be able to express the semantics of "if T: A + B (where B is a safe trait), the B implementation must behave a certain way". Safe code can maliciously impl B for dyn C with a locally-definded trait C: A, so requiring this in the unsafe preconditions of A is insufficient. This came up when we were looking to stabilise a dyn-compatible Allocator, notably: dyn Allocator together with Allocator + Clone requirements is unsound, leading to UB with Arc · Issue #156920 · rust-lang/rust · GitHub.

Notably, breaking dyn compatiblity only makes Allocator sound in that implementors can rely on the orphan rule to reason about which impls may exist downstream; the underlying semantics of a sometimes-implemented safe trait affecting the correctness of an unsafe trait are currently inexpressible. The closest we could do would be making unsafe trait A: B, so always implemented.

Upon getting a vibe-check from libs(-api), lang, and a couple of people on types, this seems feasible. The proposed idea is approximately:

// -- in core --

#[unsafe(has_preconditions(Allocator))]
trait Clone {}

unsafe trait Allocator {}

#[unsafe(satisfies_preconditions(Allocator))] // this is new
impl<T: Clone> Clone for Box<T> {}

unsafe impl<A: Allocator> Allocator for Box<A> {}

// -- in downstream --

struct Foo;
// all good
impl Clone for Foo {}

struct Bar;
#[unsafe(satisfies_preconditions(Allocator))] // if we don't write this, error
impl Clone for Bar {}
unsafe impl Allocator for Bar {}

with the only bit of orphan-rule reasoning here being for implementability, not soundness: someone can't write a blanket impl Clone that breaks their downstream dependents, and if they somehow did it anyway said dependent would get a compiler error.

The one part of this we'd need to have on stable is the unsafe(satisfies_preconditions(_)) attribute. In fairness, we could ditch that as well and make it so it's just impossible to (stably) impl Clone on allocators, but that would be sad. The rest (e.g. the way we mark a safe trait as conditionally-unsafe-relevant) could be delegated to later syntax bikeshedding.

Discussion in the ATmosphere

Loading comments...