@@ -5,16 +5,15 @@ use clippy_utils::visitors::for_each_expr_with_closures;
5
5
use clippy_utils:: { get_parent_node, inherits_cfg, is_from_proc_macro, is_self} ;
6
6
use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
7
7
use rustc_errors:: Applicability ;
8
- use rustc_hir:: intravisit:: { walk_qpath , FnKind , Visitor } ;
8
+ use rustc_hir:: intravisit:: FnKind ;
9
9
use rustc_hir:: {
10
10
BlockCheckMode , Body , Closure , Expr , ExprKind , FnDecl , HirId , HirIdMap , HirIdSet , Impl , ItemKind , Mutability , Node ,
11
- PatKind , QPath ,
11
+ PatKind ,
12
12
} ;
13
13
use rustc_hir_typeck:: expr_use_visitor as euv;
14
14
use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
15
15
use rustc_lint:: { LateContext , LateLintPass } ;
16
16
use rustc_middle:: hir:: map:: associated_body;
17
- use rustc_middle:: hir:: nested_filter:: OnlyBodies ;
18
17
use rustc_middle:: mir:: FakeReadCause ;
19
18
use rustc_middle:: ty:: { self , Ty , TyCtxt , UpvarId , UpvarPath } ;
20
19
use rustc_session:: impl_lint_pass;
@@ -234,12 +233,29 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
234
233
}
235
234
}
236
235
237
- fn check_crate_post ( & mut self , cx : & LateContext < ' tcx > ) {
238
- cx. tcx . hir ( ) . visit_all_item_likes_in_crate ( & mut FnNeedsMutVisitor {
239
- cx,
240
- used_fn_def_ids : & mut self . used_fn_def_ids ,
241
- } ) ;
236
+ fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > ) {
237
+ // #11182; do not lint if mutability is required elsewhere
238
+ if let ExprKind :: Path ( ..) = expr. kind
239
+ && let Some ( parent) = get_parent_node ( cx. tcx , expr. hir_id )
240
+ && let ty:: FnDef ( def_id, _) = cx. typeck_results ( ) . expr_ty ( expr) . kind ( )
241
+ && let Some ( def_id) = def_id. as_local ( )
242
+ {
243
+ if let Node :: Expr ( e) = parent
244
+ && let ExprKind :: Call ( call, _) = e. kind
245
+ && call. hir_id == expr. hir_id
246
+ {
247
+ return ;
248
+ }
242
249
250
+ // We don't need to check each argument individually as you cannot coerce a function
251
+ // taking `&mut` -> `&`, for some reason, so if we've gotten this far we know it's
252
+ // passed as a `fn`-like argument (or is unified) and should ignore every "unused"
253
+ // argument entirely
254
+ self . used_fn_def_ids . insert ( def_id) ;
255
+ }
256
+ }
257
+
258
+ fn check_crate_post ( & mut self , cx : & LateContext < ' tcx > ) {
243
259
for ( fn_def_id, unused) in self
244
260
. fn_def_ids_to_maybe_unused_mut
245
261
. iter ( )
@@ -501,48 +517,3 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
501
517
}
502
518
}
503
519
}
504
-
505
- /// A final pass to check for paths referencing this function that require the argument to be
506
- /// `&mut`, basically if the function is ever used as a `fn`-like argument.
507
- struct FnNeedsMutVisitor < ' a , ' tcx > {
508
- cx : & ' a LateContext < ' tcx > ,
509
- used_fn_def_ids : & ' a mut FxHashSet < LocalDefId > ,
510
- }
511
-
512
- impl < ' tcx > Visitor < ' tcx > for FnNeedsMutVisitor < ' _ , ' tcx > {
513
- type NestedFilter = OnlyBodies ;
514
-
515
- fn nested_visit_map ( & mut self ) -> Self :: Map {
516
- self . cx . tcx . hir ( )
517
- }
518
-
519
- fn visit_qpath ( & mut self , qpath : & ' tcx QPath < ' tcx > , hir_id : HirId , _: Span ) {
520
- walk_qpath ( self , qpath, hir_id) ;
521
-
522
- let Self { cx, used_fn_def_ids } = self ;
523
-
524
- // #11182; do not lint if mutability is required elsewhere
525
- if let Node :: Expr ( expr) = cx. tcx . hir_node ( hir_id)
526
- && let Some ( parent) = get_parent_node ( cx. tcx , expr. hir_id )
527
- && let ty:: FnDef ( def_id, _) = cx
528
- . tcx
529
- . typeck ( cx. tcx . hir ( ) . enclosing_body_owner ( hir_id) )
530
- . expr_ty ( expr)
531
- . kind ( )
532
- && let Some ( def_id) = def_id. as_local ( )
533
- {
534
- if let Node :: Expr ( e) = parent
535
- && let ExprKind :: Call ( call, _) = e. kind
536
- && call. hir_id == expr. hir_id
537
- {
538
- return ;
539
- }
540
-
541
- // We don't need to check each argument individually as you cannot coerce a function
542
- // taking `&mut` -> `&`, for some reason, so if we've gotten this far we know it's
543
- // passed as a `fn`-like argument (or is unified) and should ignore every "unused"
544
- // argument entirely
545
- used_fn_def_ids. insert ( def_id) ;
546
- }
547
- }
548
- }
0 commit comments