@@ -6,6 +6,9 @@ A coercion is implicit and has no syntax.
6
6
[ RFC 401 ] : https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
7
7
[ RFC 1558 ] : https://github.com/rust-lang/rfcs/blob/master/text/1558-closure-to-fn-coercion.md
8
8
9
+ ** Attention: The LUB coercion part is not specified in any RFC currently.
10
+ Things described in that part may changes overtime.**
11
+
9
12
## Coercion sites
10
13
11
14
A coercion can only occur at certain coercion sites in a program; these are
@@ -187,45 +190,80 @@ unsized coercion to `Foo<U>`.
187
190
188
191
## LUB Coercion
189
192
190
- This is not in the RFC 401, but it's the behavior of current compiler. In LUB
191
- Coercion, we tried to find the least upper bound of given types. It can be
192
- observed in array collection, if-else/match arms.
193
+ ** This part is not specified in any RFC directly, but it's the compiler's
194
+ behavior.**
195
+
196
+ * Least upper bound coercion* (LUB coercion) is the type of coercion take place
197
+ when we want to unify several types. It can be observed in [ match] arms,
198
+ [ if expressions] and [ array literal expressions] . In LUB Coercion, the compiler
199
+ tries to find the least upper bound of given types.
200
+
201
+ [ match ] : expressions/match-expr.md
202
+ [ If expressions ] : expressions/if-expr.md
203
+ [ array literal expressions ] : expressions/array-expr.md
193
204
194
205
For example:
195
206
196
207
``` rust
197
- # let (A , B , C ) = (0 , 1 , 2 );
198
- let emm = if true {
199
- A
208
+ # let (a , b , c ) = (0 , 1 , 2 );
209
+ let foo = if true {
210
+ a
200
211
} else if false {
201
- B
212
+ b
202
213
} else {
203
- C
214
+ c
204
215
};
205
216
206
- let foo = match 42 {
207
- 0 => A ,
208
- 1 => B ,
209
- _ => C ,
217
+ let bar = match 42 {
218
+ 0 => a ,
219
+ 1 => b ,
220
+ _ => c ,
210
221
};
211
222
212
- let bar = [A , B , C ];
223
+ let baz = [a , b , c ];
213
224
```
214
- In this example, both ` emm ` and ` foo ` has type
215
- ` LubCoerce(typeof(A ), typeof(B ), typeof(C )) ` and ` bar ` has type
216
- ` [LubCoerce(typeof(A ), typeof(B ), typeof(C )); 3] ` .
225
+ In this example, both ` foo ` and ` bar ` get the type
226
+ ` LubCoerce(typeof(a ), typeof(a ), typeof(c )) ` and ` baz ` get the type
227
+ ` [LubCoerce(typeof(a ), typeof(b ), typeof(c )); 3] ` .
217
228
218
- LUB Coercion has some features :
229
+ LUB coercion has the following properties :
219
230
1 . Order independent: e.g. ` LubCoerce(ty0, ty1, ty2, ty3) ` equals to
220
231
` LubCoerce(ty1, ty0, ty4, ty3) ` .
221
232
2 . ` LubCoerce(ty0, ty1, ty2, ...) ` equals to
222
233
` LubCoerce(LubCoerce(ty0, ty1), ty2, ...) `
223
- 4 . ` LubCoerce(ty0, ty1) == ty2 ` means both ` ty0 ` and ` ty1 ` can be coerced to
234
+ 3 . ` LubCoerce(ty0, ty1) == ty2 ` means both ` ty0 ` and ` ty1 ` can be coerced to
224
235
` ty2 ` .
225
236
226
237
Notice the feature No.3, it uses the word "means" rather than "if and only if".
227
- That's because currently if ` ty0 ` and ` ty1 ` can be coerced to ` ty2 ` and ` ty2 `
228
- equals to neither ` ty0 ` nor ` ty1 ` , there are only two special cases we can get
229
- ` LubCoerce(ty0, ty1) == ty2 ` :
230
- 1 . ` LubCoerce(FnDef, FnDef) == FnPtr ` ,
231
- 2 . ` LubCoerce(Closure, Closure) == FnPtr ` (where Closure is non-capturing).
238
+ That's because currently if ` ty0 ` and ` ty1 ` can be coerced to ` ty2 ` and
239
+ unfortunately ` ty2 ` equals to neither ` ty0 ` nor ` ty1 ` , there are only one
240
+ special situation where we can get ` LubCoerce(ty0, ty1) == ty2 ` :
241
+ ` LubCoerce((FnDef | Closure), (FnDef | Closure)) == FnPtr ` (where Closure is
242
+ non-capturing).
243
+
244
+ If the comments above confuses you, here is the pseudo code of ` LubCoerce `
245
+ in current rustc:
246
+
247
+ ``` txt
248
+ Lub(a, b):
249
+ if a == (FnDef | Closure)
250
+ && b == (FnDef | Closure)
251
+ && a != capturing Closure
252
+ && b != capturing Closure:
253
+ return FnPtr
254
+
255
+ // Coerce(x, y) returns true when x can be coerced to y
256
+ if Coerce(b, a):
257
+ return a
258
+ if Coerce(a, b):
259
+ return b
260
+
261
+ // LubCoerce failed
262
+ emits error
263
+
264
+ LubCoerce(vars):
265
+ result = vars.get(0)
266
+ for var in vars[1..]:
267
+ result = Lub(result, var)
268
+ return result
269
+ ```
0 commit comments