Skip to content

TRPL: casting #24632

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 21, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 87 additions & 1 deletion src/doc/trpl/casting-between-types.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,89 @@
% Casting Between Types

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

# `as`

The `as` keyword does basic casting:

```rust
let x: i32 = 5;

let y = x as i64;
```

It only allows certain kinds of casting, however:

```rust,ignore
let a = [0u8, 0u8, 0u8, 0u8];

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

This errors with:

```text
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 strucutres are
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/strucutres/structures/

implemented. For this, we need something more dangerous.

# `transmute`

The `transmute` function is provided by a [compiler intrinsic][intrinsics], 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.

[intrinsic]: intrinsics.html

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

```rust
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` block, but this will compile
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

block~~, but this will~~ [for this to] compile successfully

I think this is better...

successfully. Technically, only the `mem::transmute` 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` 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` isn't a great idea.

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

```rust,ignore
use std::mem;

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

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

with:

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

Other than that, you're on your own!