about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2024-03-22 00:33:31 +0100
committerSamuel Tardieu <sam@rfc1149.net>2024-03-22 10:02:09 +0100
commit7c9fe30ce4313cc9e77030ca1e66a7c88a8ffd02 (patch)
tree560f40d698316be56977183811df62eb22a54532
parent9d6f41691ed9dbfaec2a2df2661c42451f2fe0d3 (diff)
downloadrust-7c9fe30ce4313cc9e77030ca1e66a7c88a8ffd02.tar.gz
rust-7c9fe30ce4313cc9e77030ca1e66a7c88a8ffd02.zip
Do not warn on .map(_::clone) for Arc, Rc, and their weak variants
Those constructions are idiomatic, and using `Arc::clone(x)` and
`Rc::clone(x)` is often the recommended way of cloning a `Arc` or a
`Rc`.
-rw-r--r--clippy_lints/src/methods/map_clone.rs5
-rw-r--r--tests/ui/map_clone.fixed24
-rw-r--r--tests/ui/map_clone.rs24
3 files changed, 53 insertions, 0 deletions
diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs
index c3c7a3a0033..749a31c8a91 100644
--- a/clippy_lints/src/methods/map_clone.rs
+++ b/clippy_lints/src/methods/map_clone.rs
@@ -124,6 +124,11 @@ fn handle_path(
             && let ty::Ref(_, ty, Mutability::Not) = ty.kind()
             && let ty::FnDef(_, lst) = cx.typeck_results().expr_ty(arg).kind()
             && lst.iter().all(|l| l.as_type() == Some(*ty))
+            && !matches!(
+                ty.ty_adt_def()
+                    .and_then(|adt_def| cx.tcx.get_diagnostic_name(adt_def.did())),
+                Some(sym::Arc | sym::ArcWeak | sym::Rc | sym::RcWeak)
+            )
         {
             lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs()));
         }
diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed
index e58b6b2f19e..f9f8dc1a512 100644
--- a/tests/ui/map_clone.fixed
+++ b/tests/ui/map_clone.fixed
@@ -131,4 +131,28 @@ fn main() {
         let x: Vec<&u8> = vec![];
         let y = x.into_iter().map(|x| u8::clone(loop {}));
     }
+
+    // Issue #12528
+    {
+        // Don't lint these
+        use std::rc::{Rc, Weak as RcWeak};
+        use std::sync::{Arc, Weak as ArcWeak};
+        struct Foo;
+
+        let x = Arc::new(Foo);
+        let y = Some(&x);
+        let _z = y.map(Arc::clone);
+
+        let x = Rc::new(Foo);
+        let y = Some(&x);
+        let _z = y.map(Rc::clone);
+
+        let x = Arc::downgrade(&Arc::new(Foo));
+        let y = Some(&x);
+        let _z = y.map(ArcWeak::clone);
+
+        let x = Rc::downgrade(&Rc::new(Foo));
+        let y = Some(&x);
+        let _z = y.map(RcWeak::clone);
+    }
 }
diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs
index e642e4046f8..a5c19ce0631 100644
--- a/tests/ui/map_clone.rs
+++ b/tests/ui/map_clone.rs
@@ -131,4 +131,28 @@ fn main() {
         let x: Vec<&u8> = vec![];
         let y = x.into_iter().map(|x| u8::clone(loop {}));
     }
+
+    // Issue #12528
+    {
+        // Don't lint these
+        use std::rc::{Rc, Weak as RcWeak};
+        use std::sync::{Arc, Weak as ArcWeak};
+        struct Foo;
+
+        let x = Arc::new(Foo);
+        let y = Some(&x);
+        let _z = y.map(Arc::clone);
+
+        let x = Rc::new(Foo);
+        let y = Some(&x);
+        let _z = y.map(Rc::clone);
+
+        let x = Arc::downgrade(&Arc::new(Foo));
+        let y = Some(&x);
+        let _z = y.map(ArcWeak::clone);
+
+        let x = Rc::downgrade(&Rc::new(Foo));
+        let y = Some(&x);
+        let _z = y.map(RcWeak::clone);
+    }
 }