From 2a9dec681fe8a7bd1985790fc70f671975c68da0 Mon Sep 17 00:00:00 2001 From: HMPerson1 Date: Fri, 19 Oct 2018 14:51:25 -0400 Subject: [PATCH] Fix suggestion for multiple derefs --- clippy_lints/src/methods/mod.rs | 15 +++++++++++++-- tests/ui/unnecessary_clone.rs | 32 +++++++++++++++++++++++++++++++ tests/ui/unnecessary_clone.stderr | 8 +++++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index a0d57e0916b..dd44aad351c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1250,7 +1250,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp if is_copy(cx, ty) { let snip; if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) { - // x.clone() might have dereferenced x, possibly through a Deref impl + // x.clone() might have dereferenced x, possibly through Deref impls if cx.tables.expr_ty(arg) != ty { let parent = cx.tcx.hir.get_parent_node(expr.id); match cx.tcx.hir.get(parent) { @@ -1273,7 +1273,18 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp }, _ => {}, } - snip = Some(("try dereferencing it", format!("{}", snippet.deref()))); + + let deref_count = cx.tables.expr_adjustments(arg).iter() + .filter(|adj| { + if let ty::adjustment::Adjust::Deref(_) = adj.kind { + true + } else { + false + } + }) + .count(); + let derefs: String = iter::repeat('*').take(deref_count).collect(); + snip = Some(("try dereferencing it", format!("{}{}", derefs, snippet))); } else { snip = Some(("try removing the `clone` call", format!("{}", snippet))); } diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 2dd2213e138..28cad1d881f 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -79,3 +79,35 @@ fn iter_clone_collect() { let v3 : HashSet = v.iter().cloned().collect(); let v4 : VecDeque = v.iter().cloned().collect(); } + +mod many_derefs { + struct A; + struct B; + struct C; + struct D; + #[derive(Copy, Clone)] + struct E; + + macro_rules! impl_deref { + ($src:ident, $dst:ident) => { + impl std::ops::Deref for $src { + type Target = $dst; + fn deref(&self) -> &Self::Target { &$dst } + } + } + } + + impl_deref!(A, B); + impl_deref!(B, C); + impl_deref!(C, D); + impl std::ops::Deref for D { + type Target = &'static E; + fn deref(&self) -> &Self::Target { &&E } + } + + fn go1() { + let a = A; + let _: E = a.clone(); + let _: E = *****a; + } +} diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 63e6f3d8bd5..5dcd5cae463 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -86,5 +86,11 @@ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec | = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` -error: aborting due to 12 previous errors +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:110:20 + | +110 | let _: E = a.clone(); + | ^^^^^^^^^ help: try dereferencing it: `*****a` + +error: aborting due to 13 previous errors