@@ -181,19 +181,19 @@ impl EarlyLintPass for NeedlessContinue {
181
181
/// - The expression is a `continue` node.
182
182
/// - The expression node is a block with the first statement being a
183
183
/// `continue`.
184
- fn needless_continue_in_else ( else_expr : & ast:: Expr ) -> bool {
184
+ fn needless_continue_in_else ( else_expr : & ast:: Expr , label : Option < & ast :: Label > ) -> bool {
185
185
match else_expr. node {
186
- ast:: ExprKind :: Block ( ref else_block, _) => is_first_block_stmt_continue ( else_block) ,
187
- ast:: ExprKind :: Continue ( _ ) => true ,
186
+ ast:: ExprKind :: Block ( ref else_block, _) => is_first_block_stmt_continue ( else_block, label ) ,
187
+ ast:: ExprKind :: Continue ( l ) => compare_labels ( label , l . as_ref ( ) ) ,
188
188
_ => false ,
189
189
}
190
190
}
191
191
192
- fn is_first_block_stmt_continue ( block : & ast:: Block ) -> bool {
192
+ fn is_first_block_stmt_continue ( block : & ast:: Block , label : Option < & ast :: Label > ) -> bool {
193
193
block. stmts . get ( 0 ) . map_or ( false , |stmt| match stmt. node {
194
194
ast:: StmtKind :: Semi ( ref e) | ast:: StmtKind :: Expr ( ref e) => {
195
- if let ast:: ExprKind :: Continue ( _ ) = e. node {
196
- true
195
+ if let ast:: ExprKind :: Continue ( ref l ) = e. node {
196
+ compare_labels ( label , l . as_ref ( ) )
197
197
} else {
198
198
false
199
199
}
@@ -202,17 +202,29 @@ fn is_first_block_stmt_continue(block: &ast::Block) -> bool {
202
202
} )
203
203
}
204
204
205
+ /// If the `continue` has a label, check it matches the label of the loop.
206
+ fn compare_labels ( loop_label : Option < & ast:: Label > , continue_label : Option < & ast:: Label > ) -> bool {
207
+ match ( loop_label, continue_label) {
208
+ // `loop { continue; }` or `'a loop { continue; }`
209
+ ( _, None ) => true ,
210
+ // `loop { continue 'a; }`
211
+ ( None , _) => false ,
212
+ // `'a loop { continue 'a; }` or `'a loop { continue 'b; }`
213
+ ( Some ( x) , Some ( y) ) => x. ident == y. ident ,
214
+ }
215
+ }
216
+
205
217
/// If `expr` is a loop expression (while/while let/for/loop), calls `func` with
206
218
/// the AST object representing the loop block of `expr`.
207
219
fn with_loop_block < F > ( expr : & ast:: Expr , mut func : F )
208
220
where
209
- F : FnMut ( & ast:: Block ) ,
221
+ F : FnMut ( & ast:: Block , Option < & ast :: Label > ) ,
210
222
{
211
223
match expr. node {
212
- ast:: ExprKind :: While ( _, ref loop_block, _ )
213
- | ast:: ExprKind :: WhileLet ( _, _, ref loop_block, _ )
214
- | ast:: ExprKind :: ForLoop ( _, _, ref loop_block, _ )
215
- | ast:: ExprKind :: Loop ( ref loop_block, _ ) => func ( loop_block) ,
224
+ ast:: ExprKind :: While ( _, ref loop_block, ref label )
225
+ | ast:: ExprKind :: WhileLet ( _, _, ref loop_block, ref label )
226
+ | ast:: ExprKind :: ForLoop ( _, _, ref loop_block, ref label )
227
+ | ast:: ExprKind :: Loop ( ref loop_block, ref label ) => func ( loop_block, label . as_ref ( ) ) ,
216
228
_ => { } ,
217
229
}
218
230
}
@@ -350,7 +362,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(
350
362
}
351
363
352
364
fn check_and_warn < ' a > ( ctx : & EarlyContext < ' _ > , expr : & ' a ast:: Expr ) {
353
- with_loop_block ( expr, |loop_block| {
365
+ with_loop_block ( expr, |loop_block, label | {
354
366
for ( i, stmt) in loop_block. stmts . iter ( ) . enumerate ( ) {
355
367
with_if_expr ( stmt, |if_expr, cond, then_block, else_expr| {
356
368
let data = & LintData {
@@ -361,14 +373,14 @@ fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) {
361
373
else_expr,
362
374
block_stmts : & loop_block. stmts ,
363
375
} ;
364
- if needless_continue_in_else ( else_expr) {
376
+ if needless_continue_in_else ( else_expr, label ) {
365
377
emit_warning (
366
378
ctx,
367
379
data,
368
380
DROP_ELSE_BLOCK_AND_MERGE_MSG ,
369
381
LintType :: ContinueInsideElseBlock ,
370
382
) ;
371
- } else if is_first_block_stmt_continue ( then_block) {
383
+ } else if is_first_block_stmt_continue ( then_block, label ) {
372
384
emit_warning ( ctx, data, DROP_ELSE_BLOCK_MSG , LintType :: ContinueInsideThenBlock ) ;
373
385
}
374
386
} ) ;
0 commit comments