1
1
# Type coercions
2
2
3
+ r[ coerce]
4
+
5
+ r[ coerce.intro]
3
6
** Type coercions** are implicit operations that change the type of a value.
4
7
They happen automatically at specific locations and are highly restricted in
5
8
what types actually coerce.
6
9
10
+ r[ cerce.as]
7
11
Any conversions allowed by coercion can also be explicitly performed by the
8
12
[ type cast operator] , ` as ` .
9
13
10
14
Coercions are originally defined in [ RFC 401] and expanded upon in [ RFC 1558] .
11
15
12
16
## Coercion sites
13
17
18
+ r[ coerce.site]
19
+
20
+ r[ coerce.site.intro]
14
21
A coercion can only occur at certain coercion sites in a program; these are
15
22
typically places where the desired type is explicit or can be derived by
16
23
propagation from explicit types (without type inference). Possible coercion
17
24
sites are:
18
25
26
+ r[ coerce.site.let]
19
27
* ` let ` statements where an explicit type is given.
20
28
21
29
For example, ` &mut 42 ` is coerced to have type ` &i8 ` in the following:
@@ -24,8 +32,10 @@ sites are:
24
32
let _ : & i8 = & mut 42 ;
25
33
```
26
34
35
+ r[ coerce.site.value]
27
36
* ` static ` and ` const ` item declarations (similar to ` let ` statements).
28
37
38
+ r[ coerce.site.argument]
29
39
* Arguments for function calls
30
40
31
41
The value being coerced is the actual parameter, and it is coerced to
@@ -44,6 +54,7 @@ sites are:
44
54
For method calls, the receiver (` self ` parameter) type is coerced
45
55
differently, see the documentation on [ method-call expressions] for details.
46
56
57
+ r[ coerce.site.constructor]
47
58
* Instantiations of struct, union, or enum variant fields
48
59
49
60
For example, ` &mut 42 ` is coerced to have type ` &i8 ` in the following:
@@ -56,6 +67,7 @@ sites are:
56
67
}
57
68
```
58
69
70
+ r[ coerce.site.return]
59
71
* Function results&mdash ; either the final line of a block if it is not
60
72
semicolon-terminated or any expression in a ` return ` statement
61
73
@@ -68,48 +80,64 @@ sites are:
68
80
}
69
81
```
70
82
83
+ r[ coerce.site.subexpr]
71
84
If the expression in one of these coercion sites is a coercion-propagating
72
85
expression, then the relevant sub-expressions in that expression are also
73
86
coercion sites. Propagation recurses from these new coercion sites.
74
87
Propagating expressions and their relevant sub-expressions are:
75
88
89
+ r[ coerce.site.array]
76
90
* Array literals, where the array has type ` [U; n] ` . Each sub-expression in
77
91
the array literal is a coercion site for coercion to type ` U ` .
78
92
93
+ r[ coerce.site.repeat]
79
94
* Array literals with repeating syntax, where the array has type ` [U; n] ` . The
80
95
repeated sub-expression is a coercion site for coercion to type ` U ` .
81
96
97
+ r[ coerce.site.tuple]
82
98
* Tuples, where a tuple is a coercion site to type ` (U_0, U_1, ..., U_n) ` .
83
99
Each sub-expression is a coercion site to the respective type, e.g. the
84
100
zeroth sub-expression is a coercion site to type ` U_0 ` .
85
101
102
+ r[ coerce.site.parenthesis]
86
103
* Parenthesized sub-expressions (` (e) ` ): if the expression has type ` U ` , then
87
104
the sub-expression is a coercion site to ` U ` .
88
105
106
+ r[ coerce.site.block]
89
107
* Blocks: if a block has type ` U ` , then the last expression in the block (if
90
108
it is not semicolon-terminated) is a coercion site to ` U ` . This includes
91
109
blocks which are part of control flow statements, such as ` if ` /` else ` , if
92
110
the block has a known type.
93
111
94
112
## Coercion types
95
113
114
+ r[ coerce.types]
115
+
116
+ r[ coerce.types.intro]
96
117
Coercion is allowed between the following types:
97
118
119
+ r[ coerce.types.reflexive]
98
120
* ` T ` to ` U ` if ` T ` is a [ subtype] of ` U ` (* reflexive case* )
99
121
122
+ r[ coerce.types.transitive]
100
123
* ` T_1 ` to ` T_3 ` where ` T_1 ` coerces to ` T_2 ` and ` T_2 ` coerces to ` T_3 `
101
124
(* transitive case* )
102
125
103
126
Note that this is not fully supported yet.
104
127
128
+ r[ coerce.types.mut-reborrow]
105
129
* ` &mut T ` to ` &T `
106
130
131
+ r[ coerce.types.mut-pointer]
107
132
* ` *mut T ` to ` *const T `
108
133
134
+ r[ coerce.types.ref-to-pointer]
109
135
* ` &T ` to ` *const T `
110
136
137
+ r[ coerce.types.mut-to-pointer]
111
138
* ` &mut T ` to ` *mut T `
112
139
140
+ r[ coerce.types.deref]
113
141
* ` &T ` or ` &mut T ` to ` &U ` if ` T ` implements ` Deref<Target = U> ` . For example:
114
142
115
143
``` rust
@@ -135,8 +163,10 @@ Coercion is allowed between the following types:
135
163
}
136
164
```
137
165
166
+ r[ coerce.types.deref-mut]
138
167
* ` &mut T ` to ` &mut U ` if ` T ` implements ` DerefMut<Target = U> ` .
139
168
169
+ r[ coerce.types.unsize]
140
170
* TyCtor(` T ` ) to TyCtor(` U ` ), where TyCtor(` T ` ) is one of
141
171
- ` &T `
142
172
- ` &mut T `
@@ -150,35 +180,46 @@ Coercion is allowed between the following types:
150
180
structs. In addition, coercions from subtraits to supertraits will be
151
181
added. See [RFC 401] for more details.-->
152
182
183
+ r[ coerce.types.fn]
153
184
* Function item types to ` fn ` pointers
154
185
186
+ r[ coerce.types.closure]
155
187
* Non capturing closures to ` fn ` pointers
156
188
189
+ r[ coerce.types.never]
157
190
* ` ! ` to any ` T `
158
191
159
192
### Unsized Coercions
160
193
194
+ r[ coerce.unsize]
195
+
196
+ r[ coerce.unsize.intro]
161
197
The following coercions are called ` unsized coercions ` , since they
162
198
relate to converting sized types to unsized types, and are permitted in a few
163
199
cases where other coercions are not, as described above. They can still happen
164
200
anywhere else a coercion can occur.
165
201
202
+ r[ coerce.unsize.trait]
166
203
Two traits, [ ` Unsize ` ] and [ ` CoerceUnsized ` ] , are used
167
204
to assist in this process and expose it for library use. The following
168
205
coercions are built-ins and, if ` T ` can be coerced to ` U ` with one of them, then
169
206
an implementation of ` Unsize<U> ` for ` T ` will be provided:
170
207
208
+ r[ coerce.unsize.slice]
171
209
* ` [T; n] ` to ` [T] ` .
172
210
211
+ r[ coerce.unsize.trait-object]
173
212
* ` T ` to ` dyn U ` , when ` T ` implements ` U + Sized ` , and ` U ` is [ object safe] .
174
213
214
+ r[ coerce.unsized.composite]
175
215
* ` Foo<..., T, ...> ` to ` Foo<..., U, ...> ` , when:
176
216
* ` Foo ` is a struct.
177
217
* ` T ` implements ` Unsize<U> ` .
178
218
* The last field of ` Foo ` has a type involving ` T ` .
179
219
* If that field has type ` Bar<T> ` , then ` Bar<T> ` implements ` Unsized<Bar<U>> ` .
180
220
* T is not part of the type of any other fields.
181
221
222
+ r[ coerce.unsized.pointer]
182
223
Additionally, a type ` Foo<T> ` can implement ` CoerceUnsized<Foo<U>> ` when ` T `
183
224
implements ` Unsize<U> ` or ` CoerceUnsized<Foo<U>> ` . This allows it to provide an
184
225
unsized coercion to ` Foo<U> ` .
@@ -189,6 +230,9 @@ unsized coercion to `Foo<U>`.
189
230
190
231
## Least upper bound coercions
191
232
233
+ r[ coerce.least-upper-bound]
234
+
235
+ r[ coerce.least-upper-bound.intro]
192
236
In some contexts, the compiler must coerce together multiple types to try and
193
237
find the most general type. This is called a "Least Upper Bound" coercion.
194
238
LUB coercion is used and only used in the following situations:
@@ -199,15 +243,24 @@ LUB coercion is used and only used in the following situations:
199
243
+ To find the type for the return type of a closure with multiple return statements.
200
244
+ To check the type for the return type of a function with multiple return statements.
201
245
246
+ r[ coerce.least-upper-bound.target]
202
247
In each such case, there are a set of types ` T0..Tn ` to be mutually coerced
203
- to some target type ` T_t ` , which is unknown to start. Computing the LUB
248
+ to some target type ` T_t ` , which is unknown to start.
249
+
250
+ r[ coerce.least-upper-bound.computation]
251
+ Computing the LUB
204
252
coercion is done iteratively. The target type ` T_t ` begins as the type ` T0 ` .
205
253
For each new type ` Ti ` , we consider whether
206
254
255
+ r[ coerce.least-upper-bound.computation-identity]
207
256
+ If ` Ti ` can be coerced to the current target type ` T_t ` , then no change is made.
257
+
258
+ r[ coerce.least-upper-bound.computation-replace]
208
259
+ Otherwise, check whether ` T_t ` can be coerced to ` Ti ` ; if so, the ` T_t ` is
209
260
changed to ` Ti ` . (This check is also conditioned on whether all of the source
210
261
expressions considered thus far have implicit coercions.)
262
+
263
+ r[ coerce.least-upper-bound.computation-unify]
211
264
+ If not, try to compute a mutual supertype of ` T_t ` and ` Ti ` , which will become the new target type.
212
265
213
266
### Examples:
0 commit comments