about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2020-07-20 00:00:00 +0000
committerTomasz Miąsko <tomasz.miasko@gmail.com>2020-07-20 00:56:27 +0200
commita5cdd4aeb11fad6b0bf73d342398700a27c4484b (patch)
treee7c988d3b9b4ca6eb4f556a53134969f035d6f40
parent8cf4219c1673533eb5caf304237bffaa8e847067 (diff)
downloadrust-a5cdd4aeb11fad6b0bf73d342398700a27c4484b.tar.gz
rust-a5cdd4aeb11fad6b0bf73d342398700a27c4484b.zip
Ignore not really redundant clones of ManuallyDrop
"Redundant" clones of `ManuallyDrop` are sometimes used for the side effect of
invoking the clone, without running the drop implementation of the inner type.
In other words, they aren't really redundant. For example, futures-rs crate:

```rust
#[allow(clippy::redundant_clone)] // The clone here isn't actually redundant.
unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
    // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
    let arc = mem::ManuallyDrop::new(Arc::<T>::from_raw(data as *const T));
    // Now increase refcount, but don't drop new refcount either
    let _arc_clone: mem::ManuallyDrop<_> = arc.clone();
}
```

Ignore redundant clone lint for ManuallyDrop.
-rw-r--r--clippy_lints/src/redundant_clone.rs6
-rw-r--r--clippy_lints/src/utils/paths.rs1
-rw-r--r--tests/ui/redundant_clone.fixed15
-rw-r--r--tests/ui/redundant_clone.rs15
-rw-r--r--tests/ui/redundant_clone.stderr20
5 files changed, 47 insertions, 10 deletions
diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index fda7480194d..7932be0d4b1 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/clippy_lints/src/redundant_clone.rs
@@ -124,6 +124,12 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 continue;
             }
 
+            if let ty::Adt(ref def, _) = arg_ty.kind {
+                if match_def_path(cx, def.did, &paths::MEM_MANUALLY_DROP) {
+                    continue;
+                }
+            }
+
             // `{ cloned = &arg; clone(move cloned); }` or `{ cloned = &arg; to_path_buf(cloned); }`
             let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(cx, mir, arg, from_borrow, bb));
 
diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs
index 4c3462802e9..a515ee29c82 100644
--- a/clippy_lints/src/utils/paths.rs
+++ b/clippy_lints/src/utils/paths.rs
@@ -59,6 +59,7 @@ pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "Link
 pub const LINT: [&str; 3] = ["rustc_session", "lint", "Lint"];
 pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"];
 pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"];
+pub const MEM_MANUALLY_DROP: [&str; 4] = ["core", "mem", "manually_drop", "ManuallyDrop"];
 pub const MEM_MAYBEUNINIT: [&str; 4] = ["core", "mem", "maybe_uninit", "MaybeUninit"];
 pub const MEM_MAYBEUNINIT_UNINIT: [&str; 5] = ["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"];
 pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"];
diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed
index 764c10a6d39..cdeefda4c23 100644
--- a/tests/ui/redundant_clone.fixed
+++ b/tests/ui/redundant_clone.fixed
@@ -52,6 +52,7 @@ fn main() {
     borrower_propagation();
     not_consumed();
     issue_5405();
+    manually_drop();
 }
 
 #[derive(Clone)]
@@ -170,3 +171,17 @@ fn issue_5405() {
     let c: [usize; 2] = [2, 3];
     let _d: usize = c[1].clone();
 }
+
+fn manually_drop() {
+    use std::mem::ManuallyDrop;
+    use std::sync::Arc;
+
+    let a = ManuallyDrop::new(Arc::new("Hello!".to_owned()));
+    let _ = a.clone(); // OK
+
+    let p: *const String = Arc::into_raw(ManuallyDrop::into_inner(a));
+    unsafe {
+        Arc::from_raw(p);
+        Arc::from_raw(p);
+    }
+}
diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs
index 839747b131d..acb7ffb305f 100644
--- a/tests/ui/redundant_clone.rs
+++ b/tests/ui/redundant_clone.rs
@@ -52,6 +52,7 @@ fn main() {
     borrower_propagation();
     not_consumed();
     issue_5405();
+    manually_drop();
 }
 
 #[derive(Clone)]
@@ -170,3 +171,17 @@ fn issue_5405() {
     let c: [usize; 2] = [2, 3];
     let _d: usize = c[1].clone();
 }
+
+fn manually_drop() {
+    use std::mem::ManuallyDrop;
+    use std::sync::Arc;
+
+    let a = ManuallyDrop::new(Arc::new("Hello!".to_owned()));
+    let _ = a.clone(); // OK
+
+    let p: *const String = Arc::into_raw(ManuallyDrop::into_inner(a));
+    unsafe {
+        Arc::from_raw(p);
+        Arc::from_raw(p);
+    }
+}
diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr
index eced198283c..89b39254299 100644
--- a/tests/ui/redundant_clone.stderr
+++ b/tests/ui/redundant_clone.stderr
@@ -108,61 +108,61 @@ LL |     let _t = tup.0.clone();
    |              ^^^^^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:61:22
+  --> $DIR/redundant_clone.rs:62:22
    |
 LL |         (a.clone(), a.clone())
    |                      ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:61:21
+  --> $DIR/redundant_clone.rs:62:21
    |
 LL |         (a.clone(), a.clone())
    |                     ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:121:15
+  --> $DIR/redundant_clone.rs:122:15
    |
 LL |     let _s = s.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:121:14
+  --> $DIR/redundant_clone.rs:122:14
    |
 LL |     let _s = s.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:122:15
+  --> $DIR/redundant_clone.rs:123:15
    |
 LL |     let _t = t.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:122:14
+  --> $DIR/redundant_clone.rs:123:14
    |
 LL |     let _t = t.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:132:19
+  --> $DIR/redundant_clone.rs:133:19
    |
 LL |         let _f = f.clone();
    |                   ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:132:18
+  --> $DIR/redundant_clone.rs:133:18
    |
 LL |         let _f = f.clone();
    |                  ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:144:14
+  --> $DIR/redundant_clone.rs:145:14
    |
 LL |     let y = x.clone().join("matthias");
    |              ^^^^^^^^ help: remove this
    |
 note: cloned value is neither consumed nor mutated
-  --> $DIR/redundant_clone.rs:144:13
+  --> $DIR/redundant_clone.rs:145:13
    |
 LL |     let y = x.clone().join("matthias");
    |             ^^^^^^^^^