rust-lang / rust-lang/rust-clippy

redundant-clone: doesn't see redundant clone when involving aliasing

Open
#17,637 1 comment 0 reactions 1 assignee View on GitHub

@saberoueslati is already working on this.

Since Aug 29, 2026.

C-an-interesting-project C-bug E-hard I-false-negative L-nursery
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.