about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Moelius <sam@moeli.us>2024-11-13 10:16:59 -0500
committerSamuel Moelius <sam@moeli.us>2024-11-15 17:37:10 -0500
commitd0f35777205090e24d5822e668cc280cab78e4ec (patch)
treef3ff1070975014212d9acf53a3edb7097094b939
parentf159a3eb1dfc3b81088fce364a09e8a79968adda (diff)
downloadrust-d0f35777205090e24d5822e668cc280cab78e4ec.tar.gz
rust-d0f35777205090e24d5822e668cc280cab78e4ec.zip
Properly handle `disallowed_types`
-rw-r--r--clippy_config/src/types.rs2
-rw-r--r--clippy_lints/src/disallowed_types.rs25
-rw-r--r--tests/ui-toml/replaceable_disallowed_types/clippy.toml3
-rw-r--r--tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.fixed16
-rw-r--r--tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.rs16
-rw-r--r--tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.stderr11
6 files changed, 58 insertions, 15 deletions
diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs
index 70d9073b59c..122fdca726d 100644
--- a/clippy_config/src/types.rs
+++ b/clippy_config/src/types.rs
@@ -47,7 +47,7 @@ impl DisallowedPath {
         }
     }
 
-    pub fn reason(&self) -> Option<&str> {
+    fn reason(&self) -> Option<&str> {
         match &self {
             Self::WithReason { reason, .. } => reason.as_deref(),
             Self::Simple(_) => None,
diff --git a/clippy_lints/src/disallowed_types.rs b/clippy_lints/src/disallowed_types.rs
index 3265404f2b2..a34ec4616e5 100644
--- a/clippy_lints/src/disallowed_types.rs
+++ b/clippy_lints/src/disallowed_types.rs
@@ -1,4 +1,5 @@
 use clippy_config::Conf;
+use clippy_config::types::DisallowedPath;
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::Res;
@@ -31,7 +32,8 @@ declare_clippy_lint! {
     ///     # When using an inline table, can add a `reason` for why the type
     ///     # is disallowed.
     ///     { path = "std::net::Ipv4Addr", reason = "no IPv4 allowed" },
-    /// ]
+    ///     # Can also add a `replacement` that will be offered as a suggestion.
+    ///     { path = "std::sync::Mutex", reason = "prefer faster & simpler non-poisonable mutex", replacement = "parking_lot::Mutex" },    /// ]
     /// ```
     ///
     /// ```rust,ignore
@@ -51,24 +53,23 @@ declare_clippy_lint! {
 }
 
 pub struct DisallowedTypes {
-    def_ids: DefIdMap<(&'static str, Option<&'static str>)>,
-    prim_tys: FxHashMap<PrimTy, (&'static str, Option<&'static str>)>,
+    def_ids: DefIdMap<(&'static str, &'static DisallowedPath)>,
+    prim_tys: FxHashMap<PrimTy, (&'static str, &'static DisallowedPath)>,
 }
 
 impl DisallowedTypes {
     pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
         let mut def_ids = DefIdMap::default();
         let mut prim_tys = FxHashMap::default();
-        for x in &conf.disallowed_types {
-            let path: Vec<_> = x.path().split("::").collect::<Vec<_>>();
-            let reason = x.reason();
+        for disallowed_path in &conf.disallowed_types {
+            let path: Vec<_> = disallowed_path.path().split("::").collect::<Vec<_>>();
             for res in clippy_utils::def_path_res(tcx, &path) {
                 match res {
                     Res::Def(_, id) => {
-                        def_ids.insert(id, (x.path(), reason));
+                        def_ids.insert(id, (disallowed_path.path(), disallowed_path));
                     },
                     Res::PrimTy(ty) => {
-                        prim_tys.insert(ty, (x.path(), reason));
+                        prim_tys.insert(ty, (disallowed_path.path(), disallowed_path));
                     },
                     _ => {},
                 }
@@ -78,7 +79,7 @@ impl DisallowedTypes {
     }
 
     fn check_res_emit(&self, cx: &LateContext<'_>, res: &Res, span: Span) {
-        let (path, reason) = match res {
+        let (path, disallowed_path) = match res {
             Res::Def(_, did) if let Some(&x) = self.def_ids.get(did) => x,
             Res::PrimTy(prim) if let Some(&x) = self.prim_tys.get(prim) => x,
             _ => return,
@@ -88,11 +89,7 @@ impl DisallowedTypes {
             DISALLOWED_TYPES,
             span,
             format!("use of a disallowed type `{path}`"),
-            |diag| {
-                if let Some(reason) = reason {
-                    diag.note(reason);
-                }
-            },
+            disallowed_path.diag_amendment(span),
         );
     }
 }
diff --git a/tests/ui-toml/replaceable_disallowed_types/clippy.toml b/tests/ui-toml/replaceable_disallowed_types/clippy.toml
new file mode 100644
index 00000000000..a08a2f00f50
--- /dev/null
+++ b/tests/ui-toml/replaceable_disallowed_types/clippy.toml
@@ -0,0 +1,3 @@
+disallowed-types = [
+    { path = "std::string::String", replacement = "wrapper::String" },
+]
diff --git a/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.fixed b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.fixed
new file mode 100644
index 00000000000..6546981bd81
--- /dev/null
+++ b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.fixed
@@ -0,0 +1,16 @@
+#![warn(clippy::disallowed_types)]
+
+#[allow(clippy::disallowed_types)]
+mod wrapper {
+    pub struct String(std::string::String);
+
+    impl From<&str> for String {
+        fn from(value: &str) -> Self {
+            Self(std::string::String::from(value))
+        }
+    }
+}
+
+fn main() {
+    let _ = wrapper::String::from("x");
+}
diff --git a/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.rs b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.rs
new file mode 100644
index 00000000000..d76f1af481d
--- /dev/null
+++ b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.rs
@@ -0,0 +1,16 @@
+#![warn(clippy::disallowed_types)]
+
+#[allow(clippy::disallowed_types)]
+mod wrapper {
+    pub struct String(std::string::String);
+
+    impl From<&str> for String {
+        fn from(value: &str) -> Self {
+            Self(std::string::String::from(value))
+        }
+    }
+}
+
+fn main() {
+    let _ = String::from("x");
+}
diff --git a/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.stderr b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.stderr
new file mode 100644
index 00000000000..bb63e6970a1
--- /dev/null
+++ b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.stderr
@@ -0,0 +1,11 @@
+error: use of a disallowed type `std::string::String`
+  --> tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.rs:15:13
+   |
+LL |     let _ = String::from("x");
+   |             ^^^^^^ help: use: `wrapper::String`
+   |
+   = note: `-D clippy::disallowed-types` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::disallowed_types)]`
+
+error: aborting due to 1 previous error
+