@@ -120,19 +120,16 @@ impl<'a> InferenceContext<'a> {
120
120
let ty = match label {
121
121
Some ( _) => {
122
122
let break_ty = self . table . new_type_var ( ) ;
123
- let ( ctx, ty) = self . with_breakable_ctx ( break_ty. clone ( ) , * label, |this| {
124
- this. infer_block (
125
- tgt_expr,
126
- statements,
127
- * tail,
128
- & Expectation :: has_type ( break_ty) ,
129
- )
130
- } ) ;
131
- if ctx. may_break {
132
- ctx. coerce . complete ( )
133
- } else {
134
- ty
135
- }
123
+ let ( breaks, ty) =
124
+ self . with_breakable_ctx ( break_ty. clone ( ) , * label, |this| {
125
+ this. infer_block (
126
+ tgt_expr,
127
+ statements,
128
+ * tail,
129
+ & Expectation :: has_type ( break_ty) ,
130
+ )
131
+ } ) ;
132
+ breaks. unwrap_or ( ty)
136
133
}
137
134
None => self . infer_block ( tgt_expr, statements, * tail, expected) ,
138
135
} ;
@@ -164,15 +161,16 @@ impl<'a> InferenceContext<'a> {
164
161
}
165
162
& Expr :: Loop { body, label } => {
166
163
let ty = self . table . new_type_var ( ) ;
167
- let ( ctx , ( ) ) = self . with_breakable_ctx ( ty, label, |this| {
164
+ let ( breaks , ( ) ) = self . with_breakable_ctx ( ty, label, |this| {
168
165
this. infer_expr ( body, & Expectation :: has_type ( TyBuilder :: unit ( ) ) ) ;
169
166
} ) ;
170
167
171
- if ctx. may_break {
172
- self . diverges = Diverges :: Maybe ;
173
- ctx. coerce . complete ( )
174
- } else {
175
- TyKind :: Never . intern ( Interner )
168
+ match breaks {
169
+ Some ( breaks) => {
170
+ self . diverges = Diverges :: Maybe ;
171
+ breaks
172
+ }
173
+ None => TyKind :: Never . intern ( Interner ) ,
176
174
}
177
175
}
178
176
& Expr :: While { condition, body, label } => {
@@ -194,7 +192,7 @@ impl<'a> InferenceContext<'a> {
194
192
self . resolve_associated_type ( iterable_ty, self . resolve_into_iter_item ( ) ) ;
195
193
196
194
self . infer_pat ( pat, & pat_ty, BindingMode :: default ( ) ) ;
197
- let ( _ctx , ( ) ) = self . with_breakable_ctx ( self . err_ty ( ) , label, |this| {
195
+ self . with_breakable_ctx ( self . err_ty ( ) , label, |this| {
198
196
this. infer_expr ( body, & Expectation :: has_type ( TyBuilder :: unit ( ) ) ) ;
199
197
} ) ;
200
198
@@ -356,7 +354,15 @@ impl<'a> InferenceContext<'a> {
356
354
let resolver = resolver_for_expr ( self . db . upcast ( ) , self . owner , tgt_expr) ;
357
355
self . infer_path ( & resolver, p, tgt_expr. into ( ) ) . unwrap_or_else ( || self . err_ty ( ) )
358
356
}
359
- Expr :: Continue { .. } => TyKind :: Never . intern ( Interner ) ,
357
+ Expr :: Continue { label } => {
358
+ if let None = find_breakable ( & mut self . breakables , label. as_ref ( ) ) {
359
+ self . push_diagnostic ( InferenceDiagnostic :: BreakOutsideOfLoop {
360
+ expr : tgt_expr,
361
+ is_break : false ,
362
+ } ) ;
363
+ } ;
364
+ TyKind :: Never . intern ( Interner )
365
+ }
360
366
Expr :: Break { expr, label } => {
361
367
let mut coerce = match find_breakable ( & mut self . breakables , label. as_ref ( ) ) {
362
368
Some ( ctxt) => {
@@ -384,6 +390,7 @@ impl<'a> InferenceContext<'a> {
384
390
} else {
385
391
self . push_diagnostic ( InferenceDiagnostic :: BreakOutsideOfLoop {
386
392
expr : tgt_expr,
393
+ is_break : true ,
387
394
} ) ;
388
395
} ;
389
396
@@ -1462,13 +1469,13 @@ impl<'a> InferenceContext<'a> {
1462
1469
ty : Ty ,
1463
1470
label : Option < LabelId > ,
1464
1471
cb : impl FnOnce ( & mut Self ) -> T ,
1465
- ) -> ( BreakableContext , T ) {
1472
+ ) -> ( Option < Ty > , T ) {
1466
1473
self . breakables . push ( {
1467
1474
let label = label. map ( |label| self . body [ label] . name . clone ( ) ) ;
1468
1475
BreakableContext { may_break : false , coerce : CoerceMany :: new ( ty) , label }
1469
1476
} ) ;
1470
1477
let res = cb ( self ) ;
1471
1478
let ctx = self . breakables . pop ( ) . expect ( "breakable stack broken" ) ;
1472
- ( ctx, res)
1479
+ ( ctx. may_break . then ( || ctx . coerce . complete ( ) ) , res)
1473
1480
}
1474
1481
}
0 commit comments