This is a pre-RFC for safe coercions.
Safe coercions are implemented via a magic trait Coercible<A, B>. Instances of Coercible<A, B> exist as follows:
- Between any two types A and B such that casting via
as would be legal AND the two types have
the same size, but NOT if one is a floating-point type and the other is not.
- Between any two struct, enum, tuple, or slice types A and B, such that:
- a. Instances of
Coercible<C, D> exist for every corresponding member of A and B.
- b. All fields that have different types in A and B are visible at the location where the coercion is made.
- Optionally, other instances may exist, such as allowing an array of integers to be coerced to an array of bytes of the same size.
Coercible<A,B> looks as follows:
use std::mem;
unsafe trait Coercible<A, B> {
#[inline(always)]
fn coerce(a: A) -> B {
unsafe { mem::transmute(a) }
}
}
Creating instances of Coercible manually is nonsensical and a compile-time error. Alternatively, it may be possible for users to opt-in manually by implementing it. This doesn’t break Rust’s safety guarantees, since Coercible is an unsafe trait.
Because of rule 2b, it is not possible to use Coercible to circumvent privacy restrictions.
The inspiration for this comes entirely from GHC’s Coercible typeclass and matching function coerce, which serve the same purpose as here.