google/zerocopy

Make `AliasingSafe` more powerful

joshlf opened this issue · 0 comments

Currently, AliasingSafe has the following safety invariants:

/// `U: AliasingSafe<T, A, R>` if either of the following conditions holds:
/// - `A` is [`Exclusive`]
/// - `T` and `U` both implement [`Immutable`]

However, we could relax this to:

/// `U: AliasingSafe<T, A, R>` if either of the following conditions holds:
/// - `A` is [`Exclusive`]
/// - `T` and `U` contain [`UnsafeCell`]s at the same locations

In particular, "T and U implement Immutable" is just a special case of " T and U contain UnsafeCells at the same locations." If we did this, we could add a new AliasingSafeReason called BecauseUnsafeCellsAgree or something to that effect.

We could then piggy-back on our existing TransparentWrapper machinery to provide a blanket impl. In particular, wherever W: TransparentWrapper<Inner = T, UnsafeCellVariance = Covariant>, we can infer that W: AliasingSafe<T, _, BecauseUnsafeCellsAgree>.

Unfortunately, this construction is less powerful than we'd like. In particular, it is not true in the general case that W: TransparentWrapper<Inner = T> implies T: TransparentWrapper<Inner = W>, but AliasingSafe is reflexive in this way. In practice, this causes problems for transparent_wrapper_into_inner: If we try to add an AliasingSafe bound to cast_unsized (a natural thing to do, and it removes a safety precondition), transparent_wrapper_into_inner's TransparentWrapper bound isn't sufficient to satisfy cast_unsized's bound. This is prototyped here. Try to build that code and see its compilation errors from transparent_wrapper_into_inner.


In order to work around this, we should split TransparentWrapper into multiple traits. Some of its properties - namely, size equality and UnsafeCell agreement - are reflexive, and can go in a separate trait which guarantees this reflexivity (and maybe encodes it in the type system somehow).