@@ -163,7 +163,7 @@ impl<'a> InferenceContext<'a> {
163
163
let break_ty = self . table . new_type_var ( ) ;
164
164
self . breakables . push ( BreakableContext {
165
165
may_break : false ,
166
- break_ty : break_ty. clone ( ) ,
166
+ coerce : CoerceMany :: new ( break_ty. clone ( ) ) ,
167
167
label : label. map ( |label| self . body [ label] . name . clone ( ) ) ,
168
168
} ) ;
169
169
let ty = self . infer_block (
@@ -174,7 +174,7 @@ impl<'a> InferenceContext<'a> {
174
174
) ;
175
175
let ctxt = self . breakables . pop ( ) . expect ( "breakable stack broken" ) ;
176
176
if ctxt. may_break {
177
- ctxt. break_ty
177
+ ctxt. coerce . complete ( )
178
178
} else {
179
179
ty
180
180
}
@@ -202,27 +202,24 @@ impl<'a> InferenceContext<'a> {
202
202
Expr :: Loop { body, label } => {
203
203
self . breakables . push ( BreakableContext {
204
204
may_break : false ,
205
- break_ty : self . table . new_type_var ( ) ,
205
+ coerce : CoerceMany :: new ( self . table . new_type_var ( ) ) ,
206
206
label : label. map ( |label| self . body [ label] . name . clone ( ) ) ,
207
207
} ) ;
208
208
self . infer_expr ( * body, & Expectation :: has_type ( TyBuilder :: unit ( ) ) ) ;
209
209
210
210
let ctxt = self . breakables . pop ( ) . expect ( "breakable stack broken" ) ;
211
- if ctxt. may_break {
212
- self . diverges = Diverges :: Maybe ;
213
- }
214
211
215
212
if ctxt. may_break {
216
- ctxt. break_ty
213
+ self . diverges = Diverges :: Maybe ;
214
+ ctxt. coerce . complete ( )
217
215
} else {
218
216
TyKind :: Never . intern ( & Interner )
219
217
}
220
218
}
221
219
Expr :: While { condition, body, label } => {
222
220
self . breakables . push ( BreakableContext {
223
221
may_break : false ,
224
- break_ty : self . err_ty ( ) ,
225
-
222
+ coerce : CoerceMany :: new ( self . err_ty ( ) ) ,
226
223
label : label. map ( |label| self . body [ label] . name . clone ( ) ) ,
227
224
} ) ;
228
225
// while let is desugared to a match loop, so this is always simple while
@@ -241,7 +238,7 @@ impl<'a> InferenceContext<'a> {
241
238
242
239
self . breakables . push ( BreakableContext {
243
240
may_break : false ,
244
- break_ty : self . err_ty ( ) ,
241
+ coerce : CoerceMany :: new ( self . err_ty ( ) ) ,
245
242
label : label. map ( |label| self . body [ label] . name . clone ( ) ) ,
246
243
} ) ;
247
244
let pat_ty =
@@ -383,31 +380,35 @@ impl<'a> InferenceContext<'a> {
383
380
}
384
381
Expr :: Continue { .. } => TyKind :: Never . intern ( & Interner ) ,
385
382
Expr :: Break { expr, label } => {
386
- let expr = * expr;
387
- let last_ty =
388
- if let Some ( ctxt) = find_breakable ( & mut self . breakables , label. as_ref ( ) ) {
389
- ctxt. break_ty . clone ( )
390
- } else {
391
- self . err_ty ( )
392
- } ;
383
+ let mut coerce = match find_breakable ( & mut self . breakables , label. as_ref ( ) ) {
384
+ Some ( ctxt) => {
385
+ // avoiding the borrowck
386
+ mem:: replace (
387
+ & mut ctxt. coerce ,
388
+ CoerceMany :: new ( self . result . standard_types . unknown . clone ( ) ) ,
389
+ )
390
+ }
391
+ None => CoerceMany :: new ( self . result . standard_types . unknown . clone ( ) ) ,
392
+ } ;
393
393
394
- let val_ty = if let Some ( expr) = expr {
394
+ let val_ty = if let Some ( expr) = * expr {
395
395
self . infer_expr ( expr, & Expectation :: none ( ) )
396
396
} else {
397
397
TyBuilder :: unit ( )
398
398
} ;
399
399
400
400
// FIXME: create a synthetic `()` during lowering so we have something to refer to here?
401
- let merged_type = CoerceMany :: once ( self , last_ty , expr, & val_ty) ;
401
+ coerce . coerce ( self , * expr, & val_ty) ;
402
402
403
403
if let Some ( ctxt) = find_breakable ( & mut self . breakables , label. as_ref ( ) ) {
404
- ctxt. break_ty = merged_type ;
404
+ ctxt. coerce = coerce ;
405
405
ctxt. may_break = true ;
406
406
} else {
407
407
self . push_diagnostic ( InferenceDiagnostic :: BreakOutsideOfLoop {
408
408
expr : tgt_expr,
409
409
} ) ;
410
- }
410
+ } ;
411
+
411
412
TyKind :: Never . intern ( & Interner )
412
413
}
413
414
Expr :: Return { expr } => {
0 commit comments