]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/unused_self.rs
Rollup merge of #83092 - petrochenkov:qspan, r=estebank
[rust.git] / clippy_lints / src / unused_self.rs
index 8579fd73fbb75322bbea7dea35d7b015430d23b2..812482cf5cfb6638bdbb7eeaa18461c6937a8467 100644 (file)
@@ -1,12 +1,10 @@
 use if_chain::if_chain;
-use rustc::hir::map::Map;
-use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
-use rustc_hir::{AssocItemKind, HirId, ImplItem, ImplItemKind, ImplItemRef, ItemKind, Path};
+use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 use crate::utils::span_lint_and_help;
+use crate::utils::visitors::LocalUsedVisitor;
 
 declare_clippy_lint! {
     /// **What it does:** Checks methods that contain a `self` argument but don't use it
 
 declare_lint_pass!(UnusedSelf => [UNUSED_SELF]);
 
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedSelf {
-    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &ImplItem<'_>) {
+impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
+    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &ImplItem<'_>) {
         if impl_item.span.from_expansion() {
             return;
         }
-        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id);
-        let item = cx.tcx.hir().expect_item(parent);
-        if let ItemKind::Impl {
-            of_trait: None,
-            items: impl_item_refs,
-            ..
-        } = item.kind
-        {
-            for impl_item_ref in impl_item_refs {
-                if_chain! {
-                    if let ImplItemRef {
-                        kind: AssocItemKind::Method { has_self: true },
-                        ..
-                    } = impl_item_ref;
-                    if let ImplItemKind::Method(_, body_id) = &impl_item.kind;
-                    let body = cx.tcx.hir().body(*body_id);
-                    if !body.params.is_empty();
-                    then {
-                        let self_param = &body.params[0];
-                        let self_hir_id = self_param.pat.hir_id;
-                        let mut visitor = UnusedSelfVisitor {
-                            cx,
-                            uses_self: false,
-                            self_hir_id: &self_hir_id,
-                        };
-                        visitor.visit_body(body);
-                        if !visitor.uses_self {
-                            span_lint_and_help(
-                                cx,
-                                UNUSED_SELF,
-                                self_param.span,
-                                "unused `self` argument",
-                                "consider refactoring to a associated function",
-                            );
-                            return;
-                        }
-                    }
+        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+        let parent_item = cx.tcx.hir().expect_item(parent);
+        let assoc_item = cx.tcx.associated_item(impl_item.def_id);
+        if_chain! {
+            if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
+            if assoc_item.fn_has_self_parameter;
+            if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
+            let body = cx.tcx.hir().body(*body_id);
+            if !body.params.is_empty();
+            then {
+                let self_param = &body.params[0];
+                let self_hir_id = self_param.pat.hir_id;
+                if !LocalUsedVisitor::new(cx, self_hir_id).check_body(body) {
+                    span_lint_and_help(
+                        cx,
+                        UNUSED_SELF,
+                        self_param.span,
+                        "unused `self` argument",
+                        None,
+                        "consider refactoring to a associated function",
+                    );
+                    return;
                 }
             }
-        };
-    }
-}
-
-struct UnusedSelfVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'a, 'tcx>,
-    uses_self: bool,
-    self_hir_id: &'a HirId,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for UnusedSelfVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
-    fn visit_path(&mut self, path: &'tcx Path<'_>, _id: HirId) {
-        if self.uses_self {
-            // This function already uses `self`
-            return;
-        }
-        if let Res::Local(hir_id) = &path.res {
-            self.uses_self = self.self_hir_id == hir_id
         }
-        walk_path(self, path);
-    }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
     }
 }