@@ -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