]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/disallowed_methods.rs
Auto merge of #9148 - arieluy:then_some_unwrap_or, r=Jarcho
[rust.git] / clippy_lints / src / disallowed_methods.rs
index 6d4065907fb458da5ca256d4e1d0e22e9c20d6ab..53973ab792a91a50cb55da6c89e8e8d6cbdd5c69 100644 (file)
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::fn_def_id;
+use clippy_utils::{fn_def_id, get_parent_expr, path_def_id};
 
-use rustc_hir::{def::Res, def_id::DefIdMap, Expr};
+use rustc_hir::{def::Res, def_id::DefIdMap, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
@@ -11,6 +11,9 @@
     /// ### What it does
     /// Denies the configured methods and functions in clippy.toml
     ///
+    /// Note: Even though this lint is warn-by-default, it will only trigger if
+    /// methods are defined in the clippy.toml file.
+    ///
     /// ### Why is this bad?
     /// Some methods are undesirable in certain contexts, and it's beneficial to
     /// lint for them as needed.
     /// ```
     #[clippy::version = "1.49.0"]
     pub DISALLOWED_METHODS,
-    nursery,
+    style,
     "use of a disallowed method call"
 }
 
 #[derive(Clone, Debug)]
 pub struct DisallowedMethods {
     conf_disallowed: Vec<conf::DisallowedMethod>,
-    disallowed: DefIdMap<Option<String>>,
+    disallowed: DefIdMap<usize>,
 }
 
 impl DisallowedMethods {
@@ -72,35 +75,38 @@ pub fn new(conf_disallowed: Vec<conf::DisallowedMethod>) -> Self {
 
 impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
-        for conf in &self.conf_disallowed {
-            let (path, reason) = match conf {
-                conf::DisallowedMethod::Simple(path) => (path, None),
-                conf::DisallowedMethod::WithReason { path, reason } => (
-                    path,
-                    reason.as_ref().map(|reason| format!("{} (from clippy.toml)", reason)),
-                ),
-            };
-            let segs: Vec<_> = path.split("::").collect();
-            if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &segs) {
-                self.disallowed.insert(id, reason);
+        for (index, conf) in self.conf_disallowed.iter().enumerate() {
+            let segs: Vec<_> = conf.path().split("::").collect();
+            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs) {
+                self.disallowed.insert(id, index);
             }
         }
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        let def_id = match fn_def_id(cx, expr) {
+        let uncalled_path = if let Some(parent) = get_parent_expr(cx, expr)
+            && let ExprKind::Call(receiver, _) = parent.kind
+            && receiver.hir_id == expr.hir_id
+        {
+            None
+        } else {
+            path_def_id(cx, expr)
+        };
+        let def_id = match uncalled_path.or_else(|| fn_def_id(cx, expr)) {
             Some(def_id) => def_id,
             None => return,
         };
-        let reason = match self.disallowed.get(&def_id) {
-            Some(reason) => reason,
+        let conf = match self.disallowed.get(&def_id) {
+            Some(&index) => &self.conf_disallowed[index],
             None => return,
         };
-        let func_path = cx.tcx.def_path_str(def_id);
-        let msg = format!("use of a disallowed method `{}`", func_path);
+        let msg = format!("use of a disallowed method `{}`", conf.path());
         span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, &msg, |diag| {
-            if let Some(reason) = reason {
-                diag.note(reason);
+            if let conf::DisallowedMethod::WithReason {
+                reason: Some(reason), ..
+            } = conf
+            {
+                diag.note(&format!("{} (from clippy.toml)", reason));
             }
         });
     }