@@ -185,6 +185,98 @@ 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 block targeted by multiple breaks(including loop block).
198+ + To find the type for the return type of a closure with multiple return statements.
199+ + To check the type for the return type of a function with multiple return statements.
200+
201+ In each such case, there are a set of types ` T0..Tn ` to be mutually coerced
202+ to some target type ` T_t ` , which is unknown to start. Computing the LUB
203+ coercion is done iteratively. The target type ` T_t ` begins as the type ` T0 ` .
204+ For each new type ` Ti ` , we consider whether
205+
206+ + If ` Ti ` can be coerced to the current target type ` T_t ` , then no change is made.
207+ + Otherwise, check whether ` T_t ` can be coerced to ` Ti ` ; if so, the ` T_t ` is
208+ changed to ` Ti ` . (This check is also conditioned on whether all of the source
209+ expressions considered thus far have implicit coercions.)
210+ + If not, try to compute a mutual supertype of ` T_t ` and ` Ti ` , which will become the new target type.
211+
212+ ### Examples:
213+
214+ ``` rust
215+ # #![feature(label_break_value)]
216+ # let (a , b , c ) = (0 , 1 , 2 );
217+ // For if branches
218+ let bar = if true {
219+ a
220+ } else if false {
221+ b
222+ } else {
223+ c
224+ };
225+
226+ // For match arms
227+ let baw = match 42 {
228+ 0 => a ,
229+ 1 => b ,
230+ _ => c ,
231+ };
232+
233+ // For array elements
234+ let bax = [a , b , c ];
235+
236+ // For block targeted by multiple breaks(unstable, check #48594)
237+ let bay = 'out : {
238+ if true {
239+ break 'out a ;
240+ } else if false {
241+ break 'out b ;
242+ } else {
243+ break 'out c ;
244+ }
245+ };
246+
247+ // For closure with multiple return statements
248+ let clo = || {
249+ if true {
250+ a
251+ } else if false {
252+ b
253+ } else {
254+ c
255+ }
256+ };
257+ let baz = clo ();
258+
259+ // For type checking of function with multiple return statements
260+ fn foo () -> i32 {
261+ let (a , b , c ) = (0 , 1 , 2 );
262+ match 42 {
263+ 0 => a ,
264+ 1 => b ,
265+ _ => c ,
266+ }
267+ }
268+ ```
269+
270+ In these examples, types of the ` ba* ` are found by LUB coercion. And the
271+ compiler checks whether LUB coercion result of ` a ` , ` b ` , ` c ` is ` i32 ` in the
272+ processing of the function ` foo ` .
273+
274+ ### Caveat
275+
276+ This description is obviously informal. Making it more precise is expected to
277+ proceed as part of a general effort to specify the Rust type checker more
278+ precisely.
279+
188280[ RFC 401 ] : https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
189281[ RFC 1558 ] : https://github.com/rust-lang/rfcs/blob/master/text/1558-closure-to-fn-coercion.md
190282[ subtype ] : subtyping.md
0 commit comments