Skip to content

Commit 0f6b234

Browse files
authored
Merge pull request #808 from ldm0/lubcoercion
Add description for LUB Coercion
2 parents 56a13c0 + d5a5e32 commit 0f6b234

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed

src/type-coercions.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,85 @@ unsized coercion to `Foo<U>`.
185185
> has been stabilized, the traits themselves are not yet stable and therefore
186186
> can't be used directly in stable Rust.
187187
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+
188267
[RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
189268
[RFC 1558]: https://github.com/rust-lang/rfcs/blob/master/text/1558-closure-to-fn-coercion.md
190269
[subtype]: subtyping.md

0 commit comments

Comments
 (0)