Skip to content

Commit 7e67f44

Browse files
committed
add suggestions to clone_on_copy
also: * don't report clone_on_copy when reporting clone_on_double_ref * don't suggest `((x))`
1 parent ac5abcf commit 7e67f44

File tree

3 files changed

+34
-14
lines changed

3 files changed

+34
-14
lines changed

clippy_lints/src/methods.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,7 @@ impl LateLintPass for Pass {
514514

515515
let self_ty = cx.tcx.expr_ty_adjusted(&args[0]);
516516
if args.len() == 1 && name.node.as_str() == "clone" {
517-
lint_clone_on_copy(cx, expr);
518-
lint_clone_double_ref(cx, expr, &args[0], self_ty);
517+
lint_clone_on_copy(cx, expr, &args[0], self_ty);
519518
}
520519

521520
match self_ty.sty {
@@ -703,19 +702,11 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
703702
}
704703

705704
/// Checks for the `CLONE_ON_COPY` lint.
706-
fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr) {
705+
fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: ty::Ty) {
707706
let ty = cx.tcx.expr_ty(expr);
708707
let parent = cx.tcx.map.get_parent(expr.id);
709708
let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent);
710-
711-
if !ty.moves_by_default(cx.tcx.global_tcx(), &parameter_environment, expr.span) {
712-
span_lint(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type");
713-
}
714-
}
715-
716-
/// Checks for the `CLONE_DOUBLE_REF` lint.
717-
fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty: ty::Ty) {
718-
if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = ty.sty {
709+
if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = arg_ty.sty {
719710
if let ty::TyRef(..) = inner.sty {
720711
span_lint_and_then(cx,
721712
CLONE_DOUBLE_REF,
@@ -725,8 +716,23 @@ fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty
725716
|db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
726717
db.span_suggestion(expr.span, "try dereferencing it", format!("({}).clone()", snip.deref()));
727718
});
719+
return; // don't report clone_on_copy
728720
}
729721
}
722+
723+
if !ty.moves_by_default(cx.tcx.global_tcx(), &parameter_environment, expr.span) {
724+
span_lint_and_then(cx,
725+
CLONE_ON_COPY,
726+
expr.span,
727+
"using `clone` on a `Copy` type",
728+
|db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
729+
if let ty::TyRef(..) = cx.tcx.expr_ty(arg).sty {
730+
db.span_suggestion(expr.span, "try dereferencing it", format!("{}", snip.deref()));
731+
} else {
732+
db.span_suggestion(expr.span, "try removing the `clone` call", format!("{}", snip));
733+
}
734+
});
735+
}
730736
}
731737

732738
fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) {

clippy_lints/src/utils/sugg.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,13 @@ impl<'a> Sugg<'a> {
161161
pub fn maybe_par(self) -> Self {
162162
match self {
163163
Sugg::NonParen(..) => self,
164-
Sugg::MaybeParen(sugg) | Sugg::BinOp(_, sugg) => Sugg::NonParen(format!("({})", sugg).into()),
164+
// (x) and (x).y() both don't need additional parens
165+
Sugg::MaybeParen(sugg) => if sugg.starts_with('(') && sugg.ends_with(')') {
166+
Sugg::MaybeParen(sugg)
167+
} else {
168+
Sugg::NonParen(format!("({})", sugg).into())
169+
},
170+
Sugg::BinOp(_, sugg) => Sugg::NonParen(format!("({})", sugg).into()),
165171
}
166172
}
167173
}

tests/compile-fail/methods.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,13 +435,22 @@ fn use_extend_from_slice() {
435435

436436
fn clone_on_copy() {
437437
42.clone(); //~ERROR using `clone` on a `Copy` type
438+
//~| HELP try removing the `clone` call
439+
//~| SUGGESTION 42
438440
vec![1].clone(); // ok, not a Copy type
439441
Some(vec![1]).clone(); // ok, not a Copy type
442+
(&42).clone(); //~ERROR using `clone` on a `Copy` type
443+
//~| HELP try dereferencing it
444+
//~| SUGGESTION *(&42)
440445
}
441446

442447
fn clone_on_copy_generic<T: Copy>(t: T) {
443448
t.clone(); //~ERROR using `clone` on a `Copy` type
449+
//~| HELP try removing the `clone` call
450+
//~| SUGGESTION t
444451
Some(t).clone(); //~ERROR using `clone` on a `Copy` type
452+
//~| HELP try removing the `clone` call
453+
//~| SUGGESTION Some(t)
445454
}
446455

447456
fn clone_on_double_ref() {
@@ -450,7 +459,6 @@ fn clone_on_double_ref() {
450459
let z: &Vec<_> = y.clone(); //~ERROR using `clone` on a double
451460
//~| HELP try dereferencing it
452461
//~| SUGGESTION let z: &Vec<_> = (*y).clone();
453-
//~^^^ERROR using `clone` on a `Copy` type
454462
println!("{:p} {:p}",*y, z);
455463
}
456464

0 commit comments

Comments
 (0)