@@ -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,34 +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,
67- NeverLoopResult :: Otherwise => second,
68- }
69- }
70-
71- // Combine two results where both parts are called but not necessarily in order.
72- #[ must_use]
73- fn combine_both ( left : NeverLoopResult , right : NeverLoopResult ) -> NeverLoopResult {
74- match ( left, right) {
75- ( NeverLoopResult :: MayContinueMainLoop , _) | ( _, NeverLoopResult :: MayContinueMainLoop ) => {
76- NeverLoopResult :: MayContinueMainLoop
70+ NeverLoopResult :: AlwaysBreak | NeverLoopResult :: MayContinueMainLoop | NeverLoopResult :: IgnoreUntilEnd ( _) => {
71+ first
7772 } ,
78- ( NeverLoopResult :: AlwaysBreak , _) | ( _, NeverLoopResult :: AlwaysBreak ) => NeverLoopResult :: AlwaysBreak ,
79- ( NeverLoopResult :: Otherwise , NeverLoopResult :: Otherwise ) => NeverLoopResult :: Otherwise ,
73+ NeverLoopResult :: Otherwise => second,
8074 }
8175}
8276
8377// Combine two results where only one of the part may have been executed.
8478#[ must_use]
85- fn combine_branches ( b1 : NeverLoopResult , b2 : NeverLoopResult ) -> NeverLoopResult {
79+ fn combine_branches ( b1 : NeverLoopResult , b2 : NeverLoopResult , ignore_ids : & [ HirId ] ) -> NeverLoopResult {
8680 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,
8790 ( NeverLoopResult :: AlwaysBreak , NeverLoopResult :: AlwaysBreak ) => NeverLoopResult :: AlwaysBreak ,
8891 ( NeverLoopResult :: MayContinueMainLoop , _) | ( _, NeverLoopResult :: MayContinueMainLoop ) => {
8992 NeverLoopResult :: MayContinueMainLoop
@@ -103,7 +106,7 @@ fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id
103106 let e = never_loop_expr ( e, ignore_ids, main_loop_id) ;
104107 // els is an else block in a let...else binding
105108 els. map_or ( e, |els| {
106- 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 )
107110 } )
108111 } )
109112 . fold ( NeverLoopResult :: Otherwise , combine_seq)
@@ -139,7 +142,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
139142 ExprKind :: Struct ( _, fields, base) => {
140143 let fields = never_loop_expr_all ( & mut fields. iter ( ) . map ( |f| f. expr ) , ignore_ids, main_loop_id) ;
141144 if let Some ( base) = base {
142- combine_both ( fields, never_loop_expr ( base, ignore_ids, main_loop_id) )
145+ combine_seq ( fields, never_loop_expr ( base, ignore_ids, main_loop_id) )
143146 } else {
144147 fields
145148 }
@@ -159,7 +162,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
159162 let e3 = e3. as_ref ( ) . map_or ( NeverLoopResult :: Otherwise , |e| {
160163 never_loop_expr ( e, ignore_ids, main_loop_id)
161164 } ) ;
162- combine_seq ( e1, combine_branches ( e2, e3) )
165+ combine_seq ( e1, combine_branches ( e2, e3, ignore_ids ) )
163166 } ,
164167 ExprKind :: Match ( e, arms, _) => {
165168 let e = never_loop_expr ( e, ignore_ids, main_loop_id) ;
@@ -175,8 +178,13 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
175178 ignore_ids. push ( b. hir_id ) ;
176179 }
177180 let ret = never_loop_block ( b, ignore_ids, main_loop_id) ;
178- ignore_ids. pop ( ) ;
179- ret
181+ if l. is_some ( ) {
182+ ignore_ids. pop ( ) ;
183+ }
184+ match ret {
185+ NeverLoopResult :: IgnoreUntilEnd ( a) if a == b. hir_id => NeverLoopResult :: Otherwise ,
186+ _ => ret,
187+ }
180188 } ,
181189 ExprKind :: Continue ( d) => {
182190 let id = d
@@ -190,8 +198,8 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
190198 } ,
191199 // checks if break targets a block instead of a loop
192200 ExprKind :: Break ( Destination { target_id : Ok ( t) , .. } , e) if ignore_ids. contains ( & t) => e
193- . map_or ( NeverLoopResult :: Otherwise , |e| {
194- combine_seq ( never_loop_expr ( e, ignore_ids, main_loop_id) , NeverLoopResult :: Otherwise )
201+ . map_or ( NeverLoopResult :: IgnoreUntilEnd ( t ) , |e| {
202+ never_loop_expr ( e, ignore_ids, main_loop_id)
195203 } ) ,
196204 ExprKind :: Break ( _, e) | ExprKind :: Ret ( e) => e. as_ref ( ) . map_or ( NeverLoopResult :: AlwaysBreak , |e| {
197205 combine_seq (
@@ -218,7 +226,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
218226 | InlineAsmOperand :: SymFn { .. }
219227 | InlineAsmOperand :: SymStatic { .. } => NeverLoopResult :: Otherwise ,
220228 } )
221- . fold ( NeverLoopResult :: Otherwise , combine_both ) ,
229+ . fold ( NeverLoopResult :: Otherwise , combine_seq ) ,
222230 ExprKind :: Yield ( _, _)
223231 | ExprKind :: Closure { .. }
224232 | ExprKind :: Path ( _)
@@ -234,16 +242,17 @@ fn never_loop_expr_all<'a, T: Iterator<Item = &'a Expr<'a>>>(
234242 main_loop_id : HirId ,
235243) -> NeverLoopResult {
236244 es. map ( |e| never_loop_expr ( e, ignore_ids, main_loop_id) )
237- . fold ( NeverLoopResult :: Otherwise , combine_both )
245+ . fold ( NeverLoopResult :: Otherwise , combine_seq )
238246}
239247
240248fn never_loop_expr_branch < ' a , T : Iterator < Item = & ' a Expr < ' a > > > (
241249 e : & mut T ,
242250 ignore_ids : & mut Vec < HirId > ,
243251 main_loop_id : HirId ,
244252) -> NeverLoopResult {
245- e. map ( |e| never_loop_expr ( e, ignore_ids, main_loop_id) )
246- . 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+ } )
247256}
248257
249258fn for_to_if_let_sugg ( cx : & LateContext < ' _ > , iterator : & Expr < ' _ > , pat : & Pat < ' _ > ) -> String {
0 commit comments