core::intrinsics::transmute - Rust
Description: API documentation for the Rust `transmute` fn in crate `core`.
Keywords: rust, rustlang, rust-lang, transmute

# 1.0.0 (const: 1.46.0)[−][src]Function core::intrinsics::transmute

    pub unsafe extern "rust-intrinsic" fn transmute<T, U>(e: T) -> U

Reinterprets the bits of a value of one type as another type.

Both types must have the same size. Neither the original, nor the result, may be an invalid value.

`transmute` is semantically equivalent to a bitwise move of one type into another. It copies the bits from the source value into the destination value, then forgets the original. It's equivalent to C's `memcpy` under the hood, just like `transmute_copy`.

`transmute` is incredibly unsafe. There are a vast number of ways to cause undefined behavior with this function. `transmute` should be the absolute last resort.

The nomicon has additional documentation.

# Examples

There are a few things that `transmute` is really useful for.

Turning a pointer into a function pointer. This is not portable to machines where function pointers and data pointers have different sizes.

    fn foo() -> i32 {
        0
    }
    let pointer = foo as *const ();
    let function = unsafe {
        std::mem::transmute::<*const (), fn() -> i32>(pointer)
    };
    assert_eq!(function(), 0);

Run

Extending a lifetime, or shortening an invariant lifetime. This is advanced, very unsafe Rust!

    struct R<'a>(&'a i32);
    unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
        std::mem::transmute::<R<'b>, R<'static>>(r)
    }

    unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>)
                                                 -> &'b mut R<'c> {
        std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
    }

Run

# Alternatives

Don't despair: many uses of `transmute` can be achieved through other means. Below are common applications of `transmute` which can be replaced with safer constructs.

Turning raw bytes(`&[u8]`) to `u32`, `f64`, etc.:

    let raw_bytes = [0x78, 0x56, 0x34, 0x12];

    let num = unsafe {
        std::mem::transmute::<[u8; 4], u32>(raw_bytes)
    };

    // use `u32::from_ne_bytes` instead
    let num = u32::from_ne_bytes(raw_bytes);
    // or use `u32::from_le_bytes` or `u32::from_be_bytes` to specify the endianness
    let num = u32::from_le_bytes(raw_bytes);
    assert_eq!(num, 0x12345678);
    let num = u32::from_be_bytes(raw_bytes);
    assert_eq!(num, 0x78563412);

Run

Turning a pointer into a `usize`:

    let ptr = &0;
    let ptr_num_transmute = unsafe {
        std::mem::transmute::<&i32, usize>(ptr)
    };

    // Use an `as` cast instead
    let ptr_num_cast = ptr as *const i32 as usize;

Run

Turning a `*mut T` into an `&mut T`:

    let ptr: *mut i32 = &mut 0;
    let ref_transmuted = unsafe {
        std::mem::transmute::<*mut i32, &mut i32>(ptr)
    };

    // Use a reborrow instead
    let ref_casted = unsafe { &mut *ptr };

Run

Turning an `&mut T` into an `&mut U`:

    let ptr = &mut 0;
    let val_transmuted = unsafe {
        std::mem::transmute::<&mut i32, &mut u32>(ptr)
    };

    // Now, put together `as` and reborrowing - note the chaining of `as`
    // `as` is not transitive
    let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };

Run

Turning an `&str` into an `&[u8]`:

    // this is not a good way to do this.
    let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") };
    assert_eq!(slice, &[82, 117, 115, 116]);

    // You could use `str::as_bytes`
    let slice = "Rust".as_bytes();
    assert_eq!(slice, &[82, 117, 115, 116]);

    // Or, just use a byte string, if you have control over the string
    // literal
    assert_eq!(b"Rust", &[82, 117, 115, 116]);

Run

Turning a `Vec<&T>` into a `Vec<Option<&T>>`:

    let store = [0, 1, 2, 3];
    let v_orig = store.iter().collect::<Vec<&i32>>();

    // clone the vector as we will reuse them later
    let v_clone = v_orig.clone();

    // Using transmute: this relies on the unspecified data layout of `Vec`, which is a
    // bad idea and could cause Undefined Behavior.
    // However, it is no-copy.
    let v_transmuted = unsafe {
        std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone)
    };

    let v_clone = v_orig.clone();

    // This is the suggested, safe way.
    // It does copy the entire vector, though, into a new array.
    let v_collected = v_clone.into_iter()
                             .map(Some)
                             .collect::<Vec<Option<&i32>>>();

    let v_clone = v_orig.clone();

    // The no-copy, unsafe way, still using transmute, but not relying on the data layout.
    // Like the first approach, this reuses the `Vec` internals.
    // Therefore, the new inner type must have the
    // exact same size, *and the same alignment*, as the old type.
    // The same caveats exist for this method as transmute, for
    // the original inner type (`&i32`) to the converted inner type
    // (`Option<&i32>`), so read the nomicon pages linked above and also
    // consult the [`from_raw_parts`] documentation.
    let v_from_raw = unsafe {
        // Ensure the original vector is not dropped.
        let mut v_clone = std::mem::ManuallyDrop::new(v_clone);
        Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,
                            v_clone.len(),
                            v_clone.capacity())
    };

Run

Implementing `split_at_mut`:

    use std::{slice, mem};

    // There are multiple ways to do this, and there are multiple problems
    // with the following (transmute) way.
    fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize)
                                 -> (&mut [T], &mut [T]) {
        let len = slice.len();
        assert!(mid <= len);
        unsafe {
            let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
            // first: transmute is not type safe; all it checks is that T and
            // U are of the same size. Second, right here, you have two
            // mutable references pointing to the same memory.
            (&mut slice[0..mid], &mut slice2[mid..len])
        }
    }

    // This gets rid of the type safety problems; `&mut *` will *only* give
    // you an `&mut T` from an `&mut T` or `*mut T`.
    fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
                             -> (&mut [T], &mut [T]) {
        let len = slice.len();
        assert!(mid <= len);
        unsafe {
            let slice2 = &mut *(slice as *mut [T]);
            // however, you still have two mutable references pointing to
            // the same memory.
            (&mut slice[0..mid], &mut slice2[mid..len])
        }
    }

    // This is how the standard library does it. This is the best method, if
    // you need to do something like this
    fn split_at_stdlib<T>(slice: &mut [T], mid: usize)
                          -> (&mut [T], &mut [T]) {
        let len = slice.len();
        assert!(mid <= len);
        unsafe {
            let ptr = slice.as_mut_ptr();
            // This now has three mutable references pointing at the same
            // memory. `slice`, the rvalue ret.0, and the rvalue ret.1.
            // `slice` is never used after `let ptr = ...`, and so one can
            // treat it as "dead", and therefore, you only have two real
            // mutable slices.
            (slice::from_raw_parts_mut(ptr, mid),
             slice::from_raw_parts_mut(ptr.add(mid), len - mid))
        }
    }

Run