Overview
We propose that this compiler-intrinsic trait (end-users cannot implement it) be added to core::mem
:
pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume>
where
Src: ?Sized
{}
This trait is capable of telling you whether a particular bit-reinterpretation cast from Src
to Self
is well-defined and safe (notwithstanding whatever static checks you decide to Assume
).
This trait is useful:
When is a transmutation well-defined and safe?
A transmutation is well-defined if any possible values of type Src
are a valid instance of Dst
. The compiler determines this by inspecting the layouts of Src
and Dst
.
In order to be safe, a well-defined transmutation must also not allow you to:
- construct instances of a hidden
Dst
type - mutate hidden fields of the
Src
type - construct hidden fields of the
Dst
type
Whether these conditions are satisfied depends on the scope the transmutation occurs in. The existing mechanism of type privacy will ensure that first condition is satisfied. To enforce the second and third conditions, we introduce the Context
type parameter (see below).
What is Assume
?
The Assume
parameter encodes the set of static checks that the compiler should ignore when determining transmutability. These checks include:
- alignment
- lifetimes
- validity
- visibility
The Assume
type is represented like this:
#[derive(PartialEq, Eq)]
#[non_exhaustive]
pub struct Assume {
pub alignment : bool,
pub lifetimes : bool,
pub validity : bool,
pub visibility : bool,
}
impl Assume {
pub const NOTHING: Self = Self {
alignment : false,
lifetimes : false,
validity : false,
visibility : false,
};
pub const ALIGNMENT: Self = Self {alignment: true, ..Self::NOTHING};
pub const LIFETIMES: Self = Self {lifetimes: true, ..Self::NOTHING};
pub const VALIDITY: Self = Self {validity: true, ..Self::NOTHING};
pub const VISIBILITY: Self = Self {validity: true, ..Self::NOTHING};
}
impl const core::ops::Add for Assume {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
alignment : self.alignment || other.alignment,
lifetimes : self.lifetimes || other.lifetimes,
validity : self.validity || other.validity,
visibility : self.visibility || other.visibility,
}
}
}
For more information, see here.
What is Context
?
The Context
parameter of BikeshedIntrinsicFrom
is used to ensure that the second and third safety conditions are satisfied.
When visibility is enforced, Context
must be instantiated with any private (i.e., pub(self)
type. The compiler pretends that it is at the defining scope of that type, and checks that the necessary fields of Src
and Dst
are visible.
When visibility is assumed, the Context
parameter is ignored.
For more information, see here.