Skip to content

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

Description

@CommanderStorm

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

Metadata

Metadata

Assignees

Labels

C-an-interesting-projectCategory: Interesting projects, that usually are more involved design/code wise.C-bugCategory: Clippy is not doing the correct thingE-hardCall for participation: This a hard problem and requires more experience or effort to work onI-false-negativeIssue: The lint should have been triggered on code, but wasn'tL-nurseryLint: Currently in the nursery group

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions