@@ -39,6 +39,7 @@ pub(super) fn check(
3939 } ) ;
4040 } ,
4141 NeverLoopResult :: MayContinueMainLoop | NeverLoopResult :: Otherwise => ( ) ,
42+ NeverLoopResult :: IgnoreUntilEnd ( _) => unreachable ! ( ) ,
4243 }
4344}
4445
@@ -48,6 +49,8 @@ enum NeverLoopResult {
4849 AlwaysBreak ,
4950 // A continue may occur for the main loop.
5051 MayContinueMainLoop ,
52+ // Ignore everything until the end of the block with this id
53+ IgnoreUntilEnd ( HirId ) ,
5154 Otherwise ,
5255}
5356
@@ -56,22 +59,34 @@ fn absorb_break(arg: NeverLoopResult) -> NeverLoopResult {
5659 match arg {
5760 NeverLoopResult :: AlwaysBreak | NeverLoopResult :: Otherwise => NeverLoopResult :: Otherwise ,
5861 NeverLoopResult :: MayContinueMainLoop => NeverLoopResult :: MayContinueMainLoop ,
62+ NeverLoopResult :: IgnoreUntilEnd ( id) => NeverLoopResult :: IgnoreUntilEnd ( id) ,
5963 }
6064}
6165
6266// Combine two results for parts that are called in order.
6367#[ must_use]
6468fn combine_seq ( first : NeverLoopResult , second : NeverLoopResult ) -> NeverLoopResult {
6569 match first {
66- NeverLoopResult :: AlwaysBreak | NeverLoopResult :: MayContinueMainLoop => first,
70+ NeverLoopResult :: AlwaysBreak | NeverLoopResult :: MayContinueMainLoop | NeverLoopResult :: IgnoreUntilEnd ( _) => {
71+ first
72+ } ,
6773 NeverLoopResult :: Otherwise => second,
6874 }
6975}
7076
7177// Combine two results where only one of the part may have been executed.
7278#[ must_use]
73- fn combine_branches ( b1 : NeverLoopResult , b2 : NeverLoopResult ) -> NeverLoopResult {
79+ fn combine_branches ( b1 : NeverLoopResult , b2 : NeverLoopResult , ignore_ids : & [ HirId ] ) -> NeverLoopResult {
7480 match ( b1, b2) {
81+ ( NeverLoopResult :: IgnoreUntilEnd ( a) , NeverLoopResult :: IgnoreUntilEnd ( b) ) => {
82+ if ignore_ids. iter ( ) . find ( |& e| e == & a || e == & b) . unwrap ( ) == & a {
83+ NeverLoopResult :: IgnoreUntilEnd ( b)
84+ } else {
85+ NeverLoopResult :: IgnoreUntilEnd ( a)
86+ }
87+ } ,
88+ ( i @ NeverLoopResult :: IgnoreUntilEnd ( _) , NeverLoopResult :: AlwaysBreak )
89+ | ( NeverLoopResult :: AlwaysBreak , i @ NeverLoopResult :: IgnoreUntilEnd ( _) ) => i,
7590 ( NeverLoopResult :: AlwaysBreak , NeverLoopResult :: AlwaysBreak ) => NeverLoopResult :: AlwaysBreak ,
7691 ( NeverLoopResult :: MayContinueMainLoop , _) | ( _, NeverLoopResult :: MayContinueMainLoop ) => {
7792 NeverLoopResult :: MayContinueMainLoop
@@ -91,7 +106,7 @@ fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id
91106 let e = never_loop_expr ( e, ignore_ids, main_loop_id) ;
92107 // els is an else block in a let...else binding
93108 els. map_or ( e, |els| {
94- combine_branches ( e, never_loop_block ( els, ignore_ids, main_loop_id) )
109+ combine_branches ( e, never_loop_block ( els, ignore_ids, main_loop_id) , ignore_ids )
95110 } )
96111 } )
97112 . fold ( NeverLoopResult :: Otherwise , combine_seq)
@@ -147,7 +162,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
147162 let e3 = e3. as_ref ( ) . map_or ( NeverLoopResult :: Otherwise , |e| {
148163 never_loop_expr ( e, ignore_ids, main_loop_id)
149164 } ) ;
150- combine_seq ( e1, combine_branches ( e2, e3) )
165+ combine_seq ( e1, combine_branches ( e2, e3, ignore_ids ) )
151166 } ,
152167 ExprKind :: Match ( e, arms, _) => {
153168 let e = never_loop_expr ( e, ignore_ids, main_loop_id) ;
@@ -166,7 +181,10 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
166181 if l. is_some ( ) {
167182 ignore_ids. pop ( ) ;
168183 }
169- ret
184+ match ret {
185+ NeverLoopResult :: IgnoreUntilEnd ( a) if a == b. hir_id => NeverLoopResult :: Otherwise ,
186+ _ => ret,
187+ }
170188 } ,
171189 ExprKind :: Continue ( d) => {
172190 let id = d
@@ -180,7 +198,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
180198 } ,
181199 // checks if break targets a block instead of a loop
182200 ExprKind :: Break ( Destination { target_id : Ok ( t) , .. } , e) if ignore_ids. contains ( & t) => e
183- . map_or ( NeverLoopResult :: Otherwise , |e| {
201+ . map_or ( NeverLoopResult :: IgnoreUntilEnd ( t ) , |e| {
184202 never_loop_expr ( e, ignore_ids, main_loop_id)
185203 } ) ,
186204 ExprKind :: Break ( _, e) | ExprKind :: Ret ( e) => e. as_ref ( ) . map_or ( NeverLoopResult :: AlwaysBreak , |e| {
@@ -232,8 +250,9 @@ fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(
232250 ignore_ids : & mut Vec < HirId > ,
233251 main_loop_id : HirId ,
234252) -> NeverLoopResult {
235- e. map ( |e| never_loop_expr ( e, ignore_ids, main_loop_id) )
236- . fold ( NeverLoopResult :: AlwaysBreak , combine_branches)
253+ e. fold ( NeverLoopResult :: AlwaysBreak , |a, b| {
254+ combine_branches ( a, never_loop_expr ( b, ignore_ids, main_loop_id) , ignore_ids)
255+ } )
237256}
238257
239258fn for_to_if_let_sugg ( cx : & LateContext < ' _ > , iterator : & Expr < ' _ > , pat : & Pat < ' _ > ) -> String {
0 commit comments