|
1 | 1 | # Casts
|
2 | 2 |
|
3 |
| -Casts are a superset of coercions: every coercion can be explicitly |
4 |
| -invoked via a cast. However some conversions require a cast. |
5 |
| -While coercions are pervasive and largely harmless, these "true casts" |
6 |
| -are rare and potentially dangerous. As such, casts must be explicitly invoked |
7 |
| -using the `as` keyword: `expr as Type`. |
| 3 | +Casts are a superset of coercions: every coercion can be explicitly invoked via a cast. |
| 4 | +However some conversions require a cast. |
| 5 | +While coercions are pervasive and largely harmless, these "true casts" are rare and potentially dangerous. |
| 6 | +As such, casts must be explicitly invoked using the `as` keyword: `expr as Type`. |
8 | 7 |
|
9 |
| -True casts generally revolve around raw pointers and the primitive numeric |
10 |
| -types. Even though they're dangerous, these casts are infallible at runtime. |
11 |
| -If a cast triggers some subtle corner case no indication will be given that |
12 |
| -this occurred. The cast will simply succeed. That said, casts must be valid |
13 |
| -at the type level, or else they will be prevented statically. For instance, |
14 |
| -`7u8 as bool` will not compile. |
| 8 | +You can find an exhaustive list of [all the true casts][cast list] and [casting semantics][semantics list] on the reference. |
15 | 9 |
|
16 |
| -That said, casts aren't `unsafe` because they generally can't violate memory |
17 |
| -safety *on their own*. For instance, converting an integer to a raw pointer can |
18 |
| -very easily lead to terrible things. However the act of creating the pointer |
19 |
| -itself is safe, because actually using a raw pointer is already marked as |
20 |
| -`unsafe`. |
| 10 | +## Safety of casting |
21 | 11 |
|
22 |
| -Here's an exhaustive list of all the true casts. For brevity, we will use `*` |
23 |
| -to denote either a `*const` or `*mut`, and `integer` to denote any integral |
24 |
| -primitive: |
| 12 | +True casts generally revolve around raw pointers and the primitive numeric types. |
| 13 | +Even though they're dangerous, these casts are infallible at runtime. |
| 14 | +If a cast triggers some subtle corner case no indication will be given that this occurred. |
| 15 | +The cast will simply succeed. |
| 16 | +That said, casts must be valid at the type level, or else they will be prevented statically. |
| 17 | +For instance, `7u8 as bool` will not compile. |
25 | 18 |
|
26 |
| -* `*T as *U` where `T, U: Sized` |
27 |
| -* `*T as *U` TODO: explain unsized situation |
28 |
| -* `*T as integer` |
29 |
| -* `integer as *T` |
30 |
| -* `number as number` |
31 |
| -* `field-less enum as integer` |
32 |
| -* `bool as integer` |
33 |
| -* `char as integer` |
34 |
| -* `u8 as char` |
35 |
| -* `&[T; n] as *const T` |
36 |
| -* `fn as *T` where `T: Sized` |
37 |
| -* `fn as integer` |
| 19 | +That said, casts aren't `unsafe` because they generally can't violate memory safety *on their own*. |
| 20 | +For instance, converting an integer to a raw pointer can very easily lead to terrible things. |
| 21 | +However the act of creating the pointer itself is safe, because actually using a raw pointer is already marked as `unsafe`. |
38 | 22 |
|
39 |
| -Note that lengths are not adjusted when casting raw slices - |
40 |
| -`*const [u16] as *const [u8]` creates a slice that only includes |
41 |
| -half of the original memory. |
| 23 | +## Some notes about casting |
42 | 24 |
|
43 |
| -Casting is not transitive, that is, even if `e as U1 as U2` is a valid |
44 |
| -expression, `e as U2` is not necessarily so. |
| 25 | +### Lengths when casting raw slices |
45 | 26 |
|
46 |
| -For numeric casts, there are quite a few cases to consider: |
| 27 | +Note that lengths are not adjusted when casting raw slices; `*const [u16] as *const [u8]` creates a slice that only includes half of the original memory. |
47 | 28 |
|
48 |
| -* casting between two integers of the same size (e.g. i32 -> u32) is a no-op |
49 |
| - (Rust uses 2's complement for negative values of fixed integers) |
50 |
| -* casting from a larger integer to a smaller integer (e.g. u32 -> u8) will |
51 |
| - truncate |
52 |
| -* casting from a smaller integer to a larger integer (e.g. u8 -> u32) will |
53 |
| - * zero-extend if the source is unsigned |
54 |
| - * sign-extend if the source is signed |
55 |
| -* casting from a float to an integer will round the float towards zero and |
56 |
| - produces a "saturating cast" when the float is outside the integer's range |
57 |
| - * floats that are too big turn into the largest possible integer |
58 |
| - * floats that are too small produce the smallest possible integer |
59 |
| - * NaN produces zero |
60 |
| -* casting from an integer to float will produce the floating point |
61 |
| - representation of the integer, rounded if necessary (rounding to |
62 |
| - nearest, ties to even) |
63 |
| -* casting from an f32 to an f64 is perfect and lossless |
64 |
| -* casting from an f64 to an f32 will produce the closest possible value |
65 |
| - (rounding to nearest, ties to even) |
| 29 | +### Transitivity |
| 30 | + |
| 31 | +Casting is not transitive, that is, even if `e as U1 as U2` is a valid expression, `e as U2` is not necessarily so. |
| 32 | + |
| 33 | +[cast list]: ../reference/expressions/operator-expr.html#type-cast-expressions |
| 34 | +[semantics list]: ../reference/expressions/operator-expr.html#semantics |
0 commit comments