about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThibsG <Thibs@debian.com>2020-08-24 14:01:27 +0200
committerThibsG <Thibs@debian.com>2020-08-24 14:05:49 +0200
commit3d820f71fe820c0bb7a1204e28ce549407a937cc (patch)
tree6bb5210b1dbb3010298079f8c7d96ae7d1f12503
parent27ae4d303ce9103a104c57088913741ab17f4d36 (diff)
downloadrust-3d820f71fe820c0bb7a1204e28ce549407a937cc.tar.gz
rust-3d820f71fe820c0bb7a1204e28ce549407a937cc.zip
Fix incorrect suggestion when `clone_on_ref_ptr` is triggered in macros
-rw-r--r--clippy_lints/src/methods/mod.rs13
-rw-r--r--tests/ui/unnecessary_clone.rs18
-rw-r--r--tests/ui/unnecessary_clone.stderr8
3 files changed, 32 insertions, 7 deletions
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 22942d9fb0c..4f0a533592c 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -2150,18 +2150,19 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::
             return;
         };
 
+        let snippet = if in_macro(arg.span) {
+            snippet_with_macro_callsite(cx, arg.span, "_")
+        } else {
+            snippet(cx, arg.span, "_")
+        };
+
         span_lint_and_sugg(
             cx,
             CLONE_ON_REF_PTR,
             expr.span,
             "using `.clone()` on a ref-counted pointer",
             "try this",
-            format!(
-                "{}::<{}>::clone(&{})",
-                caller_type,
-                subst.type_at(0),
-                snippet(cx, arg.span, "_")
-            ),
+            format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet),
             Applicability::Unspecified, // Sometimes unnecessary ::<_> after Rc/Arc/Weak
         );
     }
diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs
index 2c9d4d39e6c..e785ac02feb 100644
--- a/tests/ui/unnecessary_clone.rs
+++ b/tests/ui/unnecessary_clone.rs
@@ -90,3 +90,21 @@ mod many_derefs {
         let _ = &encoded.clone();
     }
 }
+
+mod issue2076 {
+    use std::rc::Rc;
+
+    macro_rules! try_opt {
+        ($expr: expr) => {
+            match $expr {
+                Some(value) => value,
+                None => return None,
+            }
+        };
+    }
+
+    fn func() -> Option<Rc<u8>> {
+        let rc = Rc::new(42);
+        Some(try_opt!(Some(rc)).clone())
+    }
+}
diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr
index 113fab69009..5ffa6c4fd06 100644
--- a/tests/ui/unnecessary_clone.stderr
+++ b/tests/ui/unnecessary_clone.stderr
@@ -96,5 +96,11 @@ help: or try being explicit if you are sure, that you want to clone a reference
 LL |         let _ = &<&[u8]>::clone(encoded);
    |                  ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 11 previous errors
+error: using `.clone()` on a ref-counted pointer
+  --> $DIR/unnecessary_clone.rs:108:14
+   |
+LL |         Some(try_opt!(Some(rc)).clone())
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Rc::<u8>::clone(&try_opt!(Some(rc)))`
+
+error: aborting due to 12 previous errors