@@ -378,7 +378,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
378
378
match expr. node {
379
379
ExprWhile ( _, ref block, _) |
380
380
ExprLoop ( ref block, _, _) => {
381
- if never_loop ( block, & expr. id ) {
381
+ if never_loop ( block, expr. id ) {
382
382
span_lint ( cx, NEVER_LOOP , expr. span , "this loop never actually loops" ) ;
383
383
}
384
384
} ,
@@ -485,27 +485,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
485
485
}
486
486
}
487
487
488
- fn never_loop ( block : & Block , id : & NodeId ) -> bool {
489
- !contains_continue_block ( block, id) && loop_exit_block ( block)
488
+ fn never_loop ( block : & Block , id : NodeId ) -> bool {
489
+ !contains_continue_block ( block, Some ( id) ) && loop_exit_block ( block, & mut vec ! [ id ] )
490
490
}
491
491
492
- fn contains_continue_block ( block : & Block , dest : & NodeId ) -> bool {
492
+ fn contains_continue_block ( block : & Block , dest : Option < NodeId > ) -> bool {
493
493
block. stmts . iter ( ) . any ( |e| contains_continue_stmt ( e, dest) ) ||
494
494
block. expr . as_ref ( ) . map_or (
495
495
false ,
496
496
|e| contains_continue_expr ( e, dest) ,
497
497
)
498
498
}
499
499
500
- fn contains_continue_stmt ( stmt : & Stmt , dest : & NodeId ) -> bool {
500
+ fn contains_continue_stmt ( stmt : & Stmt , dest : Option < NodeId > ) -> bool {
501
501
match stmt. node {
502
502
StmtSemi ( ref e, _) |
503
503
StmtExpr ( ref e, _) => contains_continue_expr ( e, dest) ,
504
504
StmtDecl ( ref d, _) => contains_continue_decl ( d, dest) ,
505
505
}
506
506
}
507
507
508
- fn contains_continue_decl ( decl : & Decl , dest : & NodeId ) -> bool {
508
+ fn contains_continue_decl ( decl : & Decl , dest : Option < NodeId > ) -> bool {
509
509
match decl. node {
510
510
DeclLocal ( ref local) => {
511
511
local. init . as_ref ( ) . map_or (
@@ -517,7 +517,7 @@ fn contains_continue_decl(decl: &Decl, dest: &NodeId) -> bool {
517
517
}
518
518
}
519
519
520
- fn contains_continue_expr ( expr : & Expr , dest : & NodeId ) -> bool {
520
+ fn contains_continue_expr ( expr : & Expr , dest : Option < NodeId > ) -> bool {
521
521
match expr. node {
522
522
ExprRet ( Some ( ref e) ) |
523
523
ExprBox ( ref e) |
@@ -555,31 +555,32 @@ fn contains_continue_expr(expr: &Expr, dest: &NodeId) -> bool {
555
555
|e| contains_continue_expr ( e, dest) ,
556
556
)
557
557
} ,
558
- ExprAgain ( d) => d. target_id . opt_id ( ) . map_or ( false , |id| id == * dest) ,
558
+ ExprAgain ( d) => dest . map_or ( true , |dest| d. target_id . opt_id ( ) . map_or ( false , |id| id == dest) ) ,
559
559
_ => false ,
560
560
}
561
561
}
562
562
563
- fn loop_exit_block ( block : & Block ) -> bool {
564
- block. stmts . iter ( ) . any ( |e| loop_exit_stmt ( e) ) || block. expr . as_ref ( ) . map_or ( false , |e| loop_exit_expr ( e) )
563
+ fn loop_exit_block ( block : & Block , loops : & mut Vec < NodeId > ) -> bool {
564
+ block. stmts . iter ( ) . take_while ( |s| !contains_continue_stmt ( s, None ) ) . any ( |s| loop_exit_stmt ( s, loops) )
565
+ || block. expr . as_ref ( ) . map_or ( false , |e| loop_exit_expr ( e, loops) )
565
566
}
566
567
567
- fn loop_exit_stmt ( stmt : & Stmt ) -> bool {
568
+ fn loop_exit_stmt ( stmt : & Stmt , loops : & mut Vec < NodeId > ) -> bool {
568
569
match stmt. node {
569
570
StmtSemi ( ref e, _) |
570
- StmtExpr ( ref e, _) => loop_exit_expr ( e) ,
571
- StmtDecl ( ref d, _) => loop_exit_decl ( d) ,
571
+ StmtExpr ( ref e, _) => loop_exit_expr ( e, loops ) ,
572
+ StmtDecl ( ref d, _) => loop_exit_decl ( d, loops ) ,
572
573
}
573
574
}
574
575
575
- fn loop_exit_decl ( decl : & Decl ) -> bool {
576
+ fn loop_exit_decl ( decl : & Decl , loops : & mut Vec < NodeId > ) -> bool {
576
577
match decl. node {
577
- DeclLocal ( ref local) => local. init . as_ref ( ) . map_or ( false , |e| loop_exit_expr ( e) ) ,
578
+ DeclLocal ( ref local) => local. init . as_ref ( ) . map_or ( false , |e| loop_exit_expr ( e, loops ) ) ,
578
579
_ => false ,
579
580
}
580
581
}
581
582
582
- fn loop_exit_expr ( expr : & Expr ) -> bool {
583
+ fn loop_exit_expr ( expr : & Expr , loops : & mut Vec < NodeId > ) -> bool {
583
584
match expr. node {
584
585
ExprBox ( ref e) |
585
586
ExprUnary ( _, ref e) |
@@ -588,22 +589,34 @@ fn loop_exit_expr(expr: &Expr) -> bool {
588
589
ExprField ( ref e, _) |
589
590
ExprTupField ( ref e, _) |
590
591
ExprAddrOf ( _, ref e) |
591
- ExprRepeat ( ref e, _) => loop_exit_expr ( e) ,
592
+ ExprRepeat ( ref e, _) => loop_exit_expr ( e, loops ) ,
592
593
ExprArray ( ref es) |
593
594
ExprMethodCall ( _, _, ref es) |
594
- ExprTup ( ref es) => es. iter ( ) . any ( |e| loop_exit_expr ( e) ) ,
595
- ExprCall ( ref e, ref es) => loop_exit_expr ( e) || es. iter ( ) . any ( |e| loop_exit_expr ( e) ) ,
595
+ ExprTup ( ref es) => es. iter ( ) . any ( |e| loop_exit_expr ( e, loops ) ) ,
596
+ ExprCall ( ref e, ref es) => loop_exit_expr ( e, loops ) || es. iter ( ) . any ( |e| loop_exit_expr ( e, loops ) ) ,
596
597
ExprBinary ( _, ref e1, ref e2) |
597
598
ExprAssign ( ref e1, ref e2) |
598
599
ExprAssignOp ( _, ref e1, ref e2) |
599
- ExprIndex ( ref e1, ref e2) => [ e1, e2] . iter ( ) . any ( |e| loop_exit_expr ( e) ) ,
600
- ExprIf ( ref e, ref e2, ref e3) => {
601
- loop_exit_expr ( e) || e3. as_ref ( ) . map_or ( false , |e| loop_exit_expr ( e) ) && loop_exit_expr ( e2)
600
+ ExprIndex ( ref e1, ref e2) => [ e1, e2] . iter ( ) . any ( |e| loop_exit_expr ( e, loops) ) ,
601
+ ExprIf ( ref e, ref e2, ref e3) => loop_exit_expr ( e, loops)
602
+ || e3. as_ref ( ) . map_or ( false , |e3| loop_exit_expr ( e3, loops) ) && loop_exit_expr ( e2, loops) ,
603
+ ExprLoop ( ref b, _, _) => {
604
+ loops. push ( expr. id ) ;
605
+ let val = loop_exit_block ( b, loops) ;
606
+ loops. pop ( ) ;
607
+ val
608
+ } ,
609
+ ExprWhile ( ref e, ref b, _) => {
610
+ loops. push ( expr. id ) ;
611
+ let val = loop_exit_expr ( e, loops) || loop_exit_block ( b, loops) ;
612
+ loops. pop ( ) ;
613
+ val
602
614
} ,
603
- ExprWhile ( ref e, ref b, _) => loop_exit_expr ( e) || loop_exit_block ( b) ,
604
- ExprMatch ( ref e, ref arms, _) => loop_exit_expr ( e) || arms. iter ( ) . all ( |a| loop_exit_expr ( & a. body ) ) ,
605
- ExprBlock ( ref b) => loop_exit_block ( b) ,
606
- ExprBreak ( _, _) | ExprAgain ( _) | ExprRet ( _) => true ,
615
+ ExprMatch ( ref e, ref arms, _) => loop_exit_expr ( e, loops) || arms. iter ( ) . all ( |a| loop_exit_expr ( & a. body , loops) ) ,
616
+ ExprBlock ( ref b) => loop_exit_block ( b, loops) ,
617
+ ExprAgain ( d) => d. target_id . opt_id ( ) . map_or ( false , |id| loops. iter ( ) . skip ( 1 ) . all ( |& id2| id != id2) ) ,
618
+ ExprBreak ( d, _) => d. target_id . opt_id ( ) . map_or ( false , |id| loops[ 0 ] == id) ,
619
+ ExprRet ( _) => true ,
607
620
_ => false ,
608
621
}
609
622
}
0 commit comments