about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-11-11 00:48:33 +0000
committerbors <bors@rust-lang.org>2020-11-11 00:48:33 +0000
commitc4fc076e11b7125d481ee96df6d2e0c4ed493356 (patch)
tree4a6ec1d234a1318e56288b9ba8f4b5212a3915d2
parentd0858d0f36cc43c348a2da73a68b5931b37b82d5 (diff)
parent769094410a22849c426972dd421a1937463a48e7 (diff)
downloadrust-c4fc076e11b7125d481ee96df6d2e0c4ed493356.tar.gz
rust-c4fc076e11b7125d481ee96df6d2e0c4ed493356.zip
Auto merge of #6269 - camsteffen:map-clone-deref, r=ebroto
Fix map_clone with deref and clone

changelog: Fix map_clone false positive with deref coercion

Fixes #6239
-rw-r--r--clippy_lints/src/map_clone.rs14
-rw-r--r--tests/ui/map_clone.fixed7
-rw-r--r--tests/ui/map_clone.rs7
3 files changed, 23 insertions, 5 deletions
diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs
index 9a00608ce39..3f34dd5112e 100644
--- a/clippy_lints/src/map_clone.rs
+++ b/clippy_lints/src/map_clone.rs
@@ -8,6 +8,7 @@ use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty;
+use rustc_middle::ty::adjustment::Adjust;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span};
@@ -75,11 +76,14 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
                                     }
                                 }
                             },
-                            hir::ExprKind::MethodCall(ref method, _, ref obj, _) => {
-                                if ident_eq(name, &obj[0]) && method.ident.as_str() == "clone"
-                                    && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {
-
-                                    let obj_ty = cx.typeck_results().expr_ty(&obj[0]);
+                            hir::ExprKind::MethodCall(ref method, _, [obj], _) => if_chain! {
+                                if ident_eq(name, obj) && method.ident.name == sym::clone;
+                                if match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT);
+                                // no autoderefs
+                                if !cx.typeck_results().expr_adjustments(obj).iter()
+                                    .any(|a| matches!(a.kind, Adjust::Deref(Some(..))));
+                                then {
+                                    let obj_ty = cx.typeck_results().expr_ty(obj);
                                     if let ty::Ref(_, ty, mutability) = obj_ty.kind() {
                                         if matches!(mutability, Mutability::Not) {
                                             let copy = is_copy(cx, ty);
diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed
index ce92b3c0c30..178d8705c2f 100644
--- a/tests/ui/map_clone.fixed
+++ b/tests/ui/map_clone.fixed
@@ -53,4 +53,11 @@ fn main() {
         let items = vec![&mut aa, &mut bb];
         let _: Vec<_> = items.into_iter().map(|x| x.clone()).collect();
     }
+
+    // Issue #6239 deref coercion and clone deref
+    {
+        use std::cell::RefCell;
+
+        let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone());
+    }
 }
diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs
index 324c776c3c9..c73d81713b8 100644
--- a/tests/ui/map_clone.rs
+++ b/tests/ui/map_clone.rs
@@ -53,4 +53,11 @@ fn main() {
         let items = vec![&mut aa, &mut bb];
         let _: Vec<_> = items.into_iter().map(|x| x.clone()).collect();
     }
+
+    // Issue #6239 deref coercion and clone deref
+    {
+        use std::cell::RefCell;
+
+        let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone());
+    }
 }