Skip to content

Commit 2a9dec6

Browse files
committed
Fix suggestion for multiple derefs
1 parent a2be050 commit 2a9dec6

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

clippy_lints/src/methods/mod.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp
12501250
if is_copy(cx, ty) {
12511251
let snip;
12521252
if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) {
1253-
// x.clone() might have dereferenced x, possibly through a Deref impl
1253+
// x.clone() might have dereferenced x, possibly through Deref impls
12541254
if cx.tables.expr_ty(arg) != ty {
12551255
let parent = cx.tcx.hir.get_parent_node(expr.id);
12561256
match cx.tcx.hir.get(parent) {
@@ -1273,7 +1273,18 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp
12731273
},
12741274
_ => {},
12751275
}
1276-
snip = Some(("try dereferencing it", format!("{}", snippet.deref())));
1276+
1277+
let deref_count = cx.tables.expr_adjustments(arg).iter()
1278+
.filter(|adj| {
1279+
if let ty::adjustment::Adjust::Deref(_) = adj.kind {
1280+
true
1281+
} else {
1282+
false
1283+
}
1284+
})
1285+
.count();
1286+
let derefs: String = iter::repeat('*').take(deref_count).collect();
1287+
snip = Some(("try dereferencing it", format!("{}{}", derefs, snippet)));
12771288
} else {
12781289
snip = Some(("try removing the `clone` call", format!("{}", snippet)));
12791290
}

tests/ui/unnecessary_clone.rs

+32
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,35 @@ fn iter_clone_collect() {
7979
let v3 : HashSet<isize> = v.iter().cloned().collect();
8080
let v4 : VecDeque<isize> = v.iter().cloned().collect();
8181
}
82+
83+
mod many_derefs {
84+
struct A;
85+
struct B;
86+
struct C;
87+
struct D;
88+
#[derive(Copy, Clone)]
89+
struct E;
90+
91+
macro_rules! impl_deref {
92+
($src:ident, $dst:ident) => {
93+
impl std::ops::Deref for $src {
94+
type Target = $dst;
95+
fn deref(&self) -> &Self::Target { &$dst }
96+
}
97+
}
98+
}
99+
100+
impl_deref!(A, B);
101+
impl_deref!(B, C);
102+
impl_deref!(C, D);
103+
impl std::ops::Deref for D {
104+
type Target = &'static E;
105+
fn deref(&self) -> &Self::Target { &&E }
106+
}
107+
108+
fn go1() {
109+
let a = A;
110+
let _: E = a.clone();
111+
let _: E = *****a;
112+
}
113+
}

tests/ui/unnecessary_clone.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,11 @@ error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec
8686
|
8787
= note: `-D clippy::iter-cloned-collect` implied by `-D warnings`
8888

89-
error: aborting due to 12 previous errors
89+
error: using `clone` on a `Copy` type
90+
--> $DIR/unnecessary_clone.rs:110:20
91+
|
92+
110 | let _: E = a.clone();
93+
| ^^^^^^^^^ help: try dereferencing it: `*****a`
94+
95+
error: aborting due to 13 previous errors
9096

0 commit comments

Comments
 (0)