Skip to content

Commit 0774489

Browse files
committed
find function path references early in the lint pass
1 parent a71211d commit 0774489

File tree

1 file changed

+24
-53
lines changed

1 file changed

+24
-53
lines changed

clippy_lints/src/needless_pass_by_ref_mut.rs

Lines changed: 24 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@ use clippy_utils::visitors::for_each_expr_with_closures;
55
use clippy_utils::{get_parent_node, inherits_cfg, is_from_proc_macro, is_self};
66
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
77
use rustc_errors::Applicability;
8-
use rustc_hir::intravisit::{walk_qpath, FnKind, Visitor};
8+
use rustc_hir::intravisit::FnKind;
99
use rustc_hir::{
1010
BlockCheckMode, Body, Closure, Expr, ExprKind, FnDecl, HirId, HirIdMap, HirIdSet, Impl, ItemKind, Mutability, Node,
11-
PatKind, QPath,
11+
PatKind,
1212
};
1313
use rustc_hir_typeck::expr_use_visitor as euv;
1414
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
1515
use rustc_lint::{LateContext, LateLintPass};
1616
use rustc_middle::hir::map::associated_body;
17-
use rustc_middle::hir::nested_filter::OnlyBodies;
1817
use rustc_middle::mir::FakeReadCause;
1918
use rustc_middle::ty::{self, Ty, TyCtxt, UpvarId, UpvarPath};
2019
use 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

Comments
 (0)