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} ;
2
3
use core:: ops:: ControlFlow ;
3
4
use hir:: def:: Res ;
4
5
use 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 } ;
6
7
use rustc_hir_typeck:: expr_use_visitor:: { Delegate , ExprUseVisitor , PlaceBase , PlaceWithHirId } ;
7
8
use rustc_infer:: infer:: TyCtxtInferExt ;
8
9
use rustc_lint:: LateContext ;
9
10
use rustc_middle:: hir:: nested_filter;
10
11
use rustc_middle:: mir:: FakeReadCause ;
11
12
use rustc_middle:: ty;
12
- use { crate as utils, rustc_hir as hir} ;
13
13
14
14
/// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined.
15
15
pub 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 {
154
154
. is_some ( )
155
155
}
156
156
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
+
157
168
pub fn local_used_after_expr ( cx : & LateContext < ' _ > , local_id : HirId , after : & Expr < ' _ > ) -> bool {
158
169
let Some ( block) = utils:: get_enclosing_block ( cx, local_id) else {
159
170
return false ;
@@ -166,32 +177,21 @@ pub fn local_used_after_expr(cx: &LateContext<'_>, local_id: HirId, after: &Expr
166
177
// let closure = || local;
167
178
// closure();
168
179
// 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 ) ;
186
181
187
182
let mut past_expr = false ;
188
183
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 {
190
191
past_expr = true ;
191
192
ControlFlow :: Continue ( Descend :: No )
192
- } else if past_expr && utils:: path_to_local_id ( e, local_id) {
193
- ControlFlow :: Break ( ( ) )
194
193
} else {
194
+ past_expr = Some ( e. hir_id ) == loop_start;
195
195
ControlFlow :: Continue ( Descend :: Yes )
196
196
}
197
197
} )
0 commit comments