@@ -133,7 +133,7 @@ impl<'a> InferenceContext<'a> {
133
133
let break_ty = self . table . new_type_var ( ) ;
134
134
let ( breaks, ty) = self . with_breakable_ctx (
135
135
BreakableKind :: Block ,
136
- break_ty. clone ( ) ,
136
+ Some ( break_ty. clone ( ) ) ,
137
137
* label,
138
138
|this| {
139
139
this. infer_block (
@@ -153,7 +153,7 @@ impl<'a> InferenceContext<'a> {
153
153
}
154
154
Expr :: Unsafe { body } => self . infer_expr ( * body, expected) ,
155
155
Expr :: Const { body } => {
156
- self . with_breakable_ctx ( BreakableKind :: Border , self . err_ty ( ) , None , |this| {
156
+ self . with_breakable_ctx ( BreakableKind :: Border , None , None , |this| {
157
157
this. infer_expr ( * body, expected)
158
158
} )
159
159
. 1
@@ -169,7 +169,7 @@ impl<'a> InferenceContext<'a> {
169
169
let ok_ty =
170
170
self . resolve_associated_type ( try_ty. clone ( ) , self . resolve_ops_try_output ( ) ) ;
171
171
172
- self . with_breakable_ctx ( BreakableKind :: Block , ok_ty. clone ( ) , None , |this| {
172
+ self . with_breakable_ctx ( BreakableKind :: Block , Some ( ok_ty. clone ( ) ) , None , |this| {
173
173
this. infer_expr ( * body, & Expectation :: has_type ( ok_ty) ) ;
174
174
} ) ;
175
175
@@ -183,7 +183,7 @@ impl<'a> InferenceContext<'a> {
183
183
mem:: replace ( & mut self . return_coercion , Some ( CoerceMany :: new ( ret_ty. clone ( ) ) ) ) ;
184
184
185
185
let ( _, inner_ty) =
186
- self . with_breakable_ctx ( BreakableKind :: Border , self . err_ty ( ) , None , |this| {
186
+ self . with_breakable_ctx ( BreakableKind :: Border , None , None , |this| {
187
187
this. infer_expr_coerce ( * body, & Expectation :: has_type ( ret_ty) )
188
188
} ) ;
189
189
@@ -203,7 +203,7 @@ impl<'a> InferenceContext<'a> {
203
203
// let ty = expected.coercion_target_type(&mut self.table);
204
204
let ty = self . table . new_type_var ( ) ;
205
205
let ( breaks, ( ) ) =
206
- self . with_breakable_ctx ( BreakableKind :: Loop , ty , label, |this| {
206
+ self . with_breakable_ctx ( BreakableKind :: Loop , Some ( ty ) , label, |this| {
207
207
this. infer_expr ( body, & Expectation :: HasType ( TyBuilder :: unit ( ) ) ) ;
208
208
} ) ;
209
209
@@ -216,7 +216,7 @@ impl<'a> InferenceContext<'a> {
216
216
}
217
217
}
218
218
& Expr :: While { condition, body, label } => {
219
- self . with_breakable_ctx ( BreakableKind :: Loop , self . err_ty ( ) , label, |this| {
219
+ self . with_breakable_ctx ( BreakableKind :: Loop , None , label, |this| {
220
220
this. infer_expr (
221
221
condition,
222
222
& Expectation :: HasType ( this. result . standard_types . bool_ . clone ( ) ) ,
@@ -236,7 +236,7 @@ impl<'a> InferenceContext<'a> {
236
236
self . resolve_associated_type ( into_iter_ty, self . resolve_iterator_item ( ) ) ;
237
237
238
238
self . infer_top_pat ( pat, & pat_ty) ;
239
- self . with_breakable_ctx ( BreakableKind :: Loop , self . err_ty ( ) , label, |this| {
239
+ self . with_breakable_ctx ( BreakableKind :: Loop , None , label, |this| {
240
240
this. infer_expr ( body, & Expectation :: HasType ( TyBuilder :: unit ( ) ) ) ;
241
241
} ) ;
242
242
@@ -321,7 +321,7 @@ impl<'a> InferenceContext<'a> {
321
321
let prev_resume_yield_tys =
322
322
mem:: replace ( & mut self . resume_yield_tys , resume_yield_tys) ;
323
323
324
- self . with_breakable_ctx ( BreakableKind :: Border , self . err_ty ( ) , None , |this| {
324
+ self . with_breakable_ctx ( BreakableKind :: Border , None , None , |this| {
325
325
this. infer_return ( * body) ;
326
326
} ) ;
327
327
@@ -439,42 +439,50 @@ impl<'a> InferenceContext<'a> {
439
439
self . push_diagnostic ( InferenceDiagnostic :: BreakOutsideOfLoop {
440
440
expr : tgt_expr,
441
441
is_break : false ,
442
+ bad_value_break : false ,
442
443
} ) ;
443
444
} ;
444
445
self . result . standard_types . never . clone ( )
445
446
}
446
447
Expr :: Break { expr, label } => {
447
448
let val_ty = if let Some ( expr) = * expr {
448
- let opt_coerce_to = find_breakable ( & mut self . breakables , label. as_ref ( ) )
449
- . map ( |ctxt| ctxt. coerce . expected_ty ( ) ) ;
450
- self . infer_expr_inner (
451
- expr,
452
- & Expectation :: HasType ( opt_coerce_to. unwrap_or_else ( || self . err_ty ( ) ) ) ,
453
- )
449
+ let opt_coerce_to = match find_breakable ( & mut self . breakables , label. as_ref ( ) ) {
450
+ Some ( ctxt) => match & ctxt. coerce {
451
+ Some ( coerce) => coerce. expected_ty ( ) ,
452
+ None => {
453
+ self . push_diagnostic ( InferenceDiagnostic :: BreakOutsideOfLoop {
454
+ expr : tgt_expr,
455
+ is_break : true ,
456
+ bad_value_break : true ,
457
+ } ) ;
458
+ self . err_ty ( )
459
+ }
460
+ } ,
461
+ None => self . err_ty ( ) ,
462
+ } ;
463
+ self . infer_expr_inner ( expr, & Expectation :: HasType ( opt_coerce_to) )
454
464
} else {
455
465
TyBuilder :: unit ( )
456
466
} ;
457
467
458
468
match find_breakable ( & mut self . breakables , label. as_ref ( ) ) {
459
- Some ( ctxt) => {
460
- // avoiding the borrowck
461
- let mut coerce = mem:: replace (
462
- & mut ctxt. coerce ,
463
- CoerceMany :: new ( expected. coercion_target_type ( & mut self . table ) ) ,
464
- ) ;
465
-
466
- // FIXME: create a synthetic `()` during lowering so we have something to refer to here?
467
- coerce. coerce ( self , * expr, & val_ty) ;
468
-
469
- let ctxt = find_breakable ( & mut self . breakables , label. as_ref ( ) )
470
- . expect ( "breakable stack changed during coercion" ) ;
471
- ctxt. coerce = coerce;
472
- ctxt. may_break = true ;
473
- }
469
+ Some ( ctxt) => match ctxt. coerce . take ( ) {
470
+ Some ( mut coerce) => {
471
+ coerce. coerce ( self , * expr, & val_ty) ;
472
+
473
+ // Avoiding borrowck
474
+ let ctxt = find_breakable ( & mut self . breakables , label. as_ref ( ) )
475
+ . expect ( "breakable stack changed during coercion" ) ;
476
+ ctxt. may_break = true ;
477
+ ctxt. coerce = Some ( coerce) ;
478
+ }
479
+ None => ctxt. may_break = true ,
480
+ } ,
474
481
None => {
475
482
self . push_diagnostic ( InferenceDiagnostic :: BreakOutsideOfLoop {
476
483
expr : tgt_expr,
477
484
is_break : true ,
485
+ bad_value_break : false ,
478
486
} ) ;
479
487
}
480
488
}
@@ -1712,16 +1720,16 @@ impl<'a> InferenceContext<'a> {
1712
1720
fn with_breakable_ctx < T > (
1713
1721
& mut self ,
1714
1722
kind : BreakableKind ,
1715
- ty : Ty ,
1723
+ ty : Option < Ty > ,
1716
1724
label : Option < LabelId > ,
1717
1725
cb : impl FnOnce ( & mut Self ) -> T ,
1718
1726
) -> ( Option < Ty > , T ) {
1719
1727
self . breakables . push ( {
1720
1728
let label = label. map ( |label| self . body [ label] . name . clone ( ) ) ;
1721
- BreakableContext { kind, may_break : false , coerce : CoerceMany :: new ( ty ) , label }
1729
+ BreakableContext { kind, may_break : false , coerce : ty . map ( CoerceMany :: new) , label }
1722
1730
} ) ;
1723
1731
let res = cb ( self ) ;
1724
1732
let ctx = self . breakables . pop ( ) . expect ( "breakable stack broken" ) ;
1725
- ( ctx. may_break . then ( | | ctx. coerce . complete ( self ) ) , res)
1733
+ ( if ctx. may_break { ctx . coerce . map ( |ctx | ctx. complete ( self ) ) } else { None } , res)
1726
1734
}
1727
1735
}
0 commit comments