From c0b102d21e07edaa45f3ce8e4e64916d299a84b1 Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Fri, 4 Sep 2020 01:43:55 +0800 Subject: [PATCH 1/2] Introducing LUB coercion --- src/type-coercions.md | 92 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/type-coercions.md b/src/type-coercions.md index d578e042a..da2be3435 100644 --- a/src/type-coercions.md +++ b/src/type-coercions.md @@ -185,6 +185,98 @@ unsized coercion to `Foo`. > has been stabilized, the traits themselves are not yet stable and therefore > can't be used directly in stable Rust. +## Least upper bound coercions + +In some contexts, the compiler must coerce together multiple types to try and +find the most general type. This is called a "Least Upper Bound" coercion. +LUB coercion is used and only used in the following situations: + ++ To find the common type for a series of if branches. ++ To find the common type for a series of match arms. ++ To find the common type for array elements. ++ To find the type for block targeted by multiple breaks(including loop block). ++ To find the type for the return type of a closure with multiple return statements. ++ To check the type for the return type of a function with multiple return statements. + +In each such case, there are a set of types `T0..Tn` to be mutually coerced +to some target type `T_t`, which is unknown to start. Computing the LUB +coercion is done iteratively. The target type `T_t` begins as the type `T0`. +For each new type `Ti`, we consider whether + ++ If `Ti` can be coerced to the current target type `T_t`, then no change is made. ++ Otherwise, check whether `T_t` can be coerced to `Ti`; if so, the `T_t` is +changed to `Ti`. (This check is also conditioned on whether all of the source +expressions considered thus far have implicit coercions.) ++ If not, try to compute a mutual supertype of `T_t` and `Ti`, which will become the new target type. + +### Examples: + +```rust +# #![feature(label_break_value)] +# let (a, b, c) = (0, 1, 2); +// For if branches +let bar = if true { + a +} else if false { + b +} else { + c +}; + +// For match arms +let baw = match 42 { + 0 => a, + 1 => b, + _ => c, +}; + +// For array elements +let bax = [a, b, c]; + +// For block targeted by multiple breaks(unstable, check #48594) +let bay = 'out: { + if true { + break 'out a; + } else if false { + break 'out b; + } else { + break 'out c; + } +}; + +// For closure with multiple return statements +let clo = || { + if true { + a + } else if false { + b + } else { + c + } +}; +let baz = clo(); + +// For type checking of function with multiple return statements +fn foo() -> i32 { + let (a, b, c) = (0, 1, 2); + match 42 { + 0 => a, + 1 => b, + _ => c, + } +} +``` + +In these examples, types of the `ba*` are found by LUB coercion. And the +compiler checks whether LUB coercion result of `a`, `b`, `c` is `i32` in the +processing of the function `foo`. + +### Caveat + +This description is obviously informal. Making it more precise is expected to +proceed as part of a general effort to specify the Rust type checker more +precisely. + [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md [RFC 1558]: https://github.com/rust-lang/rfcs/blob/master/text/1558-closure-to-fn-coercion.md [subtype]: subtyping.md From d5a5e32d3cda8a297d2a91a85b91ff2629b0e896 Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Wed, 16 Sep 2020 10:55:00 +0800 Subject: [PATCH 2/2] Remove label break in type coercions because it's nightly. --- src/type-coercions.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/type-coercions.md b/src/type-coercions.md index da2be3435..d94dd82bf 100644 --- a/src/type-coercions.md +++ b/src/type-coercions.md @@ -194,7 +194,6 @@ LUB coercion is used and only used in the following situations: + To find the common type for a series of if branches. + To find the common type for a series of match arms. + To find the common type for array elements. -+ To find the type for block targeted by multiple breaks(including loop block). + To find the type for the return type of a closure with multiple return statements. + To check the type for the return type of a function with multiple return statements. @@ -212,7 +211,6 @@ expressions considered thus far have implicit coercions.) ### Examples: ```rust -# #![feature(label_break_value)] # let (a, b, c) = (0, 1, 2); // For if branches let bar = if true { @@ -233,17 +231,6 @@ let baw = match 42 { // For array elements let bax = [a, b, c]; -// For block targeted by multiple breaks(unstable, check #48594) -let bay = 'out: { - if true { - break 'out a; - } else if false { - break 'out b; - } else { - break 'out c; - } -}; - // For closure with multiple return statements let clo = || { if true {