1
1
use super :: needless_pass_by_value:: requires_exact_signature;
2
2
use clippy_utils:: diagnostics:: span_lint_hir_and_then;
3
3
use clippy_utils:: source:: snippet;
4
+ use clippy_utils:: visitors:: for_each_expr_with_closures;
4
5
use clippy_utils:: { get_parent_node, inherits_cfg, is_from_proc_macro, is_self} ;
5
6
use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
6
7
use rustc_errors:: Applicability ;
7
- use rustc_hir:: intravisit:: { walk_fn , walk_qpath, FnKind , Visitor } ;
8
+ use rustc_hir:: intravisit:: { walk_qpath, FnKind , Visitor } ;
8
9
use rustc_hir:: {
9
- Body , BodyId , Closure , Expr , ExprKind , FnDecl , HirId , HirIdMap , HirIdSet , Impl , ItemKind , Mutability , Node ,
10
- PatKind , QPath ,
10
+ Body , Closure , Expr , ExprKind , FnDecl , HirId , HirIdMap , HirIdSet , Impl , ItemKind , Mutability , Node , PatKind , QPath ,
11
11
} ;
12
12
use rustc_hir_typeck:: expr_use_visitor as euv;
13
13
use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
@@ -22,6 +22,8 @@ use rustc_span::symbol::kw;
22
22
use rustc_span:: Span ;
23
23
use rustc_target:: spec:: abi:: Abi ;
24
24
25
+ use core:: ops:: ControlFlow ;
26
+
25
27
declare_clippy_lint ! {
26
28
/// ### What it does
27
29
/// Check if a `&mut` function argument is actually used mutably.
@@ -189,17 +191,19 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
189
191
190
192
// We retrieve all the closures declared in the async function because they will
191
193
// not be found by `euv::Delegate`.
192
- let mut closures_retriever = ClosuresRetriever {
193
- cx,
194
- closures : FxHashSet :: default ( ) ,
195
- } ;
196
- walk_fn ( & mut closures_retriever, kind, decl, body. id ( ) , fn_def_id) ;
197
- check_closures ( & mut ctx, cx, & infcx, & mut checked_closures, closures_retriever. closures ) ;
194
+ let mut closures: FxHashSet < LocalDefId > = FxHashSet :: default ( ) ;
195
+ for_each_expr_with_closures ( cx, body, |expr| {
196
+ if let ExprKind :: Closure ( closure) = expr. kind {
197
+ closures. insert ( closure. def_id ) ;
198
+ }
199
+ ControlFlow :: < ( ) > :: Continue ( ( ) )
200
+ } ) ;
201
+ check_closures ( & mut ctx, cx, & infcx, & mut checked_closures, closures) ;
198
202
199
203
while !ctx. async_closures . is_empty ( ) {
200
- let closures = ctx. async_closures . clone ( ) ;
204
+ let async_closures = ctx. async_closures . clone ( ) ;
201
205
ctx. async_closures . clear ( ) ;
202
- check_closures ( & mut ctx, cx, & infcx, & mut checked_closures, closures ) ;
206
+ check_closures ( & mut ctx, cx, & infcx, & mut checked_closures, async_closures ) ;
203
207
}
204
208
}
205
209
ctx
@@ -264,6 +268,10 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
264
268
struct MutablyUsedVariablesCtxt < ' tcx > {
265
269
mutably_used_vars : HirIdSet ,
266
270
prev_bind : Option < HirId > ,
271
+ /// In async functions, the inner AST is composed of multiple layers until we reach the code
272
+ /// defined by the user. Because of that, some variables are marked as mutably borrowed even
273
+ /// though they're not. This field lists the `HirId` that should not be considered as mutable
274
+ /// use of a variable.
267
275
prev_move_to_closure : HirIdSet ,
268
276
aliases : HirIdMap < HirId > ,
269
277
async_closures : FxHashSet < LocalDefId > ,
@@ -459,30 +467,3 @@ impl<'tcx> Visitor<'tcx> for FnNeedsMutVisitor<'_, 'tcx> {
459
467
}
460
468
}
461
469
}
462
-
463
- struct ClosuresRetriever < ' a , ' tcx > {
464
- cx : & ' a LateContext < ' tcx > ,
465
- closures : FxHashSet < LocalDefId > ,
466
- }
467
-
468
- impl < ' a , ' tcx > Visitor < ' tcx > for ClosuresRetriever < ' a , ' tcx > {
469
- type NestedFilter = OnlyBodies ;
470
-
471
- fn nested_visit_map ( & mut self ) -> Self :: Map {
472
- self . cx . tcx . hir ( )
473
- }
474
-
475
- fn visit_fn (
476
- & mut self ,
477
- kind : FnKind < ' tcx > ,
478
- decl : & ' tcx FnDecl < ' tcx > ,
479
- body_id : BodyId ,
480
- _span : Span ,
481
- fn_def_id : LocalDefId ,
482
- ) {
483
- if matches ! ( kind, FnKind :: Closure ) {
484
- self . closures . insert ( fn_def_id) ;
485
- }
486
- walk_fn ( self , kind, decl, body_id, fn_def_id) ;
487
- }
488
- }
0 commit comments