Summary
Our redundant-clone implementation currently does not track aliasing and therefore is blind to any cloning that is redundant.
@rustbot label +L-nursery +C-an-interesting-project +E-hard
(there are a bunch of issues regarding regarding this, but still I don't think anyone has identified the aliasing path)
Lint Name
redundant-clone
Reproducer
There are a bunch of more or less hidden cases that were discussed in either of these PRS:
The loop-cases which I AM missing (=not linting) are all closely related to aliasing
let mut x = black_box(String::new());
for _ in 0..10 {
let y = x; //~ redundant_clone
black_box(y);
x = black_box(String::new());
}
let mut x = black_box(String::new());
for _ in 0..10 {
let y = x.clone(); //~ redundant_clone
black_box(y);
x = black_box(String::new());
}
let mut x = black_box(String::new());
let mut y = black_box(String::new());
for _ in 0..10 {
y = x.clone(); //~ redundant_clone
x = black_box(String::new());
}
black_box(&x);
let mut x = black_box(String::new());
let mut y = x.clone(); //~ redundant_clone
for _ in 0..10 {
black_box(y);
x = black_box(String::new());
y = x.clone(); //~ redundant_clone
}
The interesting/hard part is that the aliasing rewrites can get a bit more tricky.
For example
fn used_after_merge(c: bool) {
let s = String::new();
- let t = s.clone(); // ok: `s` is used once the branches have merged
+ let t = s;
if c {
drop(t);
}
println!("{s}");
}
causes
error[E0382]: borrow of moved value: `s`
--> src/lib.rs:7:20
|
2 | let s = String::new();
| - move occurs because `s` has type `String`, which does not implement the `Copy` trait
3 | let t = s;
| - value moved here
...
7 | println!("{s}");
| ^ value borrowed here after move
|
help: consider cloning the value if the performance cost is acceptable
|
3 | let t = s.clone();
| ++++++++
but if we rewrite it like this (Since we know what ``dropdoes), it is fine.. As soon as you useblack_box` instead that's no longer true.
let s = String::new();
if c {}
println!("{s}");
Version
rustc 1.98.0 (88d9e12ae 2026-08-18)
binary: rustc
commit-hash: 88d9e12ae178fab0fb5cc050a94da85685d449ea
commit-date: 2026-08-18
host: x86_64-unknown-linux-gnu
release: 1.98.0
LLVM version: 22.1.8
Summary
Our
redundant-cloneimplementation currently does not track aliasing and therefore is blind to any cloning that is redundant.@rustbot label +L-nursery +C-an-interesting-project +E-hard
(there are a bunch of issues regarding regarding this, but still I don't think anyone has identified the aliasing path)
Lint Name
redundant-clone
Reproducer
There are a bunch of more or less hidden cases that were discussed in either of these PRS:
visit_local_usageanalyse loop bodies instead of giving up on them #17495redundant_cloneto an analysis pass take 2 #14599The loop-cases which I AM missing (=not linting) are all closely related to aliasing
The interesting/hard part is that the aliasing rewrites can get a bit more tricky.
For example
causes
but if we rewrite it like this (Since we know what ``drop
does), it is fine.. As soon as you useblack_box` instead that's no longer true.Version