1- use crate :: visitors:: { for_each_expr, for_each_expr_with_closures, Descend } ;
1+ use crate :: visitors:: { for_each_expr, for_each_expr_with_closures, Descend , Visitable } ;
2+ use crate :: { self as utils, get_enclosing_loop_or_multi_call_closure} ;
23use core:: ops:: ControlFlow ;
34use hir:: def:: Res ;
45use rustc_hir:: intravisit:: { self , Visitor } ;
5- use rustc_hir:: { Expr , ExprKind , HirId , HirIdSet , Node } ;
6+ use rustc_hir:: { self as hir , Expr , ExprKind , HirId , HirIdSet } ;
67use rustc_hir_typeck:: expr_use_visitor:: { Delegate , ExprUseVisitor , PlaceBase , PlaceWithHirId } ;
78use rustc_infer:: infer:: TyCtxtInferExt ;
89use rustc_lint:: LateContext ;
910use rustc_middle:: hir:: nested_filter;
1011use rustc_middle:: mir:: FakeReadCause ;
1112use rustc_middle:: ty;
12- use { crate as utils, rustc_hir as hir} ;
1313
1414/// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined.
1515pub fn mutated_variables < ' tcx > ( expr : & ' tcx Expr < ' _ > , cx : & LateContext < ' tcx > ) -> Option < HirIdSet > {
@@ -154,6 +154,17 @@ pub fn contains_return_break_continue_macro(expression: &Expr<'_>) -> bool {
154154 . is_some ( )
155155}
156156
157+ pub fn local_used_in < ' tcx > ( cx : & LateContext < ' tcx > , local_id : HirId , v : impl Visitable < ' tcx > ) -> bool {
158+ for_each_expr_with_closures ( cx, v, |e| {
159+ if utils:: path_to_local_id ( e, local_id) {
160+ ControlFlow :: Break ( ( ) )
161+ } else {
162+ ControlFlow :: Continue ( ( ) )
163+ }
164+ } )
165+ . is_some ( )
166+ }
167+
157168pub fn local_used_after_expr ( cx : & LateContext < ' _ > , local_id : HirId , after : & Expr < ' _ > ) -> bool {
158169 let Some ( block) = utils:: get_enclosing_block ( cx, local_id) else {
159170 return false ;
@@ -166,32 +177,21 @@ pub fn local_used_after_expr(cx: &LateContext<'_>, local_id: HirId, after: &Expr
166177 // let closure = || local;
167178 // closure();
168179 // closure();
169- let in_loop_or_closure = cx
170- . tcx
171- . hir ( )
172- . parent_iter ( after. hir_id )
173- . take_while ( |& ( id, _) | id != block. hir_id )
174- . any ( |( _, node) | {
175- matches ! (
176- node,
177- Node :: Expr ( Expr {
178- kind: ExprKind :: Loop ( ..) | ExprKind :: Closure { .. } ,
179- ..
180- } )
181- )
182- } ) ;
183- if in_loop_or_closure {
184- return true ;
185- }
180+ let loop_start = get_enclosing_loop_or_multi_call_closure ( cx, after) . map ( |e| e. hir_id ) ;
186181
187182 let mut past_expr = false ;
188183 for_each_expr_with_closures ( cx, block, |e| {
189- if e. hir_id == after. hir_id {
184+ if past_expr {
185+ if utils:: path_to_local_id ( e, local_id) {
186+ ControlFlow :: Break ( ( ) )
187+ } else {
188+ ControlFlow :: Continue ( Descend :: Yes )
189+ }
190+ } else if e. hir_id == after. hir_id {
190191 past_expr = true ;
191192 ControlFlow :: Continue ( Descend :: No )
192- } else if past_expr && utils:: path_to_local_id ( e, local_id) {
193- ControlFlow :: Break ( ( ) )
194193 } else {
194+ past_expr = Some ( e. hir_id ) == loop_start;
195195 ControlFlow :: Continue ( Descend :: Yes )
196196 }
197197 } )
0 commit comments