@@ -185,6 +185,85 @@ unsized coercion to `Foo<U>`.
185
185
> has been stabilized, the traits themselves are not yet stable and therefore
186
186
> can't be used directly in stable Rust.
187
187
188
+ ## Least upper bound coercions
189
+
190
+ In some contexts, the compiler must coerce together multiple types to try and
191
+ find the most general type. This is called a "Least Upper Bound" coercion.
192
+ LUB coercion is used and only used in the following situations:
193
+
194
+ + To find the common type for a series of if branches.
195
+ + To find the common type for a series of match arms.
196
+ + To find the common type for array elements.
197
+ + To find the type for the return type of a closure with multiple return statements.
198
+ + To check the type for the return type of a function with multiple return statements.
199
+
200
+ In each such case, there are a set of types ` T0..Tn ` to be mutually coerced
201
+ to some target type ` T_t ` , which is unknown to start. Computing the LUB
202
+ coercion is done iteratively. The target type ` T_t ` begins as the type ` T0 ` .
203
+ For each new type ` Ti ` , we consider whether
204
+
205
+ + If ` Ti ` can be coerced to the current target type ` T_t ` , then no change is made.
206
+ + Otherwise, check whether ` T_t ` can be coerced to ` Ti ` ; if so, the ` T_t ` is
207
+ changed to ` Ti ` . (This check is also conditioned on whether all of the source
208
+ expressions considered thus far have implicit coercions.)
209
+ + If not, try to compute a mutual supertype of ` T_t ` and ` Ti ` , which will become the new target type.
210
+
211
+ ### Examples:
212
+
213
+ ``` rust
214
+ # let (a , b , c ) = (0 , 1 , 2 );
215
+ // For if branches
216
+ let bar = if true {
217
+ a
218
+ } else if false {
219
+ b
220
+ } else {
221
+ c
222
+ };
223
+
224
+ // For match arms
225
+ let baw = match 42 {
226
+ 0 => a ,
227
+ 1 => b ,
228
+ _ => c ,
229
+ };
230
+
231
+ // For array elements
232
+ let bax = [a , b , c ];
233
+
234
+ // For closure with multiple return statements
235
+ let clo = || {
236
+ if true {
237
+ a
238
+ } else if false {
239
+ b
240
+ } else {
241
+ c
242
+ }
243
+ };
244
+ let baz = clo ();
245
+
246
+ // For type checking of function with multiple return statements
247
+ fn foo () -> i32 {
248
+ let (a , b , c ) = (0 , 1 , 2 );
249
+ match 42 {
250
+ 0 => a ,
251
+ 1 => b ,
252
+ _ => c ,
253
+ }
254
+ }
255
+ ```
256
+
257
+ In these examples, types of the ` ba* ` are found by LUB coercion. And the
258
+ compiler checks whether LUB coercion result of ` a ` , ` b ` , ` c ` is ` i32 ` in the
259
+ processing of the function ` foo ` .
260
+
261
+ ### Caveat
262
+
263
+ This description is obviously informal. Making it more precise is expected to
264
+ proceed as part of a general effort to specify the Rust type checker more
265
+ precisely.
266
+
188
267
[ RFC 401 ] : https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
189
268
[ RFC 1558 ] : https://github.com/rust-lang/rfcs/blob/master/text/1558-closure-to-fn-coercion.md
190
269
[ subtype ] : subtyping.md
0 commit comments