@@ -5,16 +5,15 @@ use clippy_utils::visitors::for_each_expr_with_closures;
55use clippy_utils:: { get_parent_node, inherits_cfg, is_from_proc_macro, is_self} ;
66use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
77use rustc_errors:: Applicability ;
8- use rustc_hir:: intravisit:: { walk_qpath , FnKind , Visitor } ;
8+ use rustc_hir:: intravisit:: FnKind ;
99use rustc_hir:: {
1010 BlockCheckMode , Body , Closure , Expr , ExprKind , FnDecl , HirId , HirIdMap , HirIdSet , Impl , ItemKind , Mutability , Node ,
11- PatKind , QPath ,
11+ PatKind ,
1212} ;
1313use rustc_hir_typeck:: expr_use_visitor as euv;
1414use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
1515use rustc_lint:: { LateContext , LateLintPass } ;
1616use rustc_middle:: hir:: map:: associated_body;
17- use rustc_middle:: hir:: nested_filter:: OnlyBodies ;
1817use rustc_middle:: mir:: FakeReadCause ;
1918use rustc_middle:: ty:: { self , Ty , TyCtxt , UpvarId , UpvarPath } ;
2019use rustc_session:: impl_lint_pass;
@@ -234,12 +233,29 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
234233 }
235234 }
236235
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+ }
242249
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 > ) {
243259 for ( fn_def_id, unused) in self
244260 . fn_def_ids_to_maybe_unused_mut
245261 . iter ( )
@@ -501,48 +517,3 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
501517 }
502518 }
503519}
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