]> git.lizzy.rs Git - rust.git/blob - src/doc/book/casting-between-types.md
148c55e4b9732c96f94e9f8894c65aa2b9465505
[rust.git] / src / doc / book / casting-between-types.md
1 % Casting Between Types
2
3 Rust, with its focus on safety, provides two different ways of casting
4 different types between each other. The first, `as`, is for safe casts.
5 In contrast, `transmute` allows for arbitrary casting, and is one of the
6 most dangerous features of Rust!
7
8 # `as`
9
10 The `as` keyword does basic casting:
11
12 ```rust
13 let x: i32 = 5;
14
15 let y = x as i64;
16 ```
17
18 It only allows certain kinds of casting, however:
19
20 ```rust,ignore
21 let a = [0u8, 0u8, 0u8, 0u8];
22
23 let b = a as u32; // four eights makes 32
24 ```
25
26 This errors with:
27
28 ```text
29 error: non-scalar cast: `[u8; 4]` as `u32`
30 let b = a as u32; // four eights makes 32
31         ^~~~~~~~
32 ```
33
34 It’s a ‘non-scalar cast’ because we have multiple values here: the four
35 elements of the array. These kinds of casts are very dangerous, because they
36 make assumptions about the way that multiple underlying structures are
37 implemented. For this, we need something more dangerous.
38
39 # `transmute`
40
41 The `transmute` function is provided by a [compiler intrinsic][intrinsics], and
42 what it does is very simple, but very scary. It tells Rust to treat a value of
43 one type as though it were another type. It does this regardless of the
44 typechecking system, and just completely trusts you.
45
46 [intrinsics]: intrinsics.html
47
48 In our previous example, we know that an array of four `u8`s represents a `u32`
49 properly, and so we want to do the cast. Using `transmute` instead of `as`,
50 Rust lets us:
51
52 ```rust
53 use std::mem;
54
55 unsafe {
56     let a = [0u8, 0u8, 0u8, 0u8];
57
58     let b = mem::transmute::<[u8; 4], u32>(a);
59 }
60 ```
61
62 We have to wrap the operation in an `unsafe` block for this to compile
63 successfully. Technically, only the `mem::transmute` call itself needs to be in
64 the block, but it's nice in this case to enclose everything related, so you
65 know where to look. In this case, the details about `a` are also important, and
66 so they're in the block. You'll see code in either style, sometimes the context
67 is too far away, and wrapping all of the code in `unsafe` isn't a great idea.
68
69 While `transmute` does very little checking, it will at least make sure that
70 the types are the same size. This errors:
71
72 ```rust,ignore
73 use std::mem;
74
75 unsafe {
76     let a = [0u8, 0u8, 0u8, 0u8];
77
78     let b = mem::transmute::<[u8; 4], u64>(a);
79 }
80 ```
81
82 with:
83
84 ```text
85 error: transmute called with differently sized types: [u8; 4] (32 bits) to u64
86 (64 bits)
87 ```
88
89 Other than that, you're on your own!