[][src]Module typic::transmute::safe_transmutation

Guidance and tools for safe transmutation.

A sound transmutation is safe only if the resulting value cannot possibly violate library-enforced invariants. Typic assumes that all non-zero-sized fields with any visibility besides pub could have library-enforced invariants.

Why is safety different than soundness?

Consider the type Constrained, which enforces a validity constraint on its fields, and the type Unconstrained (which has no internal validity constraints):

#[typic::repr(C)]
#[derive(StableABI)]
pub struct Constrained {
    wizz: i8,
    bang: u8,
}

impl Constrained {
    /// the sum of `wizz` and `bang` must be greater than or equal to zero.
    pub fn new(wizz: i8, bang: u8) -> Self {
        assert!((wizz as i16) / (bang as i16) >= 0);
        Constrained { wizz, bang }
    }

    pub fn something_dangerous(&self) {
        unsafe {
            // do something that's only safe if `wizz + bang >= 0`
        }
    }
}

#[typic::repr(C)]
#[derive(StableABI)]
pub struct Unconstrained {
    pub wizz: u8,
    pub bang: i8,
}

It is sound to transmute an instance of Unconstrained into Constrained:

use typic::docs::prelude::*;
use typic::transmute::neglect;
let _ : Constrained  = unsafe { unsafe_transmute::<_, _, neglect::Transparency>(Unconstrained::default()) };

...but it is not safe! The unsafe_transmute function creates an instance of Bar without calling its new constructor, thereby bypassing the safety check which ensures something_dangerous does not violate Rust's memory model. The compiler will reject our program if we try to safely transmute Unconstrained to Constrained:

This example deliberately fails to compile
let unconstrained = Unconstrained::default();
let _ : Constrained  = unconstrained.transmute_into();

Or, automatically, by marking the fields pub:

#[typic::repr(C)]
#[derive(StableABI)]
pub struct Unconstrained {
    pub wizz: u8,
    pub bang: i8,
}

let _ : Unconstrained = u16::default().transmute_into();

If the fields are marked pub, the type cannot possibly rely on any internal validity requirements, as users of the type are free to manipulate its fields direclty via the . operator.

This rule applies to private fields that are zero-sized. It is safe to transmute from Bar to Foo, because Foo's constructor is pub:

#[typic::repr(C)]
#[derive(StableABI)]
struct ZST;

#[typic::repr(C)]
#[derive(StableABI)]
struct Foo(pub ZST);

#[typic::repr(C)]
#[derive(StableABI)]
struct Bar(ZST);

let _ : Foo = Bar(ZST).transmute_into();

It is not safe to transmute from Foo to Bar, because Bar's constructor is not public:

This example deliberately fails to compile
let _ : Bar = Foo(ZST).transmute_into();

Safely transmuting references

When safely transmuting owned values, all non-padding bytes in the source type must correspond to pub bytes in the destination type:

let _ : Unconstrained = Constrained::default().transmute_into();

The visibility (or lack thereof) of bytes in the source type does not affect safety.

When safely transmuting references, each corresponding byte in the source and destination types must have the same visibility. Without this restriction, you could inadvertently violate library invariants of a type by transmuting and mutating a mutable reference to it:

This example deliberately fails to compile
let mut x = Constrained::default();

{
    let y : &mut Unconstrained = (&mut x).transmute_into();
                                       // ^^^^^^^^^^^^^^
                                       // Compile Error!
    let z : u8 = -100i8.transmute_into();
    y.wizz = z;
}

// Ack! `x.wizz + x.bang` is now -100!
// This violates the safety invariant of `something_dangerous`!
x.something_dangerous();

Modules

neglect

Configuration options for safe transmutations.

Traits

StableTransmuteInto

For ergonomics, until rust-lang/rust#27336 is resolved.

TransmuteFrom

A safe and sound value-to-value conversion. The reciprocal of TransmuteInto.

TransmuteInto

A safe and sound value-to-value conversion. The reciprocal of TransmuteFrom.

TransmuteOptions

Options for safe and unsafe transmutation.

Functions

safe_transmute

A safe and sound value-to-value conversion.