about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSteve Klabnik <steve@steveklabnik.com>2015-04-20 11:55:21 -0400
committerSteve Klabnik <steve@steveklabnik.com>2015-04-20 11:55:29 -0400
commit9a650456117284bc8fb9aa5e976531ad539bcd7d (patch)
treef6c580fba8dda0c97be1fdf3d52347af19254fe6
parent5910dc0e8e396a4af7b948b83bab03f27b414a0e (diff)
downloadrust-9a650456117284bc8fb9aa5e976531ad539bcd7d.tar.gz
rust-9a650456117284bc8fb9aa5e976531ad539bcd7d.zip
TRPL: casting
Due to documenting `transmute`, addresses part of #12905
-rw-r--r--src/doc/trpl/casting-between-types.md88
1 files changed, 87 insertions, 1 deletions
diff --git a/src/doc/trpl/casting-between-types.md b/src/doc/trpl/casting-between-types.md
index 8bb0ec6db02..90731b64a38 100644
--- a/src/doc/trpl/casting-between-types.md
+++ b/src/doc/trpl/casting-between-types.md
@@ -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
+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
+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!