transmutability.rs - source
Description: Source of the Rust file `library/core/src/mem/transmutability.rs`.

#
core/mem/
transmutability.rs

    1use crate::marker::ConstParamTy_;
    2
    3/// Marks that `Src` is transmutable into `Self`.
    4///
    5/// # Implementation
    6///
    7/// This trait cannot be implemented explicitly. It is implemented on-the-fly by
    8/// the compiler for all types `Src` and `Self` such that, given a set of safety
    9/// obligations on the programmer (see [`Assume`]), the compiler has proved that
    10/// the bits of a value of type `Src` can be soundly reinterpreted as a `Self`.
    11///
    12/// # Safety
    13///
    14/// If `Dst: TransmuteFrom<Src, ASSUMPTIONS>`, the compiler guarantees that
    15/// `Src` is soundly *union-transmutable* into a value of type `Dst`, provided
    16/// that the programmer has guaranteed that the given [`ASSUMPTIONS`](Assume)
    17/// are satisfied.
    18///
    19/// A union-transmute is any bit-reinterpretation conversion in the form of:
    20///
    21/// ```rust
    22/// pub unsafe fn transmute_via_union<Src, Dst>(src: Src) -> Dst {
    23///     use core::mem::ManuallyDrop;
    24///
    25///     #[repr(C)]
    26///     union Transmute<Src, Dst> {
    27///         src: ManuallyDrop<Src>,
    28///         dst: ManuallyDrop<Dst>,
    29///     }
    30///
    31///     let transmute = Transmute {
    32///         src: ManuallyDrop::new(src),
    33///     };
    34///
    35///     let dst = unsafe { transmute.dst };
    36///
    37///     ManuallyDrop::into_inner(dst)
    38/// }
    39/// ```
    40///
    41/// Note that this construction is more permissive than
    42/// [`mem::transmute_copy`](super::transmute_copy); union-transmutes permit
    43/// conversions that extend the bits of `Src` with trailing padding to fill
    44/// trailing uninitialized bytes of `Self`; e.g.:
    45///
    46/// ```rust
    47/// #![feature(transmutability)]
    48///
    49/// use core::mem::{Assume, TransmuteFrom};
    50///
    51/// let src = 42u8; // size = 1
    52///
    53/// #[repr(C, align(2))]
    54/// struct Dst(u8); // size = 2
    55//
    56/// let _ = unsafe {
    57///     <Dst as TransmuteFrom<u8, { Assume::SAFETY }>>::transmute(src)
    58/// };
    59/// ```
    60///
    61/// # Caveats
    62///
    63/// ## Portability
    64///
    65/// Implementations of this trait do not provide any guarantee of portability
    66/// across toolchains, targets or compilations. This trait may be implemented
    67/// for certain combinations of `Src`, `Self` and `ASSUME` on some toolchains,
    68/// targets or compilations, but not others. For example, if the layouts of
    69/// `Src` or `Self` are non-deterministic, the presence or absence of an
    70/// implementation of this trait may also be non-deterministic. Even if `Src`
    71/// and `Self` have deterministic layouts (e.g., they are `repr(C)` structs),
    72/// Rust does not specify the alignments of its primitive integer types, and
    73/// layouts that involve these types may vary across toolchains, targets or
    74/// compilations.
    75///
    76/// ## Stability
    77///
    78/// Implementations of this trait do not provide any guarantee of SemVer
    79/// stability across the crate versions that define the `Src` and `Self` types.
    80/// If SemVer stability is crucial to your application, you must consult the
    81/// documentation of `Src` and `Self`s' defining crates. Note that the presence
    82/// of `repr(C)`, alone, does not carry a safety invariant of SemVer stability.
    83/// Furthermore, stability does not imply portability. For example, the size of
    84/// `usize` is stable, but not portable.
    85#[unstable(feature = "transmutability", issue = "99571")]
    86#[unstable_feature_bound(transmutability)]
    87#[lang = "transmute_trait"]
    88#[rustc_deny_explicit_impl]
    89#[rustc_do_not_implement_via_object]
    90#[rustc_coinductive]
    91pub unsafe trait TransmuteFrom<Src, const ASSUME: Assume = { Assume::NOTHING }>
    92where
    93    Src: ?Sized,
    94{
    95    /// Transmutes a `Src` value into a `Self`.
    96    ///
    97    /// # Safety
    98    ///
    99    /// The safety obligations of the caller depend on the value of `ASSUME`:
    100    /// - If [`ASSUME.alignment`](Assume::alignment), the caller must guarantee
    101    ///   that the addresses of references in the returned `Self` satisfy the
    102    ///   alignment requirements of their referent types.
    103    /// - If [`ASSUME.lifetimes`](Assume::lifetimes), the caller must guarantee
    104    ///   that references in the returned `Self` will not outlive their
    105    ///   referents.
    106    /// - If [`ASSUME.safety`](Assume::safety), the returned value might not
    107    ///   satisfy the library safety invariants of `Self`, and the caller must
    108    ///   guarantee that undefined behavior does not arise from uses of the
    109    ///   returned value.
    110    /// - If [`ASSUME.validity`](Assume::validity), the caller must guarantee
    111    ///   that `src` is a bit-valid instance of `Self`.
    112    ///
    113    /// When satisfying the above obligations (if any), the caller must *not*
    114    /// assume that this trait provides any inherent guarantee of layout
    115    /// [portability](#portability) or [stability](#stability).
    116    unsafe fn transmute(src: Src) -> Self
    117    where
    118        Src: Sized,
    119        Self: Sized,
    120    {
    121        use super::ManuallyDrop;
    122
    123        #[repr(C)]
    124        union Transmute<Src, Dst> {
    125            src: ManuallyDrop<Src>,
    126            dst: ManuallyDrop<Dst>,
    127        }
    128
    129        let transmute = Transmute { src: ManuallyDrop::new(src) };
    130
    131        // SAFETY: It is safe to reinterpret the bits of `src` as a value of
    132        // type `Self`, because, by combination of invariant on this trait and
    133        // contract on the caller, `src` has been proven to satisfy both the
    134        // language and library invariants of `Self`. For all invariants not
    135        // `ASSUME`'d by the caller, the safety obligation is supplied by the
    136        // compiler. Conversely, for all invariants `ASSUME`'d by the caller,
    137        // the safety obligation is supplied by contract on the caller.
    138        let dst = unsafe { transmute.dst };
    139
    140        ManuallyDrop::into_inner(dst)
    141    }
    142}
    143
    144/// Configurable proof assumptions of [`TransmuteFrom`].
    145///
    146/// When `false`, the respective proof obligation belongs to the compiler. When
    147/// `true`, the onus of the safety proof belongs to the programmer.
    148#[unstable(feature = "transmutability", issue = "99571")]
    149#[lang = "transmute_opts"]
    150#[derive(PartialEq, Eq, Clone, Copy, Debug)]
    151pub struct Assume {
    152    /// When `false`, [`TransmuteFrom`] is not implemented for transmutations
    153    /// that might violate the alignment requirements of references; e.g.:
    154    ///
    155    /// ```compile_fail,E0277
    156    /// #![feature(transmutability)]
    157    /// use core::mem::TransmuteFrom;
    158    ///
    159    /// assert_eq!(align_of::<[u8; 2]>(), 1);
    160    /// assert_eq!(align_of::<u16>(), 2);
    161    ///
    162    /// let src: &[u8; 2] = &[0xFF, 0xFF];
    163    ///
    164    /// // SAFETY: No safety obligations.
    165    /// let dst: &u16 = unsafe {
    166    ///     <_ as TransmuteFrom<_>>::transmute(src)
    167    /// };
    168    /// ```
    169    ///
    170    /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured
    171    /// that references in the transmuted value satisfy the alignment
    172    /// requirements of their referent types; e.g.:
    173    ///
    174    /// ```rust
    175    /// #![feature(pointer_is_aligned_to, transmutability)]
    176    /// use core::mem::{Assume, TransmuteFrom};
    177    ///
    178    /// let src: &[u8; 2] = &[0xFF, 0xFF];
    179    ///
    180    /// let maybe_dst: Option<&u16> = if <*const _>::is_aligned_to(src, align_of::<u16>()) {
    181    ///     // SAFETY: We have checked above that the address of `src` satisfies the
    182    ///     // alignment requirements of `u16`.
    183    ///     Some(unsafe {
    184    ///         <_ as TransmuteFrom<_, { Assume::ALIGNMENT }>>::transmute(src)
    185    ///     })
    186    /// } else {
    187    ///     None
    188    /// };
    189    ///
    190    /// assert!(matches!(maybe_dst, Some(&u16::MAX) | None));
    191    /// ```
    192    pub alignment: bool,
    193
    194    /// When `false`, [`TransmuteFrom`] is not implemented for transmutations
    195    /// that extend the lifetimes of references.
    196    ///
    197    /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured that
    198    /// references in the transmuted value do not outlive their referents.
    199    pub lifetimes: bool,
    200
    201    /// When `false`, [`TransmuteFrom`] is not implemented for transmutations
    202    /// that might violate the library safety invariants of the destination
    203    /// type; e.g.:
    204    ///
    205    /// ```compile_fail,E0277
    206    /// #![feature(transmutability)]
    207    /// use core::mem::TransmuteFrom;
    208    ///
    209    /// let src: u8 = 3;
    210    ///
    211    /// struct EvenU8 {
    212    ///     // SAFETY: `val` must be an even number.
    213    ///     val: u8,
    214    /// }
    215    ///
    216    /// // SAFETY: No safety obligations.
    217    /// let dst: EvenU8 = unsafe {
    218    ///     <_ as TransmuteFrom<_>>::transmute(src)
    219    /// };
    220    /// ```
    221    ///
    222    /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured
    223    /// that undefined behavior does not arise from using the transmuted value;
    224    /// e.g.:
    225    ///
    226    /// ```rust
    227    /// #![feature(transmutability)]
    228    /// use core::mem::{Assume, TransmuteFrom};
    229    ///
    230    /// let src: u8 = 42;
    231    ///
    232    /// struct EvenU8 {
    233    ///     // SAFETY: `val` must be an even number.
    234    ///     val: u8,
    235    /// }
    236    ///
    237    /// let maybe_dst: Option<EvenU8> = if src % 2 == 0 {
    238    ///     // SAFETY: We have checked above that the value of `src` is even.
    239    ///     Some(unsafe {
    240    ///         <_ as TransmuteFrom<_, { Assume::SAFETY }>>::transmute(src)
    241    ///     })
    242    /// } else {
    243    ///     None
    244    /// };
    245    ///
    246    /// assert!(matches!(maybe_dst, Some(EvenU8 { val: 42 })));
    247    /// ```
    248    pub safety: bool,
    249
    250    /// When `false`, [`TransmuteFrom`] is not implemented for transmutations
    251    /// that might violate the language-level bit-validity invariant of the
    252    /// destination type; e.g.:
    253    ///
    254    /// ```compile_fail,E0277
    255    /// #![feature(transmutability)]
    256    /// use core::mem::TransmuteFrom;
    257    ///
    258    /// let src: u8 = 3;
    259    ///
    260    /// // SAFETY: No safety obligations.
    261    /// let dst: bool = unsafe {
    262    ///     <_ as TransmuteFrom<_>>::transmute(src)
    263    /// };
    264    /// ```
    265    ///
    266    /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured
    267    /// that the value being transmuted is a bit-valid instance of the
    268    /// transmuted value; e.g.:
    269    ///
    270    /// ```rust
    271    /// #![feature(transmutability)]
    272    /// use core::mem::{Assume, TransmuteFrom};
    273    ///
    274    /// let src: u8 = 1;
    275    ///
    276    /// let maybe_dst: Option<bool> = if src == 0 || src == 1 {
    277    ///     // SAFETY: We have checked above that the value of `src` is a bit-valid
    278    ///     // instance of `bool`.
    279    ///     Some(unsafe {
    280    ///         <_ as TransmuteFrom<_, { Assume::VALIDITY }>>::transmute(src)
    281    ///     })
    282    /// } else {
    283    ///     None
    284    /// };
    285    ///
    286    /// assert_eq!(maybe_dst, Some(true));
    287    /// ```
    288    pub validity: bool,
    289}
    290
    291#[unstable(feature = "transmutability", issue = "99571")]
    292#[unstable_feature_bound(transmutability)]
    293impl ConstParamTy_ for Assume {}
    294
    295impl Assume {
    296    /// With this, [`TransmuteFrom`] does not assume you have ensured any safety
    297    /// obligations are met, and relies only upon its own analysis to (dis)prove
    298    /// transmutability.
    299    #[unstable(feature = "transmutability", issue = "99571")]
    300    pub const NOTHING: Self =
    301        Self { alignment: false, lifetimes: false, safety: false, validity: false };
    302
    303    /// With this, [`TransmuteFrom`] assumes only that you have ensured that
    304    /// references in the transmuted value satisfy the alignment requirements of
    305    /// their referent types. See [`Assume::alignment`] for examples.
    306    #[unstable(feature = "transmutability", issue = "99571")]
    307    pub const ALIGNMENT: Self = Self { alignment: true, ..Self::NOTHING };
    308
    309    /// With this, [`TransmuteFrom`] assumes only that you have ensured that
    310    /// references in the transmuted value do not outlive their referents. See
    311    /// [`Assume::lifetimes`] for examples.
    312    #[unstable(feature = "transmutability", issue = "99571")]
    313    pub const LIFETIMES: Self = Self { lifetimes: true, ..Self::NOTHING };
    314
    315    /// With this, [`TransmuteFrom`] assumes only that you have ensured that
    316    /// undefined behavior does not arise from using the transmuted value. See
    317    /// [`Assume::safety`] for examples.
    318    #[unstable(feature = "transmutability", issue = "99571")]
    319    pub const SAFETY: Self = Self { safety: true, ..Self::NOTHING };
    320
    321    /// With this, [`TransmuteFrom`] assumes only that you have ensured that the
    322    /// value being transmuted is a bit-valid instance of the transmuted value.
    323    /// See [`Assume::validity`] for examples.
    324    #[unstable(feature = "transmutability", issue = "99571")]
    325    pub const VALIDITY: Self = Self { validity: true, ..Self::NOTHING };
    326
    327    /// Combine the assumptions of `self` and `other_assumptions`.
    328    ///
    329    /// This is especially useful for extending [`Assume`] in generic contexts;
    330    /// e.g.:
    331    ///
    332    /// ```rust
    333    /// #![feature(
    334    ///     adt_const_params,
    335    ///     generic_const_exprs,
    336    ///     pointer_is_aligned_to,
    337    ///     transmutability,
    338    /// )]
    339    /// #![allow(incomplete_features)]
    340    /// use core::mem::{Assume, TransmuteFrom};
    341    ///
    342    /// /// Attempts to transmute `src` to `&Dst`.
    343    /// ///
    344    /// /// Returns `None` if `src` violates the alignment requirements of `&Dst`.
    345    /// ///
    346    /// /// # Safety
    347    /// ///
    348    /// /// The caller guarantees that the obligations required by `ASSUME`, except
    349    /// /// alignment, are satisfied.
    350    /// unsafe fn try_transmute_ref<'a, Src, Dst, const ASSUME: Assume>(src: &'a Src) -> Option<&'a Dst>
    351    /// where
    352    ///     &'a Dst: TransmuteFrom<&'a Src, { ASSUME.and(Assume::ALIGNMENT) }>,
    353    /// {
    354    ///     if <*const _>::is_aligned_to(src, align_of::<Dst>()) {
    355    ///         // SAFETY: By the above dynamic check, we have ensured that the address
    356    ///         // of `src` satisfies the alignment requirements of `&Dst`. By contract
    357    ///         // on the caller, the safety obligations required by `ASSUME` have also
    358    ///         // been satisfied.
    359    ///         Some(unsafe {
    360    ///             <_ as TransmuteFrom<_, { ASSUME.and(Assume::ALIGNMENT) }>>::transmute(src)
    361    ///         })
    362    ///     } else {
    363    ///         None
    364    ///     }
    365    /// }
    366    ///
    367    /// let src: &[u8; 2] = &[0xFF, 0xFF];
    368    ///
    369    /// // SAFETY: No safety obligations.
    370    /// let maybe_dst: Option<&u16> = unsafe {
    371    ///     try_transmute_ref::<_, _, { Assume::NOTHING }>(src)
    372    /// };
    373    ///```
    374    #[unstable(feature = "transmutability", issue = "99571")]
    375    pub const fn and(self, other_assumptions: Self) -> Self {
    376        Self {
    377            alignment: self.alignment || other_assumptions.alignment,
    378            lifetimes: self.lifetimes || other_assumptions.lifetimes,
    379            safety: self.safety || other_assumptions.safety,
    380            validity: self.validity || other_assumptions.validity,
    381        }
    382    }
    383
    384    /// Remove `other_assumptions` the obligations of `self`; e.g.:
    385    ///
    386    /// ```rust
    387    /// #![feature(transmutability)]
    388    /// use core::mem::Assume;
    389    ///
    390    /// let assumptions = Assume::ALIGNMENT.and(Assume::SAFETY);
    391    /// let to_be_removed = Assume::SAFETY.and(Assume::VALIDITY);
    392    ///
    393    /// assert_eq!(
    394    ///     assumptions.but_not(to_be_removed),
    395    ///     Assume::ALIGNMENT,
    396    /// );
    397    /// ```
    398    #[unstable(feature = "transmutability", issue = "99571")]
    399    pub const fn but_not(self, other_assumptions: Self) -> Self {
    400        Self {
    401            alignment: self.alignment && !other_assumptions.alignment,
    402            lifetimes: self.lifetimes && !other_assumptions.lifetimes,
    403            safety: self.safety && !other_assumptions.safety,
    404            validity: self.validity && !other_assumptions.validity,
    405        }
    406    }
    407}
    408
    409// FIXME(jswrenn): This const op is not actually usable. Why?
    410// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926
    411#[unstable(feature = "transmutability", issue = "99571")]
    412impl core::ops::Add for Assume {
    413    type Output = Assume;
    414
    415    fn add(self, other_assumptions: Assume) -> Assume {
    416        self.and(other_assumptions)
    417    }
    418}
    419
    420// FIXME(jswrenn): This const op is not actually usable. Why?
    421// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926
    422#[unstable(feature = "transmutability", issue = "99571")]
    423impl core::ops::Sub for Assume {
    424    type Output = Assume;
    425
    426    fn sub(self, other_assumptions: Assume) -> Assume {
    427        self.but_not(other_assumptions)
    428    }
    429}