Casting Between Types

Rust, with its focus on safety, provides two different ways of casting different types between each other. The first, as`as, is for safe casts. In contrast,`, is for safe casts. In contrast, transmute`transmute` allows for arbitrary casting, and is one of the most dangerous features of Rust!

as`as`

The as`as` keyword does basic casting:

fn main() { let x: i32 = 5; let y = x as i64; }
let x: i32 = 5;

let y = x as i64;

It only allows certain kinds of casting, however:

fn main() { let a = [0u8, 0u8, 0u8, 0u8]; let b = a as u32; // four eights makes 32 }
let a = [0u8, 0u8, 0u8, 0u8];

let b = a as u32; // four eights makes 32

This errors with:

error: non-scalar cast: `[u8; 4]` as `u32`
let b = a as u32; // four eights makes 32
        ^~~~~~~~

It’s a ‘non-scalar cast’ because we have multiple values here: the four elements of the array. These kinds of casts are very dangerous, because they make assumptions about the way that multiple underlying structures are implemented. For this, we need something more dangerous.

transmute`transmute`

The transmute`transmute` function is provided by a compiler intrinsic, and what it does is very simple, but very scary. It tells Rust to treat a value of one type as though it were another type. It does this regardless of the typechecking system, and just completely trusts you.

In our previous example, we know that an array of four u8`u8s represents a`s represents a u32`u32properly, and so we want to do the cast. Using` properly, and so we want to do the cast. Using transmute`transmuteinstead of` instead of as`as`, Rust lets us:

fn main() { use std::mem; unsafe { let a = [0u8, 0u8, 0u8, 0u8]; let b = mem::transmute::<[u8; 4], u32>(a); } }
use std::mem;

unsafe {
    let a = [0u8, 0u8, 0u8, 0u8];

    let b = mem::transmute::<[u8; 4], u32>(a);
}

We have to wrap the operation in an unsafe`unsafeblock for this to compile successfully. Technically, only the` block for this to compile successfully. Technically, only the mem::transmute`mem::transmutecall itself needs to be in the block, but it's nice in this case to enclose everything related, so you know where to look. In this case, the details about` call itself needs to be in the block, but it's nice in this case to enclose everything related, so you know where to look. In this case, the details about a`aare also important, and so they're in the block. You'll see code in either style, sometimes the context is too far away, and wrapping all of the code in` are also important, and so they're in the block. You'll see code in either style, sometimes the context is too far away, and wrapping all of the code in unsafe`unsafe` isn't a great idea.

While transmute`transmute` does very little checking, it will at least make sure that the types are the same size. This errors:

fn main() { use std::mem; unsafe { let a = [0u8, 0u8, 0u8, 0u8]; let b = mem::transmute::<[u8; 4], u64>(a); } }
use std::mem;

unsafe {
    let a = [0u8, 0u8, 0u8, 0u8];

    let b = mem::transmute::<[u8; 4], u64>(a);
}

with:

error: transmute called on types with different sizes: [u8; 4] (32 bits) to u64
(64 bits)

Other than that, you're on your own!