Skip to content

Commit 0826cf5

Browse files
committed
Add pseudo code for LUB coercion, Nits fixing
1 parent 019e923 commit 0826cf5

File tree

1 file changed

+61
-23
lines changed

1 file changed

+61
-23
lines changed

src/type-coercions.md

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ A coercion is implicit and has no syntax.
66
[RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
77
[RFC 1558]: https://github.com/rust-lang/rfcs/blob/master/text/1558-closure-to-fn-coercion.md
88

9+
**Attention: The LUB coercion part is not specified in any RFC currently.
10+
Things described in that part may changes overtime.**
11+
912
## Coercion sites
1013

1114
A coercion can only occur at certain coercion sites in a program; these are
@@ -187,45 +190,80 @@ unsized coercion to `Foo<U>`.
187190

188191
## LUB Coercion
189192

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
193204

194205
For example:
195206

196207
```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
200211
} else if false {
201-
B
212+
b
202213
} else {
203-
C
214+
c
204215
};
205216

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,
210221
};
211222

212-
let bar = [A, B, C];
223+
let baz = [a, b, c];
213224
```
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]`.
217228

218-
LUB Coercion has some features:
229+
LUB coercion has the following properties:
219230
1. Order independent: e.g. `LubCoerce(ty0, ty1, ty2, ty3)` equals to
220231
`LubCoerce(ty1, ty0, ty4, ty3)`.
221232
2. `LubCoerce(ty0, ty1, ty2, ...)` equals to
222233
`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
224235
`ty2`.
225236

226237
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

Comments
 (0)