@@ -175,19 +175,19 @@ impl EarlyLintPass for NeedlessContinue {
175175/// - The expression is a `continue` node.
176176/// - The expression node is a block with the first statement being a
177177/// `continue`.
178- fn needless_continue_in_else ( else_expr : & ast:: Expr ) -> bool {
178+ fn needless_continue_in_else ( else_expr : & ast:: Expr , label : Option < & ast :: Label > ) -> bool {
179179 match else_expr. node {
180- ast:: ExprKind :: Block ( ref else_block, _) => is_first_block_stmt_continue ( else_block) ,
181- ast:: ExprKind :: Continue ( _ ) => true ,
180+ ast:: ExprKind :: Block ( ref else_block, _) => is_first_block_stmt_continue ( else_block, label ) ,
181+ ast:: ExprKind :: Continue ( l ) => compare_labels ( label , l . as_ref ( ) ) ,
182182 _ => false ,
183183 }
184184}
185185
186- fn is_first_block_stmt_continue ( block : & ast:: Block ) -> bool {
186+ fn is_first_block_stmt_continue ( block : & ast:: Block , label : Option < & ast :: Label > ) -> bool {
187187 block. stmts . get ( 0 ) . map_or ( false , |stmt| match stmt. node {
188188 ast:: StmtKind :: Semi ( ref e) | ast:: StmtKind :: Expr ( ref e) => {
189- if let ast:: ExprKind :: Continue ( _ ) = e. node {
190- true
189+ if let ast:: ExprKind :: Continue ( ref l ) = e. node {
190+ compare_labels ( label , l . as_ref ( ) )
191191 } else {
192192 false
193193 }
@@ -196,17 +196,29 @@ fn is_first_block_stmt_continue(block: &ast::Block) -> bool {
196196 } )
197197}
198198
199+ /// If the `continue` has a label, check it matches the label of the loop.
200+ fn compare_labels ( loop_label : Option < & ast:: Label > , continue_label : Option < & ast:: Label > ) -> bool {
201+ match ( loop_label, continue_label) {
202+ // `loop { continue; }` or `'a loop { continue; }`
203+ ( _, None ) => true ,
204+ // `loop { continue 'a; }`
205+ ( None , _) => false ,
206+ // `'a loop { continue 'a; }` or `'a loop { continue 'b; }`
207+ ( Some ( x) , Some ( y) ) => x. ident == y. ident ,
208+ }
209+ }
210+
199211/// If `expr` is a loop expression (while/while let/for/loop), calls `func` with
200212/// the AST object representing the loop block of `expr`.
201213fn with_loop_block < F > ( expr : & ast:: Expr , mut func : F )
202214where
203- F : FnMut ( & ast:: Block ) ,
215+ F : FnMut ( & ast:: Block , Option < & ast :: Label > ) ,
204216{
205217 match expr. node {
206- ast:: ExprKind :: While ( _, ref loop_block, _ )
207- | ast:: ExprKind :: WhileLet ( _, _, ref loop_block, _ )
208- | ast:: ExprKind :: ForLoop ( _, _, ref loop_block, _ )
209- | ast:: ExprKind :: Loop ( ref loop_block, _ ) => func ( loop_block) ,
218+ ast:: ExprKind :: While ( _, ref loop_block, ref label )
219+ | ast:: ExprKind :: WhileLet ( _, _, ref loop_block, ref label )
220+ | ast:: ExprKind :: ForLoop ( _, _, ref loop_block, ref label )
221+ | ast:: ExprKind :: Loop ( ref loop_block, ref label ) => func ( loop_block, label . as_ref ( ) ) ,
210222 _ => { } ,
211223 }
212224}
@@ -344,7 +356,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(
344356}
345357
346358fn check_and_warn < ' a > ( ctx : & EarlyContext < ' _ > , expr : & ' a ast:: Expr ) {
347- with_loop_block ( expr, |loop_block| {
359+ with_loop_block ( expr, |loop_block, label | {
348360 for ( i, stmt) in loop_block. stmts . iter ( ) . enumerate ( ) {
349361 with_if_expr ( stmt, |if_expr, cond, then_block, else_expr| {
350362 let data = & LintData {
@@ -355,14 +367,14 @@ fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) {
355367 else_expr,
356368 block_stmts : & loop_block. stmts ,
357369 } ;
358- if needless_continue_in_else ( else_expr) {
370+ if needless_continue_in_else ( else_expr, label ) {
359371 emit_warning (
360372 ctx,
361373 data,
362374 DROP_ELSE_BLOCK_AND_MERGE_MSG ,
363375 LintType :: ContinueInsideElseBlock ,
364376 ) ;
365- } else if is_first_block_stmt_continue ( then_block) {
377+ } else if is_first_block_stmt_continue ( then_block, label ) {
366378 emit_warning ( ctx, data, DROP_ELSE_BLOCK_MSG , LintType :: ContinueInsideThenBlock ) ;
367379 }
368380 } ) ;
0 commit comments