Fixes #5405: redundant clone false positive with arrays

Check whether slice elements implement Copy before suggesting to drop
the clone method
This commit is contained in:
Rabi Guha 2020-04-12 15:25:47 +05:30
parent af5940b731
commit ab3946d7e9
4 changed files with 45 additions and 20 deletions

View file

@ -341,6 +341,9 @@ fn base_local_and_movability<'tcx>(
let mut deref = false;
// Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
let mut field = false;
// If projection is a slice index then clone can be removed only if the
// underlying type implements Copy
let mut slice = false;
let PlaceRef { local, mut projection } = place.as_ref();
while let [base @ .., elem] = projection {
@ -348,9 +351,11 @@ fn base_local_and_movability<'tcx>(
deref |= matches!(elem, mir::ProjectionElem::Deref);
field |= matches!(elem, mir::ProjectionElem::Field(..))
&& has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
slice |= matches!(elem, mir::ProjectionElem::Index(..))
&& !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
}
Some((local, deref || field))
Some((local, deref || field || slice))
}
struct LocalUseVisitor {

View file

@ -51,6 +51,7 @@ fn main() {
cannot_move_from_type_with_drop();
borrower_propagation();
not_consumed();
issue_5405();
}
#[derive(Clone)]
@ -160,3 +161,12 @@ fn not_consumed() {
println!("{}", x);
}
}
#[allow(clippy::clone_on_copy)]
fn issue_5405() {
let a: [String; 1] = [String::from("foo")];
let _b: String = a[0].clone();
let c: [usize; 2] = [2, 3];
let _d: usize = c[1].clone();
}

View file

@ -51,6 +51,7 @@ fn main() {
cannot_move_from_type_with_drop();
borrower_propagation();
not_consumed();
issue_5405();
}
#[derive(Clone)]
@ -160,3 +161,12 @@ fn not_consumed() {
println!("{}", x);
}
}
#[allow(clippy::clone_on_copy)]
fn issue_5405() {
let a: [String; 1] = [String::from("foo")];
let _b: String = a[0].clone();
let c: [usize; 2] = [2, 3];
let _d: usize = c[1].clone();
}

View file

@ -108,61 +108,61 @@ LL | let _t = tup.0.clone();
| ^^^^^
error: redundant clone
--> $DIR/redundant_clone.rs:60:22
--> $DIR/redundant_clone.rs:61:22
|
LL | (a.clone(), a.clone())
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> $DIR/redundant_clone.rs:60:21
--> $DIR/redundant_clone.rs:61:21
|
LL | (a.clone(), a.clone())
| ^
error: redundant clone
--> $DIR/redundant_clone.rs:120:15
|
LL | let _s = s.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> $DIR/redundant_clone.rs:120:14
|
LL | let _s = s.clone();
| ^
error: redundant clone
--> $DIR/redundant_clone.rs:121:15
|
LL | let _t = t.clone();
LL | let _s = s.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> $DIR/redundant_clone.rs:121:14
|
LL | let _s = s.clone();
| ^
error: redundant clone
--> $DIR/redundant_clone.rs:122:15
|
LL | let _t = t.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> $DIR/redundant_clone.rs:122:14
|
LL | let _t = t.clone();
| ^
error: redundant clone
--> $DIR/redundant_clone.rs:131:19
--> $DIR/redundant_clone.rs:132:19
|
LL | let _f = f.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> $DIR/redundant_clone.rs:131:18
--> $DIR/redundant_clone.rs:132:18
|
LL | let _f = f.clone();
| ^
error: redundant clone
--> $DIR/redundant_clone.rs:143:14
--> $DIR/redundant_clone.rs:144:14
|
LL | let y = x.clone().join("matthias");
| ^^^^^^^^ help: remove this
|
note: cloned value is neither consumed nor mutated
--> $DIR/redundant_clone.rs:143:13
--> $DIR/redundant_clone.rs:144:13
|
LL | let y = x.clone().join("matthias");
| ^^^^^^^^^