Skip to content

Commit aca64b8

Browse files
committed
Check for mutation
1 parent a377378 commit aca64b8

File tree

4 files changed

+27
-10
lines changed

4 files changed

+27
-10
lines changed

clippy_lints/src/redundant_clone.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
195195
let is_temp = mir_read_only.local_kind(ret_local) == mir::LocalKind::Temp;
196196

197197
// 1. `local` can be moved out if it is not used later.
198-
// 2. If `ret_local` is a temporary and is not consumed, we can remove this `clone` call anyway.
199-
let (used, consumed) = traversal::ReversePostorder::new(&mir, bb).skip(1).fold(
198+
// 2. If `ret_local` is a temporary and is neither consumed nor mutated, we can remove this `clone`
199+
// call anyway.
200+
let (used, consumed_or_mutated) = traversal::ReversePostorder::new(&mir, bb).skip(1).fold(
200201
(false, !is_temp),
201202
|(used, consumed), (tbb, tdata)| {
202203
// Short-circuit
@@ -209,14 +210,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
209210

210211
let mut vis = LocalUseVisitor {
211212
used: (local, false),
212-
consumed: (ret_local, false),
213+
consumed_or_mutated: (ret_local, false),
213214
};
214215
vis.visit_basic_block_data(tbb, tdata);
215-
(used || vis.used.1, consumed || vis.consumed.1)
216+
(used || vis.used.1, consumed || vis.consumed_or_mutated.1)
216217
},
217218
);
218219

219-
if !used || !consumed {
220+
if !used || !consumed_or_mutated {
220221
let span = terminator.source_info.span;
221222
let scope = terminator.source_info.scope;
222223
let node = mir.source_scopes[scope]
@@ -253,7 +254,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
253254
if used {
254255
db.span_note(
255256
span,
256-
"cloned value is not consumed",
257+
"cloned value is neither consumed nor mutated",
257258
);
258259
} else {
259260
db.span_note(
@@ -355,7 +356,7 @@ fn base_local_and_movability<'tcx>(
355356

356357
struct LocalUseVisitor {
357358
used: (mir::Local, bool),
358-
consumed: (mir::Local, bool),
359+
consumed_or_mutated: (mir::Local, bool),
359360
}
360361

361362
impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor {
@@ -381,8 +382,14 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor {
381382
self.used.1 = true;
382383
}
383384

384-
if *local == self.consumed.0 && matches!(ctx, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)) {
385-
self.consumed.1 = true;
385+
if *local == self.consumed_or_mutated.0 {
386+
match ctx {
387+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)
388+
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
389+
self.consumed_or_mutated.1 = true;
390+
},
391+
_ => {},
392+
}
386393
}
387394
}
388395
}

tests/ui/redundant_clone.fixed

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,9 @@ fn not_consumed() {
145145
// redundant. (It also does not consume the PathBuf)
146146

147147
println!("x: {:?}, y: {:?}", x, y);
148+
149+
let mut s = String::new();
150+
s.clone().push_str("foo"); // OK, removing this `clone()` will change the behavior.
151+
s.push_str("bar");
152+
assert_eq!(s, "bar");
148153
}

tests/ui/redundant_clone.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,9 @@ fn not_consumed() {
145145
// redundant. (It also does not consume the PathBuf)
146146

147147
println!("x: {:?}, y: {:?}", x, y);
148+
149+
let mut s = String::new();
150+
s.clone().push_str("foo"); // OK, removing this `clone()` will change the behavior.
151+
s.push_str("bar");
152+
assert_eq!(s, "bar");
148153
}

tests/ui/redundant_clone.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ error: redundant clone
161161
LL | let y = x.clone().join("matthias");
162162
| ^^^^^^^^ help: remove this
163163
|
164-
note: cloned value is not consumed
164+
note: cloned value is neither consumed nor mutated
165165
--> $DIR/redundant_clone.rs:143:13
166166
|
167167
LL | let y = x.clone().join("matthias");

0 commit comments

Comments
 (0)