@@ -5,17 +5,127 @@ different types between each other. The first, `as`, is for safe casts.
5
5
In contrast, ` transmute ` allows for arbitrary casting, and is one of the
6
6
most dangerous features of Rust!
7
7
8
+ # Coercion
9
+
10
+ Coercion between types is implicit and has no syntax of its own, but can
11
+ be spelled out with [ ` as ` ] ( #explicit-coercions ) .
12
+
13
+ Coercion occurs in ` let ` , ` const ` , and ` static ` statements; in
14
+ function call arguments; in field values in struct initialization; and in a
15
+ function result.
16
+
17
+ The main cases of coercion are:
18
+
19
+ * ` &mut T ` to ` &T `
20
+
21
+ * ` *mut T ` to ` *const T `
22
+
23
+ * ` &T ` to ` *const T `
24
+
25
+ * ` &mut T ` to ` *mut T `
26
+
27
+ * A custom coercion using [ ` Deref ` ] ( deref-coercions.md )
28
+
29
+
8
30
# ` as `
9
31
10
- The ` as ` keyword does basic casting:
32
+ The ` as ` keyword does safe casting:
11
33
12
34
``` rust
13
35
let x : i32 = 5 ;
14
36
15
37
let y = x as i64 ;
16
38
```
17
39
18
- It only allows certain kinds of casting, however:
40
+ There are three major categories of safe cast: explicit coercions, casts
41
+ between numeric types, and pointer casts.
42
+
43
+ Casting is not transitive: even if ` e as U1 as U2 ` is a valid
44
+ expression, ` e as U2 ` is not necessarily so (in fact it will only be valid if
45
+ ` U1 ` coerces to ` U2 ` ).
46
+
47
+
48
+ ## Explicit coercions
49
+
50
+ A cast ` e as U ` is valid if ` e ` has type ` T ` and ` T ` * coerces* to ` U ` .
51
+
52
+ For example:
53
+
54
+ ``` rust
55
+ let a = " hello" ;
56
+ let b = a as String ;
57
+ ```
58
+
59
+ ## Numeric casts
60
+
61
+ A cast ` e as U ` is also valid in any of the following cases:
62
+
63
+ * ` e ` has type ` T ` and ` T ` and ` U ` are any numeric types; * numeric-cast*
64
+ * ` e ` is a C-like enum (with no data attached to the variants),
65
+ and ` U ` is an integer type; * enum-cast*
66
+ * ` e ` has type ` bool ` or ` char ` and ` U ` is an integer type; * prim-int-cast*
67
+ * ` e ` has type ` u8 ` and ` U ` is ` char ` ; * u8-char-cast*
68
+
69
+ For example
70
+
71
+ ``` rust
72
+ let one = true as u8 ;
73
+ let at_sign = 64 as char ;
74
+ ```
75
+
76
+ The semantics of numeric casts are:
77
+
78
+ * Casting between two integers of the same size (e.g. i32 -> u32) is a no-op
79
+ * Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
80
+ truncate
81
+ * Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
82
+ * zero-extend if the source is unsigned
83
+ * sign-extend if the source is signed
84
+ * Casting from a float to an integer will round the float towards zero
85
+ * ** [ NOTE: currently this will cause Undefined Behavior if the rounded
86
+ value cannot be represented by the target integer type] [ float-int ] ** .
87
+ This includes Inf and NaN. This is a bug and will be fixed.
88
+ * Casting from an integer to float will produce the floating point
89
+ representation of the integer, rounded if necessary (rounding strategy
90
+ unspecified)
91
+ * Casting from an f32 to an f64 is perfect and lossless
92
+ * Casting from an f64 to an f32 will produce the closest possible value
93
+ (rounding strategy unspecified)
94
+ * ** [ NOTE: currently this will cause Undefined Behavior if the value
95
+ is finite but larger or smaller than the largest or smallest finite
96
+ value representable by f32] [ float-float ] ** . This is a bug and will
97
+ be fixed.
98
+
99
+ [ float-int ] : https://github.com/rust-lang/rust/issues/10184
100
+ [ float-float ] : https://github.com/rust-lang/rust/issues/15536
101
+
102
+ ## Pointer casts
103
+
104
+ Perhaps surprisingly, it is safe to cast pointers to and from integers, and
105
+ to cast between pointers to different types subject to some constraints. It
106
+ is only unsafe to dereference the pointer.
107
+
108
+ ` e as U ` is a valid pointer cast in any of the following cases:
109
+
110
+ * ` e ` has type ` *T ` , ` U ` has type ` *U_0 ` , and either ` U_0: Sized ` or
111
+ ` unsize_kind(T) == unsize_kind(U_0) ` ; a * ptr-ptr-cast*
112
+
113
+ * ` e ` has type ` *T ` and ` U ` is a numeric type, while ` T: Sized ` ; * ptr-addr-cast*
114
+
115
+ * ` e ` is an integer and ` U ` is ` *U_0 ` , while ` U_0: Sized ` ; * addr-ptr-cast*
116
+
117
+ * ` e ` has type ` &[T; n] ` and ` U ` is ` *const T ` ; * array-ptr-cast*
118
+
119
+ * ` e ` is a function pointer type and ` U ` has type ` *T ` ,
120
+ while ` T: Sized ` ; * fptr-ptr-cast*
121
+
122
+ * ` e ` is a function pointer type and ` U ` is an integer; * fptr-addr-cast*
123
+
124
+
125
+ # ` transmute `
126
+
127
+ ` as ` only allows safe casting, and will for example reject an attempt to
128
+ cast four bytes into a ` u32 ` :
19
129
20
130
``` rust,ignore
21
131
let a = [0u8, 0u8, 0u8, 0u8];
@@ -31,13 +141,11 @@ let b = a as u32; // four eights makes 32
31
141
^~~~~~~~
32
142
```
33
143
34
- It’s a ‘non-scalar cast’ because we have multiple values here: the four
144
+ This is a ‘non-scalar cast’ because we have multiple values here: the four
35
145
elements of the array. These kinds of casts are very dangerous, because they
36
146
make assumptions about the way that multiple underlying structures are
37
147
implemented. For this, we need something more dangerous.
38
148
39
- # ` transmute `
40
-
41
149
The ` transmute ` function is provided by a [ compiler intrinsic] [ intrinsics ] , and
42
150
what it does is very simple, but very scary. It tells Rust to treat a value of
43
151
one type as though it were another type. It does this regardless of the
0 commit comments